From 8a41aa77819d141bc3e6cb6b481e2420b11f391e Mon Sep 17 00:00:00 2001 From: c0mrade Date: Mon, 1 Jun 2026 16:24:02 +0300 Subject: [PATCH] fix(wheel): kill the center-line LED artifact during spin (drop CSS blur filter) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rim lights are static cx/cy SVG circles; their glow used a CSS filter:blur(2px). During the spin the wheel's transform transition promotes the SVG to a GPU layer, and Chrome mis-renders CSS filters on geometry-positioned SVG elements — the blurs streak toward the view-box origin, drawing a line of lights through the centre. Replace the blur with a soft radial-gradient fill (no filter, so the artefact can't occur). Also drive both the chase speed and the per-dot delay from one --led-dur var so the chase stays in order at the faster spin speed instead of scrambling (the delay was a fixed 6s value that broke once the duration dropped to 2s). --- src/components/wheel/FortuneWheel.tsx | 52 +++++++++++++++------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/components/wheel/FortuneWheel.tsx b/src/components/wheel/FortuneWheel.tsx index 4563a27..10adacc 100644 --- a/src/components/wheel/FortuneWheel.tsx +++ b/src/components/wheel/FortuneWheel.tsx @@ -206,6 +206,17 @@ const FortuneWheel = memo(function FortuneWheel({ + + {/* LED glow as a soft radial gradient instead of a CSS blur filter. + A `filter: blur()` on cx/cy-positioned SVG circles mis-renders under + GPU compositing during the spin — the blurs streak toward the + view-box origin and draw a line of lights through the centre. A + gradient fill needs no filter, so that artefact can't occur. */} + + + + + {/* Background shadow */} @@ -242,10 +253,20 @@ const FortuneWheel = memo(function FortuneWheel({ 0%, 100% { opacity: 0; } 10%, 30% { opacity: 0.4; } } - .led-dot { animation: ledChase 6s linear infinite; } - .led-glow { opacity: 0; animation: ledGlow 6s linear infinite; } - .led-spinning .led-dot { animation-duration: 2s; } - .led-spinning .led-glow { animation-duration: 2s; } + /* --led-dur drives both the speed and the per-dot delay, so they + scale together and the chase stays in order at the faster spin + speed (the delay used to be a fixed 6s value, which scrambled + the order once the duration dropped to 2s). */ + .led-dot, .led-glow { + --led-dur: 6s; + animation-duration: var(--led-dur); + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-delay: calc(var(--led-i, 0) / 20 * var(--led-dur)); + } + .led-dot { animation-name: ledChase; } + .led-glow { opacity: 0; animation-name: ledGlow; } + .led-spinning .led-dot, .led-spinning .led-glow { --led-dur: 2s; } `} @@ -254,26 +275,11 @@ const FortuneWheel = memo(function FortuneWheel({ const ledRadius = outerRadius + 3; const dotX = center + ledRadius * Math.cos(angle); const dotY = center + ledRadius * Math.sin(angle); - // Delay as fraction of full cycle — CSS handles speed via animation-duration - const delay = `${(i / 20) * 6}s`; return ( - - - + // --led-i (dot index) drives the staggered chase delay in CSS + + + ); })}