14. Drag: 3D transform
This example also uses useTransform()
to transform the drag distance to other values (like the one on the previous page). Here the x
and y
positions are converted into rotateX
and rotateY
values.
I explained this example in more detail in Chaining and Transforming Motion Values.
Code component
export default function CC_14_Drag_3D_transform(props) {
const x = useMotionValue(0)
const y = useMotionValue(0)
const rotateX = useTransform(y, [-100, 100], [60, -60])
const rotateY = useTransform(x, [-100, 100], [-60, 60])
return (
<div>
<div
style={{
width: 100,
height: 100,
borderRadius: "50%",
background: `radial-gradient(rgba(255,255,255,0),
rgba(255,255,255,0.3))`
perspective: 800,
}}
>
<motion.div
style={{
width: 150,
height: 150,
borderRadius: 30,
backgroundColor: "#fff",
left: -25,
top: -25,
position: "relative",
x: x,
y: y,
rotateX: rotateX,
rotateY: rotateY,
cursor: "grab",
}}
drag
dragConstraints={{ top: 0, right: 0, bottom: 0, left: 0 }}
dragElastic={0.6}
whileTap={{ cursor: "grabbing" }}
/>
</div>
</div>
)
}
Code overrides
The small circle is the box’s parent layer. The Circle()
override changes its perspective
a bit so that we have a stronger 3D effect.
export function Circle(Component): ComponentType {
return (props) => {
const { style, ...rest } = props
return <Component {...rest} style={{ ...style, perspective: 800 }} />
}
}
export function Drag_3D_transform(Component): ComponentType {
return (props) => {
const { style, ...rest } = props
const x = useMotionValue(0)
const y = useMotionValue(0)
const rotateX = useTransform(y, [-100, 100], [60, -60])
const rotateY = useTransform(x, [-100, 100], [-60, 60])
return (
<Component
{...rest}
drag
dragConstraints={{ top: 0, right: 0, bottom: 0, left: 0 }}
dragElastic={0.6}
style={{
...style,
x: x,
y: y,
rotateX: rotateX,
rotateY: rotateY,
}}
/>
)
}
}