Skip to content

Commit 1affea7

Browse files
committed
fix(web): stop wheel spinner drift on slow photo load
Shrink the wheel crop radius (34→28) so the crop stays strictly on the rim face; larger radii dragged the tire's baked-in lighting/aero deflector around the hub, reading as a wobbling second wheel. Also gate the entry spin animation on photo load timing: if the vehicle photo arrives more than 700ms after mount, the drive-in slide has already finished, so skip the spin instead of playing it against an already-parked car.
1 parent d9d7c92 commit 1affea7

1 file changed

Lines changed: 17 additions & 4 deletions

File tree

web/src/components/vehicles/VehicleTwin.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,11 @@ function PhotoWheelSpinner({
12421242
driveIn: boolean;
12431243
driving: boolean;
12441244
}) {
1245-
const R = 34; // crop radius in viewBox units — covers the rim, stays on the tire
1245+
// Crop radius in viewBox units. Must stay strictly on the rim face:
1246+
// anything larger drags the tire's baked-in lighting — and, on the front
1247+
// wheel, the dark aero deflector ahead of the tire — around the hub,
1248+
// which reads as a wobbling second wheel.
1249+
const R = 28;
12461250
const size = 2 * R * u;
12471251
const left = (cx - R) * u;
12481252
const top = (WHEEL_CY - R - VIEWBOX_MIN_Y) * u;
@@ -1430,6 +1434,12 @@ export function VehicleTwin({
14301434
const photoUrl = useMemo(() => buildCompositorUrl(paint.id, model), [paint.id, model]);
14311435
const photoOn = photoState === 'ready';
14321436

1437+
// Entry spin only makes sense while the drive-in slide is still running.
1438+
// If the photo arrives late (slow network), the car is already parked —
1439+
// spinning the wheels then would look broken.
1440+
const [mountedAt] = useState(() => performance.now());
1441+
const [entrySpinOk, setEntrySpinOk] = useState(false);
1442+
14331443

14341444
// Align the photo with the SVG overlay: the twin geometry was traced from
14351445
// this exact render, so image carLeft..carRight ↔ viewBox x 43..556 and
@@ -1488,7 +1498,10 @@ export function VehicleTwin({
14881498
aria-hidden="true"
14891499
draggable={false}
14901500
style={imgStyle}
1491-
onLoad={() => setPhotoState('ready')}
1501+
onLoad={() => {
1502+
setPhotoState('ready');
1503+
setEntrySpinOk(performance.now() - mountedAt < 700);
1504+
}}
14921505
onError={() => setPhotoState('failed')}
14931506
/>
14941507
)}
@@ -1501,7 +1514,7 @@ export function VehicleTwin({
15011514
imgLeft={imgLeft}
15021515
imgTop={imgTop}
15031516
photoUrl={photoUrl}
1504-
driveIn={driveIn}
1517+
driveIn={driveIn && entrySpinOk}
15051518
driving={isDriving}
15061519
/>
15071520
<PhotoWheelSpinner
@@ -1511,7 +1524,7 @@ export function VehicleTwin({
15111524
imgLeft={imgLeft}
15121525
imgTop={imgTop}
15131526
photoUrl={photoUrl}
1514-
driveIn={driveIn}
1527+
driveIn={driveIn && entrySpinOk}
15151528
driving={isDriving}
15161529
/>
15171530
</>

0 commit comments

Comments
 (0)