fix: align race story cursor to chart

This commit is contained in:
2026-07-12 16:11:26 -04:00
parent 08ff75b469
commit 0a42c05487
2 changed files with 29 additions and 1 deletions

View File

@@ -417,7 +417,10 @@ export function RaceStoryCanvas({ data }: Props) {
clearChapterSelection() clearChapterSelection()
if (!svgRef.current) return if (!svgRef.current) return
const rect = svgRef.current.getBoundingClientRect() const rect = svgRef.current.getBoundingClientRect()
const x = e.clientX - rect.left if (rect.width <= 0) return
// Pointer coordinates are CSS pixels; convert them to the SVG viewBox
// before comparing with the fixed chart margins and plot width.
const x = ((e.clientX - rect.left) / rect.width) * W
const t = Math.max(0, Math.min(1, (x - PL) / plotW)) const t = Math.max(0, Math.min(1, (x - PL) / plotW))
setScrubTime(t) setScrubTime(t)
} }
@@ -595,6 +598,7 @@ export function RaceStoryCanvas({ data }: Props) {
width={plotW} width={plotW}
height={plotH} height={plotH}
fill="transparent" fill="transparent"
data-testid="position-chart-interaction"
onPointerMove={handlePointerMove} onPointerMove={handlePointerMove}
onPointerLeave={() => { onPointerLeave={() => {
if (!isPlaying) { if (!isPlaying) {

View File

@@ -206,6 +206,30 @@ describe('RaceStoryCanvas replay map', () => {
expect(document.querySelector('.rs-driver-line')).toHaveAttribute('points', '40,8 592,8 592,8') expect(document.querySelector('.rs-driver-line')).toHaveAttribute('points', '40,8 592,8 592,8')
}) })
it('maps cursor positions from rendered pixels to the SVG viewBox', () => {
renderCanvas()
const svg = document.querySelector('.rs-position-chart-svg')!
vi.spyOn(svg, 'getBoundingClientRect').mockReturnValue({
x: 0,
y: 0,
width: 1280,
height: 360,
top: 0,
right: 1280,
bottom: 360,
left: 0,
toJSON: () => ({}),
})
const pointerMove = new Event('pointermove', { bubbles: true })
Object.defineProperty(pointerMove, 'clientX', { value: 640 })
fireEvent(screen.getByTestId('position-chart-interaction'), pointerMove)
// 640px is the middle of a 1280px rendered chart, which is x=320 in its 640-unit viewBox.
expect(document.querySelector('.rs-playhead')).toHaveAttribute('x1', '320')
})
it('syncs active chapter highlight when a chapter card is clicked', async () => { it('syncs active chapter highlight when a chapter card is clicked', async () => {
renderCanvas() renderCanvas()