[auto] pulse target arrow on step detection for visual feedback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>main
parent
dbc259c3b4
commit
f22de64108
|
|
@ -77,6 +77,16 @@
|
|||
padding: 4px;
|
||||
}
|
||||
|
||||
.ag-target-pulse {
|
||||
animation: target-beat 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes target-beat {
|
||||
0% { transform: translateX(-50%) scale(1); opacity: 0.5; filter: drop-shadow(0 0 0px white); }
|
||||
30% { transform: translateX(-50%) scale(1.4); opacity: 1; filter: drop-shadow(0 0 20px white); }
|
||||
100% { transform: translateX(-50%) scale(1); opacity: 0.35; filter: drop-shadow(0 0 0px white); }
|
||||
}
|
||||
|
||||
/* Scrolling arrows */
|
||||
.ag-arrow {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export const ArrowGame = forwardRef<ArrowGameHandle, Props>(({ active = true, on
|
|||
const [score, setScore] = useState({ perfect: 0, good: 0, miss: 0, combo: 0 })
|
||||
const [judgment, setJudgment] = useState<{ text: string; key: number } | null>(null)
|
||||
const judgmentTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const [targetPulse, setTargetPulse] = useState<{ dir: ArrowDirection; key: number } | null>(null)
|
||||
|
||||
const showJudgment = useCallback((text: string) => {
|
||||
if (judgmentTimer.current) clearTimeout(judgmentTimer.current)
|
||||
|
|
@ -61,6 +62,7 @@ export const ArrowGame = forwardRef<ArrowGameHandle, Props>(({ active = true, on
|
|||
handleStep(stepDir: StepDirection) {
|
||||
const dir = STEP_TO_ARROW[stepDir]
|
||||
const now = performance.now()
|
||||
setTargetPulse({ dir, key: now })
|
||||
|
||||
let best: GameArrow | null = null
|
||||
let bestDelta = Infinity
|
||||
|
|
@ -183,7 +185,11 @@ export const ArrowGame = forwardRef<ArrowGameHandle, Props>(({ active = true, on
|
|||
|
||||
<div className="ag-targets">
|
||||
{DIRECTIONS.map(dir => (
|
||||
<div key={dir} className="ag-target" style={{ left: LANE_X[dir] }}>
|
||||
<div
|
||||
key={targetPulse?.dir === dir ? `${dir}-${targetPulse.key}` : dir}
|
||||
className={`ag-target${targetPulse?.dir === dir ? ' ag-target-pulse' : ''}`}
|
||||
style={{ left: LANE_X[dir] }}
|
||||
>
|
||||
<Arrow direction={dir} />
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Reference in New Issue