fix: vrai crossfade simultané — canvas fade-in + overlay fade-out en même temps
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
Avant : overlay se dissout mais le canvas apparaît instantanément en dessous. Maintenant : canvas part à opacity 0, les deux transitions démarrent en même temps → ancienne frame fade out pendant que la nouvelle fade in simultanément. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -65,7 +65,7 @@ export function HeatMap({ transactions }: HeatMapProps) {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Crossfade: capture current heatmap → update underneath → fade out overlay
|
// True crossfade: old frame (overlay) fades out WHILE new frame (canvas) fades in simultaneously
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!heatRef.current || !mapRef.current) return;
|
if (!heatRef.current || !mapRef.current) return;
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ export function HeatMap({ transactions }: HeatMapProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Freeze previous frame in overlay (canvas still at opacity 1)
|
// 1. Capture old frame into overlay
|
||||||
try {
|
try {
|
||||||
overlay.src = canvas.toDataURL();
|
overlay.src = canvas.toDataURL();
|
||||||
} catch {
|
} catch {
|
||||||
@@ -99,18 +99,27 @@ export function HeatMap({ transactions }: HeatMapProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Snap overlay visible — cancel any running transition first
|
// 2. Snap overlay to visible, cancel any running transition
|
||||||
overlay.style.transition = 'none';
|
overlay.style.transition = 'none';
|
||||||
void overlay.offsetWidth; // flush
|
|
||||||
overlay.style.opacity = '1';
|
overlay.style.opacity = '1';
|
||||||
|
|
||||||
// 3. Update canvas underneath (canvas always at opacity 1, covered by overlay)
|
// 3. Hide canvas (new frame will fade in from here)
|
||||||
|
canvas.style.transition = 'none';
|
||||||
|
canvas.style.opacity = '0';
|
||||||
|
|
||||||
|
// flush both
|
||||||
|
void overlay.offsetWidth;
|
||||||
|
|
||||||
|
// 4. Draw new data onto canvas (invisible at opacity 0)
|
||||||
update();
|
update();
|
||||||
|
|
||||||
// 4. After Leaflet redraws: dissolve overlay away, revealing new frame
|
// 5. Simultaneously: canvas fades in, overlay fades out → true crossfade
|
||||||
const raf = requestAnimationFrame(() => {
|
const raf = requestAnimationFrame(() => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
overlay.style.transition = 'opacity 0.5s ease-in-out';
|
const DURATION = '0.55s ease-in-out';
|
||||||
|
canvas.style.transition = `opacity ${DURATION}`;
|
||||||
|
canvas.style.opacity = '1';
|
||||||
|
overlay.style.transition = `opacity ${DURATION}`;
|
||||||
overlay.style.opacity = '0';
|
overlay.style.opacity = '0';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user