fix: éliminer le double affichage du crossfade
ci/woodpecker/push/woodpecker Pipeline was successful

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 <noreply@anthropic.com>
This commit is contained in:
syoul
2026-03-23 22:07:34 +01:00
parent a9bf445747
commit 8a31b60716
+9 -7
View File
@@ -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';