fix(resultat): le marqueur du joueur reste visible, marqueur reel + ligne + etiquette distance + fitBounds (comparaison visuelle facon GeoGuessr)

This commit is contained in:
sucupira
2026-07-16 23:45:17 -04:00
parent 2f8867497a
commit 19b83159a9
4 changed files with 40 additions and 27 deletions
+34 -27
View File
@@ -23,6 +23,7 @@
interface Props {
guess?: Coordonnees | null;
real?: Coordonnees | null;
distanceKm?: number | null;
interactive?: boolean;
pairs?: Paire[];
markers?: MarqueurInfo[];
@@ -34,6 +35,7 @@
let {
guess = $bindable(null),
real = null,
distanceKm = null,
interactive = true,
pairs = [],
markers = [],
@@ -48,7 +50,6 @@
let guessMarker: Marker | null = null;
let realMarker: Marker | null = null;
let explorerMarkers: Marker[] = [];
let raf = 0;
const SRC_LIGNE = 'jwe-ligne';
const SRC_PAIRES = 'jwe-paires';
@@ -100,39 +101,47 @@
id: 'jwe-ligne-line',
type: 'line',
source: SRC_LIGNE,
filter: ['==', ['geometry-type'], 'LineString'],
paint: { 'line-color': '#e4572e', 'line-width': 3, 'line-dasharray': [2, 1.5] }
});
map.addLayer({
id: 'jwe-ligne-label',
type: 'symbol',
source: SRC_LIGNE,
filter: ['==', ['geometry-type'], 'Point'],
layout: {
'text-field': ['get', 'etiquette'],
'text-size': 14,
'text-font': ['Noto Sans Regular'],
'text-offset': [0, -1.4]
},
paint: { 'text-color': '#0b3d2e', 'text-halo-color': '#fffdf8', 'text-halo-width': 2 }
});
}
const features: GeoJSON.Feature[] = [];
if (guess) {
features.push(ligneFeature(guess, real, null));
if (distanceKm !== null) {
// Étiquette de distance au milieu de la ligne guess ↔ réel
features.push(
pointFeature(
{ lat: (guess.lat + real.lat) / 2, lon: (guess.lon + real.lon) / 2 },
{ etiquette: `${distanceKm} km` }
)
);
}
}
const features: GeoJSON.Feature[] = guess ? [ligneFeature(guess, real, null)] : [];
setGeoJSON(SRC_LIGNE, { type: 'FeatureCollection', features });
// Marqueur vert = position réelle
// Marqueur vert = position réelle ; le marqueur corail du joueur RESTE
// à sa position : la comparaison visuelle guess ↔ réel est le cœur du jeu.
realMarker?.remove();
realMarker = new ml.Marker({ color: '#0b3d2e' }).setLngLat([real.lon, real.lat]).addTo(map);
// Le marqueur du joueur « vole » vers la position réelle (sauf reduced-motion)
if (guessMarker && guess) {
const from = { ...guess };
if (reducedMotion) {
guessMarker.setLngLat([real.lon, real.lat]);
} else {
const debut = performance.now();
const duree = 1400;
const step = (now: number) => {
if (!guessMarker) return;
const k = Math.min(1, (now - debut) / duree);
const e = 1 - Math.pow(1 - k, 3);
guessMarker.setLngLat([
from.lon + (real.lon - from.lon) * e,
from.lat + (real.lat - from.lat) * e
]);
if (k < 1) raf = requestAnimationFrame(step);
};
raf = requestAnimationFrame(step);
}
if (guess) {
const bounds = new ml.LngLatBounds(
[Math.min(from.lon, real.lon), Math.min(from.lat, real.lat)],
[Math.max(from.lon, real.lon), Math.max(from.lat, real.lat)]
[Math.min(guess.lon, real.lon), Math.min(guess.lat, real.lat)],
[Math.max(guess.lon, real.lon), Math.max(guess.lat, real.lat)]
);
map.fitBounds(bounds, { padding: 80, duration: reducedMotion ? 0 : 900, maxZoom: 12 });
} else {
@@ -141,7 +150,6 @@
}
function nettoyerRevelation(): void {
cancelAnimationFrame(raf);
realMarker?.remove();
realMarker = null;
setGeoJSON(SRC_LIGNE, { type: 'FeatureCollection', features: [] });
@@ -311,7 +319,6 @@
})();
return () => {
detruit = true;
cancelAnimationFrame(raf);
map?.remove();
map = null;
};