Borner la barre de comparaison hors du panneau et des outils, poignée au-dessus du volet
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -525,6 +525,20 @@ def test_ui_compare_mode_replaces_both():
|
|||||||
assert "'both'" in parse and "'relief'" in parse
|
assert "'both'" in parse and "'relief'" in parse
|
||||||
assert "#compareBar" in _MAP_CSS and "touch-action: none" in _MAP_CSS
|
assert "#compareBar" in _MAP_CSS and "touch-action: none" in _MAP_CSS
|
||||||
|
|
||||||
|
# La poignée reste hors du panneau et de la colonne d'outils : séparation
|
||||||
|
# affichée bornée (barre et découpe ensemble), y compris en glissant, et
|
||||||
|
# recalculée quand le panneau change de largeur.
|
||||||
|
assert "function compareBounds(" in _MAP_JS
|
||||||
|
bounds = _MAP_JS[_MAP_JS.index("function compareBounds("):_MAP_JS.index("function applyCompareClip(")]
|
||||||
|
assert "el('panel').getBoundingClientRect()" in bounds and "el('tools').getBoundingClientRect()" in bounds
|
||||||
|
clip = _MAP_JS[_MAP_JS.index("function applyCompareClip("):_MAP_JS.index("(function compareDrag(")]
|
||||||
|
assert "compareBounds()" in clip
|
||||||
|
drag = _MAP_JS[_MAP_JS.index("(function compareDrag("):]
|
||||||
|
assert "compareBounds()" in drag[:drag.index("})();")]
|
||||||
|
assert "document.addEventListener('panel:tab', applyCompareClip)" in _MAP_JS
|
||||||
|
# Poignée centrée sur la carte visible au-dessus du volet (téléphone)
|
||||||
|
assert "top: calc((100% - var(--sheet-h)) / 2)" in _MAP_CSS
|
||||||
|
|
||||||
|
|
||||||
def test_ui_applies_server_defaults():
|
def test_ui_applies_server_defaults():
|
||||||
"""L'interface part des défauts du serveur et sait les (re)définir."""
|
"""L'interface part des défauts du serveur et sait les (re)définir."""
|
||||||
|
|||||||
@ -60,7 +60,9 @@ html, body { height: 100%; overflow: hidden; background: var(--bg); color: var(-
|
|||||||
/* Mode Comparer : barre glissante qui sépare les deux couches. */
|
/* Mode Comparer : barre glissante qui sépare les deux couches. */
|
||||||
#compareBar { position: fixed; top: 0; bottom: 0; width: 4px; margin-left: -2px; z-index: var(--z-map-ui);
|
#compareBar { position: fixed; top: 0; bottom: 0; width: 4px; margin-left: -2px; z-index: var(--z-map-ui);
|
||||||
background: var(--surface); box-shadow: var(--shadow-sm); cursor: ew-resize; touch-action: none; }
|
background: var(--surface); box-shadow: var(--shadow-sm); cursor: ew-resize; touch-action: none; }
|
||||||
#compareBar span { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
/* Poignée au milieu de la carte visible, au-dessus du volet (téléphone) : à
|
||||||
|
mi-hauteur de l'écran elle tombait sous l'échelle Leaflet posée sur le volet. */
|
||||||
|
#compareBar span { position: absolute; top: calc((100% - var(--sheet-h)) / 2); left: 50%; transform: translate(-50%, -50%);
|
||||||
width: 36px; height: 36px; border-radius: var(--r-full); display: flex; align-items: center;
|
width: 36px; height: 36px; border-radius: var(--r-full); display: flex; align-items: center;
|
||||||
justify-content: center; background: var(--surface); color: var(--text); border: 1px solid var(--border);
|
justify-content: center; background: var(--surface); color: var(--text); border: 1px solid var(--border);
|
||||||
box-shadow: var(--shadow-sm); font-size: var(--fs-lg); }
|
box-shadow: var(--shadow-sm); font-size: var(--fs-lg); }
|
||||||
|
|||||||
@ -425,15 +425,36 @@ function applyLayers() {
|
|||||||
updateRose();
|
updateRose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Plage de la séparation, en px du conteneur de la carte : la poignée reste
|
||||||
|
// dans la partie visible de la carte, jamais sous le panneau (ordinateur :
|
||||||
|
// panneau ouvert ou bande d'icônes, toute la hauteur) ni sous la colonne
|
||||||
|
// d'outils. COMPARE_MARGIN = demi-largeur de la poignée + marge.
|
||||||
|
const COMPARE_MARGIN = 24;
|
||||||
|
function compareBounds() {
|
||||||
|
const r = map.getContainer().getBoundingClientRect();
|
||||||
|
let min = COMPARE_MARGIN, max = r.width - COMPARE_MARGIN;
|
||||||
|
if (!isPhone()) {
|
||||||
|
min = Math.max(min, el('panel').getBoundingClientRect().right - r.left + COMPARE_MARGIN);
|
||||||
|
max = Math.min(max, el('tools').getBoundingClientRect().left - r.left - COMPARE_MARGIN);
|
||||||
|
}
|
||||||
|
// Fenêtre trop étroite : la séparation reste au milieu de la plage.
|
||||||
|
if (min > max) min = max = (min + max) / 2;
|
||||||
|
return { left: r.left, min, max };
|
||||||
|
}
|
||||||
|
|
||||||
// Découpe des couches de part et d'autre de la barre, en coordonnées de
|
// Découpe des couches de part et d'autre de la barre, en coordonnées de
|
||||||
// calque (les conteneurs de tuiles se déplacent avec la carte) : recalculée
|
// calque (les conteneurs de tuiles se déplacent avec la carte) : recalculée
|
||||||
// à chaque déplacement. Même couche des deux côtés : aucune découpe.
|
// à chaque déplacement. Même couche des deux côtés : aucune découpe.
|
||||||
|
// STATE.compare.pos garde la valeur demandée (lien, glisser) ; la séparation
|
||||||
|
// affichée, barre et découpe ensemble, est bornée à compareBounds().
|
||||||
function applyCompareClip() {
|
function applyCompareClip() {
|
||||||
if (!STATE) return;
|
if (!STATE) return;
|
||||||
const on = effectiveMode() === 'compare';
|
const on = effectiveMode() === 'compare';
|
||||||
el('compareBar').hidden = !on;
|
el('compareBar').hidden = !on;
|
||||||
const size = map.getSize();
|
const size = map.getSize();
|
||||||
const x = size.x * (on ? STATE.compare.pos : 50) / 100;
|
let x = size.x * (on ? STATE.compare.pos : 50) / 100;
|
||||||
|
const bounds = on ? compareBounds() : null;
|
||||||
|
if (bounds) x = Math.min(bounds.max, Math.max(bounds.min, x));
|
||||||
const nw = map.containerPointToLayerPoint([0, 0]);
|
const nw = map.containerPointToLayerPoint([0, 0]);
|
||||||
const se = map.containerPointToLayerPoint(size);
|
const se = map.containerPointToLayerPoint(size);
|
||||||
const cx = map.containerPointToLayerPoint([x, 0]).x;
|
const cx = map.containerPointToLayerPoint([x, 0]).x;
|
||||||
@ -448,13 +469,12 @@ function applyCompareClip() {
|
|||||||
}
|
}
|
||||||
c.style.clipPath = clip;
|
c.style.clipPath = clip;
|
||||||
}
|
}
|
||||||
if (on) {
|
if (on) el('compareBar').style.left = (bounds.left + x) + 'px';
|
||||||
const r = map.getContainer().getBoundingClientRect();
|
|
||||||
el('compareBar').style.left = (r.left + x) + 'px';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
map.on('move', applyCompareClip);
|
map.on('move', applyCompareClip);
|
||||||
map.on('resize zoomend', applyCompareClip);
|
map.on('resize zoomend', applyCompareClip);
|
||||||
|
// Panneau replié, déplié, volet redimensionné : la plage de la barre change.
|
||||||
|
document.addEventListener('panel:tab', applyCompareClip);
|
||||||
|
|
||||||
(function compareDrag() {
|
(function compareDrag() {
|
||||||
const bar = el('compareBar');
|
const bar = el('compareBar');
|
||||||
@ -462,8 +482,9 @@ map.on('resize zoomend', applyCompareClip);
|
|||||||
bar.addEventListener('pointerdown', (e) => { dragging = true; bar.setPointerCapture(e.pointerId); e.preventDefault(); });
|
bar.addEventListener('pointerdown', (e) => { dragging = true; bar.setPointerCapture(e.pointerId); e.preventDefault(); });
|
||||||
bar.addEventListener('pointermove', (e) => {
|
bar.addEventListener('pointermove', (e) => {
|
||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
const r = map.getContainer().getBoundingClientRect();
|
const b = compareBounds();
|
||||||
STATE.compare.pos = Math.min(95, Math.max(5, 100 * (e.clientX - r.left) / r.width));
|
const x = Math.min(b.max, Math.max(b.min, e.clientX - b.left));
|
||||||
|
STATE.compare.pos = Math.min(95, Math.max(5, 100 * x / map.getSize().x));
|
||||||
applyCompareClip();
|
applyCompareClip();
|
||||||
});
|
});
|
||||||
const end = () => { if (dragging) { dragging = false; saveState(); } };
|
const end = () => { if (dragging) { dragging = false; saveState(); } };
|
||||||
|
|||||||
Reference in New Issue
Block a user