From 2debc3587af32790afa36a1b90657445e8b25e36 Mon Sep 17 00:00:00 2001 From: syoul Date: Mon, 23 Mar 2026 22:18:15 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20crossfade=20simplifi=C3=A9=20=E2=80=94?= =?UTF-8?q?=20canvas=20toujours=20visible,=20seul=20l'overlay=20se=20disso?= =?UTF-8?q?ut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le canvas reste toujours à opacity 1. Quand les transactions changent : 1. Capture le canvas dans l'overlay img (snap à opacity 1 sans transition) 2. Met à jour le canvas en dessous 3. Double rAF pour laisser Leaflet.heat redessiner 4. Dissout l'overlay de 1→0 en 500ms via CSS transition Élimine le double-affichage et les conflits de transition canvas/overlay. Co-Authored-By: Claude Sonnet 4.6 --- src/components/HeatMap.tsx | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/components/HeatMap.tsx b/src/components/HeatMap.tsx index 64148f7..86831f2 100644 --- a/src/components/HeatMap.tsx +++ b/src/components/HeatMap.tsx @@ -91,12 +91,7 @@ export function HeatMap({ transactions }: HeatMapProps) { return; } - // 1. Cancel any running overlay transition instantly (flush only the overlay) - overlay.style.transition = 'none'; - overlay.style.opacity = '0'; - void overlay.offsetWidth; // flush overlay only — avoids double-paint with canvas - - // 2. Capture current frame (canvas still visible at opacity 1) + // 1. Freeze previous frame in overlay (canvas still at opacity 1) try { overlay.src = canvas.toDataURL(); } catch { @@ -104,22 +99,19 @@ export function HeatMap({ transactions }: HeatMapProps) { return; } - // 3. In one paint batch: hide canvas + show overlay (Frame A moves from canvas to overlay) - canvas.style.transition = 'none'; - canvas.style.opacity = '0'; + // 2. Snap overlay visible — cancel any running transition first + overlay.style.transition = 'none'; + void overlay.offsetWidth; // flush overlay.style.opacity = '1'; - // 4. Update heatmap (invisible: canvas at opacity 0) + // 3. Update canvas underneath (canvas always at opacity 1, covered by overlay) update(); - // 5. Simultaneous crossfade: overlay fades out, canvas fades in + // 4. After Leaflet redraws: dissolve overlay away, revealing new frame const raf = requestAnimationFrame(() => { requestAnimationFrame(() => { - const DURATION = '0.5s ease-in-out'; - overlay.style.transition = `opacity ${DURATION}`; + overlay.style.transition = 'opacity 0.5s ease-in-out'; overlay.style.opacity = '0'; - canvas.style.transition = `opacity ${DURATION}`; - canvas.style.opacity = '1'; }); });