refactor: align mobile sign and pole marker styles and grouping logic with desktop view
This commit is contained in:
parent
534488814a
commit
3f75b511f2
1 changed files with 95 additions and 52 deletions
|
|
@ -285,8 +285,8 @@
|
||||||
|
|
||||||
/* Marqueur spécifique panneau de signalisation (sans cercle bleu/blanc) */
|
/* Marqueur spécifique panneau de signalisation (sans cercle bleu/blanc) */
|
||||||
.asset-map-marker-sign {
|
.asset-map-marker-sign {
|
||||||
width: 32px;
|
width: 22px;
|
||||||
height: 32px;
|
height: 22px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -299,37 +299,46 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
.asset-map-marker-sign::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -4px;
|
||||||
|
bottom: -4px;
|
||||||
|
left: -4px;
|
||||||
|
right: -4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
.asset-map-marker-sign img {
|
.asset-map-marker-sign img {
|
||||||
width: 30px;
|
width: 20px;
|
||||||
height: 30px;
|
height: 20px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
display: block;
|
display: block;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.45));
|
filter: drop-shadow(0 1px 3px rgba(0,0,0,0.45));
|
||||||
transition: transform 0.15s ease;
|
transition: transform 0.15s ease;
|
||||||
}
|
}
|
||||||
.asset-map-marker-sign:hover img, .asset-map-marker-sign:active img {
|
.asset-map-marker-sign:hover img, .asset-map-marker-sign:active img {
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
filter: drop-shadow(0 3px 8px rgba(0,0,0,0.6));
|
filter: drop-shadow(0 2px 6px rgba(0,0,0,0.6));
|
||||||
}
|
}
|
||||||
.asset-map-marker-sign i {
|
.asset-map-marker-sign i {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 28px;
|
width: 18px;
|
||||||
height: 28px;
|
height: 18px;
|
||||||
border-radius: 4px;
|
border-radius: 3px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: 2px solid #0022ff;
|
border: 1.5px solid #2563eb;
|
||||||
color: #0022ff;
|
color: #2563eb;
|
||||||
font-size: 1rem;
|
font-size: 0.65rem;
|
||||||
box-shadow: 0 1px 4px rgba(0,0,0,0.35);
|
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: transform 0.15s ease;
|
transition: transform 0.15s ease;
|
||||||
}
|
}
|
||||||
.asset-map-marker-sign:hover i, .asset-map-marker-sign:active i {
|
.asset-map-marker-sign:hover i, .asset-map-marker-sign:active i {
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.5);
|
box-shadow: 0 2px 6px rgba(0,0,0,0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Marqueur spécifique poteau de signalisation (symbole desktop : socle circulaire + tige verticale) */
|
/* Marqueur spécifique poteau de signalisation (symbole desktop : socle circulaire + tige verticale) */
|
||||||
|
|
@ -359,8 +368,8 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.asset-map-marker-pole .pole-base {
|
.asset-map-marker-pole .pole-base {
|
||||||
width: 10px;
|
width: 8px;
|
||||||
height: 10px;
|
height: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #888888;
|
background-color: #888888;
|
||||||
border: 1.5px solid #333333;
|
border: 1.5px solid #333333;
|
||||||
|
|
@ -378,7 +387,7 @@
|
||||||
bottom: 50%;
|
bottom: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 3.5px;
|
width: 2.5px;
|
||||||
background-color: #555555;
|
background-color: #555555;
|
||||||
border-left: 0.5px solid #222222;
|
border-left: 0.5px solid #222222;
|
||||||
border-right: 0.5px solid #222222;
|
border-right: 0.5px solid #222222;
|
||||||
|
|
@ -465,24 +474,24 @@
|
||||||
}
|
}
|
||||||
.asset-map-marker-sign.selected img {
|
.asset-map-marker-sign.selected img {
|
||||||
transform: scale(1.25);
|
transform: scale(1.25);
|
||||||
filter: drop-shadow(0 0 5px #eab308) drop-shadow(0 0 10px #fde047) drop-shadow(0 3px 6px rgba(0,0,0,0.5)) !important;
|
filter: drop-shadow(0 0 5px #eab308) drop-shadow(0 0 10px #fde047) drop-shadow(0 2px 5px rgba(0,0,0,0.5)) !important;
|
||||||
}
|
}
|
||||||
.asset-map-marker-sign.selected i {
|
.asset-map-marker-sign.selected i {
|
||||||
border-color: #ca8a04;
|
border-color: #ca8a04;
|
||||||
color: #854d0e;
|
color: #854d0e;
|
||||||
transform: scale(1.2);
|
transform: scale(1.2);
|
||||||
box-shadow: 0 0 10px rgba(234, 179, 8, 0.85);
|
box-shadow: 0 0 8px rgba(234, 179, 8, 0.85);
|
||||||
}
|
}
|
||||||
.asset-map-marker-sign.selected::after {
|
.asset-map-marker-sign.selected::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -6px;
|
top: -4px;
|
||||||
left: -6px;
|
left: -4px;
|
||||||
right: -6px;
|
right: -4px;
|
||||||
bottom: -6px;
|
bottom: -4px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 2.5px solid #eab308;
|
border: 2px solid #eab308;
|
||||||
box-shadow: 0 0 10px rgba(234, 179, 8, 0.85);
|
box-shadow: 0 0 8px rgba(234, 179, 8, 0.85);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
animation: marker-selected-pulse 1.8s infinite ease-in-out;
|
animation: marker-selected-pulse 1.8s infinite ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
@ -1505,17 +1514,52 @@
|
||||||
const group = [asset];
|
const group = [asset];
|
||||||
processedSet.add(key);
|
processedSet.add(key);
|
||||||
|
|
||||||
|
const isAssetPole = asset.model_key && asset.model_key.includes('pole');
|
||||||
|
|
||||||
punctualAssets.forEach(other => {
|
punctualAssets.forEach(other => {
|
||||||
const otherKey = String(other.feature_id || `${other.model_key}_${other.id}`);
|
const otherKey = String(other.feature_id || `${other.model_key}_${other.id}`);
|
||||||
if (processedSet.has(otherKey)) return;
|
if (processedSet.has(otherKey)) return;
|
||||||
|
|
||||||
const samePole = (other.pole_id && asset.pole_id && String(other.pole_id) === String(asset.pole_id))
|
const isOtherPole = other.model_key && other.model_key.includes('pole');
|
||||||
|| (asset.model_key && asset.model_key.includes('pole') && String(other.pole_id) === String(asset.id))
|
|
||||||
|| (other.model_key && other.model_key.includes('pole') && String(asset.pole_id) === String(other.id));
|
|
||||||
|
|
||||||
const dLon = Math.abs(other.lon - asset.lon);
|
// Règle 1 : Deux poteaux distincts ne doivent JAMAIS être fusionnés
|
||||||
const dLat = Math.abs(other.lat - asset.lat);
|
if (isAssetPole && isOtherPole && String(asset.id) !== String(other.id)) {
|
||||||
const isSameLocation = samePole || (dLon < 0.00005 && dLat < 0.00005);
|
return;
|
||||||
|
}
|
||||||
|
// Règle 2 : Deux panneaux rattachés à des poteaux différents ne doivent JAMAIS être fusionnés
|
||||||
|
if (asset.pole_id && other.pole_id && String(asset.pole_id) !== String(other.pole_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Règle 3 : Un panneau et un poteau distinct ne doivent JAMAIS être fusionnés
|
||||||
|
if (isAssetPole && other.pole_id && String(asset.id) !== String(other.pole_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isOtherPole && asset.pole_id && String(other.id) !== String(asset.pole_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const samePole = (other.pole_id && asset.pole_id && String(other.pole_id) === String(asset.pole_id))
|
||||||
|
|| (isAssetPole && String(other.pole_id) === String(asset.id))
|
||||||
|
|| (isOtherPole && String(asset.pole_id) === String(other.id));
|
||||||
|
|
||||||
|
const isSignRelated = isAssetPole || isOtherPole || asset.model_key === 'signpanel' || other.model_key === 'signpanel' || !!asset.pole_id || !!other.pole_id;
|
||||||
|
|
||||||
|
let isSameLocation = false;
|
||||||
|
if (isSignRelated) {
|
||||||
|
// Pour les panneaux et poteaux, regrouper uniquement si même poteau
|
||||||
|
// ou si coordonnées strictement identiques (< 1m) pour panneaux sans pole_id
|
||||||
|
if (samePole) {
|
||||||
|
isSameLocation = true;
|
||||||
|
} else if (!asset.pole_id && !other.pole_id && !isAssetPole && !isOtherPole && asset.model_key === 'signpanel' && other.model_key === 'signpanel') {
|
||||||
|
const dLon = Math.abs(other.lon - asset.lon);
|
||||||
|
const dLat = Math.abs(other.lat - asset.lat);
|
||||||
|
isSameLocation = (dLon < 0.000015 && dLat < 0.000015);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const dLon = Math.abs(other.lon - asset.lon);
|
||||||
|
const dLat = Math.abs(other.lat - asset.lat);
|
||||||
|
isSameLocation = (dLon < 0.000015 && dLat < 0.000015);
|
||||||
|
}
|
||||||
|
|
||||||
if (isSameLocation) {
|
if (isSameLocation) {
|
||||||
group.push(other);
|
group.push(other);
|
||||||
|
|
@ -1547,11 +1591,22 @@
|
||||||
|
|
||||||
// CAS A : Emplacement avec un ou plusieurs panneaux de signalisation
|
// CAS A : Emplacement avec un ou plusieurs panneaux de signalisation
|
||||||
if (signPanels.length > 0) {
|
if (signPanels.length > 0) {
|
||||||
// 1. S'il y a un poteau ou support à la base, le positionner à l'offset [0, 0]
|
// Trier pour identifier si un poteau ou support est présent
|
||||||
if (otherAssets.length > 0) {
|
const poleAsset = otherAssets.find(a => a.model_key === 'signpole' || (a.model_key && a.model_key.includes('pole')) || (a.thematic === 'sign' && a.model_key && a.model_key.includes('pole')));
|
||||||
otherAssets.sort((a, b) => getDisplayPriority(b) - getDisplayPriority(a));
|
const baseAsset = poleAsset || (otherAssets.length > 0 ? otherAssets[0] : null);
|
||||||
const baseAsset = otherAssets[0];
|
|
||||||
|
|
||||||
|
const hasBaseSupport = !!baseAsset;
|
||||||
|
const N = signPanels.length;
|
||||||
|
const highestPanelIndex = Math.max(0, N - 1);
|
||||||
|
|
||||||
|
// Dimensions compactes identiques à la vue desktop :
|
||||||
|
// Centre du panneau le plus bas à -14px au-dessus du sol/socle
|
||||||
|
// Incrément de 14px pour chaque panneau supplémentaire sur le mât
|
||||||
|
const stemHeight = hasBaseSupport ? (16 + (highestPanelIndex * 14)) : 0;
|
||||||
|
const topOffset = -(14 + (highestPanelIndex * 14));
|
||||||
|
|
||||||
|
// 1. S'il y a un poteau ou support à la base, le positionner à l'offset [0, 0]
|
||||||
|
if (baseAsset) {
|
||||||
const symbology = (typeof AssetSymbology !== 'undefined')
|
const symbology = (typeof AssetSymbology !== 'undefined')
|
||||||
? AssetSymbology.getAssetSymbology(baseAsset)
|
? AssetSymbology.getAssetSymbology(baseAsset)
|
||||||
: { color: THEMATIC_COLORS[baseAsset.thematic] || '#888888', iconClass: baseAsset.thematic_icon || 'bi-signpost-split' };
|
: { color: THEMATIC_COLORS[baseAsset.thematic] || '#888888', iconClass: baseAsset.thematic_icon || 'bi-signpost-split' };
|
||||||
|
|
@ -1565,8 +1620,6 @@
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
if (isSignPole) {
|
if (isSignPole) {
|
||||||
el.className = 'asset-map-marker-pole';
|
el.className = 'asset-map-marker-pole';
|
||||||
const highestPanelIndex = Math.max(0, signPanels.length - 1);
|
|
||||||
const stemHeight = 36 + (highestPanelIndex * 34);
|
|
||||||
el.innerHTML = `<div class="pole-stem" style="height: ${stemHeight}px;"></div><div class="pole-base"></div>`;
|
el.innerHTML = `<div class="pole-stem" style="height: ${stemHeight}px;"></div><div class="pole-base"></div>`;
|
||||||
el.style.zIndex = '2';
|
el.style.zIndex = '2';
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1627,22 +1680,12 @@
|
||||||
return (orderA - orderB) || (Number(a.id) - Number(b.id));
|
return (orderA - orderB) || (Number(a.id) - Number(b.id));
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasBaseSupport = otherAssets.length > 0;
|
|
||||||
const N = signPanels.length;
|
|
||||||
const highestPanelIndex = Math.max(0, N - 1);
|
|
||||||
// Le sommet de la tige du poteau (topOffset)
|
|
||||||
// Si support à la base : le panneau le plus bas a son centre à -36px (garde de ~20px au-dessus du socle)
|
|
||||||
// et chaque panneau au-dessus ajoute 34px.
|
|
||||||
// Le panneau au sommet (index 0, vertical_order = 1) est à topOffset.
|
|
||||||
// Chaque panneau suivant (index i) est positionné sous le précédent : topOffset + (i * 34).
|
|
||||||
const topOffset = hasBaseSupport ? -(36 + (highestPanelIndex * 34)) : -(highestPanelIndex * 34);
|
|
||||||
|
|
||||||
// Coordonnées de référence partagées pour l'alignement parfait sur la tige
|
// Coordonnées de référence partagées pour l'alignement parfait sur la tige
|
||||||
const refLon = hasBaseSupport ? otherAssets[0].lon : (signPanels[0].lon);
|
const refLon = baseAsset ? baseAsset.lon : signPanels[0].lon;
|
||||||
const refLat = hasBaseSupport ? otherAssets[0].lat : (signPanels[0].lat);
|
const refLat = baseAsset ? baseAsset.lat : signPanels[0].lat;
|
||||||
|
|
||||||
signPanels.forEach((panel, index) => {
|
signPanels.forEach((panel, index) => {
|
||||||
const panelOffset = topOffset + (index * 34);
|
const panelOffset = topOffset + (index * 14);
|
||||||
|
|
||||||
const symbology = (typeof AssetSymbology !== 'undefined')
|
const symbology = (typeof AssetSymbology !== 'undefined')
|
||||||
? AssetSymbology.getAssetSymbology(panel)
|
? AssetSymbology.getAssetSymbology(panel)
|
||||||
|
|
@ -1684,7 +1727,7 @@
|
||||||
activeMarkers.push(marker);
|
activeMarkers.push(marker);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// CAS B : Emplacement sans panneau (arbres, bancs, corbeilles, etc.)
|
// CAS B : Emplacement sans panneau (arbres, bancs, corbeilles, poteau seul, etc.)
|
||||||
group.sort((a, b) => getDisplayPriority(b) - getDisplayPriority(a));
|
group.sort((a, b) => getDisplayPriority(b) - getDisplayPriority(a));
|
||||||
const primaryAsset = group[0];
|
const primaryAsset = group[0];
|
||||||
|
|
||||||
|
|
@ -1701,7 +1744,7 @@
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
if (isSignPole) {
|
if (isSignPole) {
|
||||||
el.className = 'asset-map-marker-pole';
|
el.className = 'asset-map-marker-pole';
|
||||||
el.innerHTML = '<div class="pole-stem" style="height: 28px;"></div><div class="pole-base"></div>';
|
el.innerHTML = '<div class="pole-stem" style="height: 16px;"></div><div class="pole-base"></div>';
|
||||||
el.style.zIndex = '5';
|
el.style.zIndex = '5';
|
||||||
} else {
|
} else {
|
||||||
el.className = 'asset-map-marker';
|
el.className = 'asset-map-marker';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue