Skip to content

Instantly share code, notes, and snippets.

@steveruizok
Created August 18, 2019 19:56
Show Gist options
  • Save steveruizok/6e293980318783e4fbf0abc7c43a83d8 to your computer and use it in GitHub Desktop.
Save steveruizok/6e293980318783e4fbf0abc7c43a83d8 to your computer and use it in GitHub Desktop.
Radial drag constraints in Framer X / Framer Motion.
import { Override, motionValue, useAnimation } from 'framer'
const x = motionValue(0)
const y = motionValue(0)
export function Knob(): Override {
const maxRadius = 32
const overDrag = 0.25
const animation = useAnimation()
// Constrain to radius (with overdrag)
const handleDrag = (event, info) => {
const { x: px, y: py } = info.point
const radius = Math.floor(Math.hypot(px, py))
if (radius < maxRadius) return
const angle = Math.atan2(py, px)
const overdragRadius = maxRadius + (radius - maxRadius) * overDrag
animation.set({
x: Math.cos(angle) * overdragRadius,
y: Math.sin(angle) * overdragRadius,
})
}
// Spring back to radius, if overdragged
const handleDragEnd = (event, info) => {
const { x: px, y: py } = info.point
const radius = Math.floor(Math.hypot(px, py))
if (radius < maxRadius) return
const angle = Math.atan2(py, px)
animation.start({
x: Math.cos(angle) * maxRadius,
y: Math.sin(angle) * maxRadius,
transition: {
damping: 22,
velocity: 0,
mass: 1,
stiffness: 215,
restDelta: 0.01,
restSpeed: 0.01,
},
})
}
return {
x,
y,
drag: true,
dragMomentum: false,
onDrag: handleDrag,
onDragEnd: handleDragEnd,
animate: animation,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment