From 8a31b607167dbd0716be0ab1ba234a7e7b041cc4 Mon Sep 17 00:00:00 2001 From: syoul Date: Mon, 23 Mar 2026 22:07:34 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20=C3=A9liminer=20le=20double=20affichage?= =?UTF-8?q?=20du=20crossfade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problème : void canvas.offsetWidth forçait un repaint avec canvas ET overlay potentiellement visibles en même temps. Fix : flusher uniquement l'overlay (void overlay.offsetWidth), puis appliquer canvas=0 + overlay=1 dans le même batch de paint — Frame A passe du canvas à l'overlay en un seul rendu sans doublon. Co-Authored-By: Claude Sonnet 4.6 --- src/components/HeatMap.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/HeatMap.tsx b/src/components/HeatMap.tsx index ef12da7..64148f7 100644 --- a/src/components/HeatMap.tsx +++ b/src/components/HeatMap.tsx @@ -91,26 +91,28 @@ export function HeatMap({ transactions }: HeatMapProps) { return; } - // 2. Freeze current frame in the overlay + // 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) try { overlay.src = canvas.toDataURL(); } catch { - // canvas tainted (shouldn't happen with heatmap-only canvas) update(); return; } - // 1. Reset transitions instantly — force reflow to flush any running transition + // 3. In one paint batch: hide canvas + show overlay (Frame A moves from canvas to overlay) canvas.style.transition = 'none'; - overlay.style.transition = 'none'; - void canvas.offsetWidth; // force reflow canvas.style.opacity = '0'; overlay.style.opacity = '1'; - // 3. Update heatmap (invisible: canvas still at opacity 0) + // 4. Update heatmap (invisible: canvas at opacity 0) update(); - // 4. Simultaneous crossfade: overlay fades out, canvas fades in + // 5. Simultaneous crossfade: overlay fades out, canvas fades in const raf = requestAnimationFrame(() => { requestAnimationFrame(() => { const DURATION = '0.5s ease-in-out';