feat: smooth cursor dampening transitions with react-spring
Problem: - Movement multiplier (cursor dampening) changed instantly when crossing region boundaries - This created jarring cursor behavior when moving from a large region to a tiny one - Example: cursor speed jumping from 0.25x to 0.03x when moving from France to Gibraltar Solution: - Added movementMultiplier to magnifierSpring for smooth animated transitions - Spring config: tension 180, friction 26 (faster than zoom, slower than position) - Uses .get() to read current animated value in mouse handler Benefits: - Gradual cursor dampening changes feel natural and predictable - No jarring speed changes when crossing region boundaries - Maintains precision control while improving UX 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
cb4114f344
commit
66544dc7dd
|
|
@ -324,11 +324,13 @@ export function MapRenderer({
|
||||||
// Different fade speeds: fast fade-in (100ms), slow fade-out (1000ms)
|
// Different fade speeds: fast fade-in (100ms), slow fade-out (1000ms)
|
||||||
// Zoom: smooth, slower animation with gentle easing
|
// Zoom: smooth, slower animation with gentle easing
|
||||||
// Position: medium speed (300ms)
|
// Position: medium speed (300ms)
|
||||||
|
// Movement multiplier: gradual transitions for smooth cursor dampening
|
||||||
const magnifierSpring = useSpring({
|
const magnifierSpring = useSpring({
|
||||||
zoom: targetZoom,
|
zoom: targetZoom,
|
||||||
opacity: targetOpacity,
|
opacity: targetOpacity,
|
||||||
top: targetTop,
|
top: targetTop,
|
||||||
left: targetLeft,
|
left: targetLeft,
|
||||||
|
movementMultiplier: getMovementMultiplier(smallestRegionSize),
|
||||||
config: (key) => {
|
config: (key) => {
|
||||||
if (key === 'opacity') {
|
if (key === 'opacity') {
|
||||||
return targetOpacity === 1
|
return targetOpacity === 1
|
||||||
|
|
@ -339,6 +341,11 @@ export function MapRenderer({
|
||||||
// Zoom: smooth, slower animation with gentle easing
|
// Zoom: smooth, slower animation with gentle easing
|
||||||
return { tension: 120, friction: 30, mass: 1 }
|
return { tension: 120, friction: 30, mass: 1 }
|
||||||
}
|
}
|
||||||
|
if (key === 'movementMultiplier') {
|
||||||
|
// Movement multiplier: smooth but responsive transitions
|
||||||
|
// Faster than zoom so cursor responsiveness changes quickly but not jarring
|
||||||
|
return { tension: 180, friction: 26 }
|
||||||
|
}
|
||||||
// Position: medium speed
|
// Position: medium speed
|
||||||
return { tension: 200, friction: 25 }
|
return { tension: 200, friction: 25 }
|
||||||
},
|
},
|
||||||
|
|
@ -763,10 +770,11 @@ export function MapRenderer({
|
||||||
const lastX = cursorPositionRef.current?.x ?? containerRect.width / 2
|
const lastX = cursorPositionRef.current?.x ?? containerRect.width / 2
|
||||||
const lastY = cursorPositionRef.current?.y ?? containerRect.height / 2
|
const lastY = cursorPositionRef.current?.y ?? containerRect.height / 2
|
||||||
|
|
||||||
// Apply movement multiplier based on smallest region size for precision control
|
// Apply smoothly animated movement multiplier for gradual cursor dampening transitions
|
||||||
const movementMultiplier = getMovementMultiplier(smallestRegionSize)
|
// This prevents jarring changes when moving between regions of different sizes
|
||||||
cursorX = lastX + e.movementX * movementMultiplier
|
const currentMultiplier = magnifierSpring.movementMultiplier.get()
|
||||||
cursorY = lastY + e.movementY * movementMultiplier
|
cursorX = lastX + e.movementX * currentMultiplier
|
||||||
|
cursorY = lastY + e.movementY * currentMultiplier
|
||||||
|
|
||||||
// Clamp to container bounds
|
// Clamp to container bounds
|
||||||
cursorX = Math.max(0, Math.min(containerRect.width, cursorX))
|
cursorX = Math.max(0, Math.min(containerRect.width, cursorX))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue