feat: fondu entre les frames de l'animation heatmap
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
Fade out 250ms → mise à jour des données → fade in 250ms sur le canvas Leaflet.heat. Aucun état React supplémentaire — manipulation directe du canvas interne via _canvas. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -64,25 +64,40 @@ export function HeatMap({ transactions }: HeatMapProps) {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Update heatmap data when transactions change
|
// Update heatmap data with fade transition when transactions change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!heatRef.current || !mapRef.current) return;
|
if (!heatRef.current || !mapRef.current) return;
|
||||||
|
|
||||||
// Normalize amounts for intensity (log scale feels better visually)
|
const canvas = (heatRef.current as unknown as { _canvas?: HTMLCanvasElement })._canvas;
|
||||||
const maxAmount = Math.max(...transactions.map((t) => t.amount), 1);
|
|
||||||
|
|
||||||
|
const update = () => {
|
||||||
|
const maxAmount = Math.max(...transactions.map((t) => t.amount), 1);
|
||||||
const points: L.HeatLatLngTuple[] = transactions.map((tx) => [
|
const points: L.HeatLatLngTuple[] = transactions.map((tx) => [
|
||||||
tx.lat,
|
tx.lat,
|
||||||
tx.lng,
|
tx.lng,
|
||||||
Math.min(Math.log1p(tx.amount) / Math.log1p(maxAmount), 1),
|
Math.min(Math.log1p(tx.amount) / Math.log1p(maxAmount), 1),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Guard: only update if the heat layer is still attached to the map
|
|
||||||
try {
|
try {
|
||||||
heatRef.current.setLatLngs(points);
|
heatRef.current?.setLatLngs(points);
|
||||||
} catch {
|
} catch {
|
||||||
// map was torn down (React StrictMode double-invoke), ignore
|
// map was torn down (React StrictMode double-invoke), ignore
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!canvas) {
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.style.transition = 'opacity 0.25s ease-in-out';
|
||||||
|
canvas.style.opacity = '0';
|
||||||
|
|
||||||
|
const t = setTimeout(() => {
|
||||||
|
update();
|
||||||
|
canvas.style.opacity = '1';
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
return () => clearTimeout(t);
|
||||||
}, [transactions]);
|
}, [transactions]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user