Animation » Example Animations » 14. Drag: 3D transform

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,
                }}
            />
        )
    }
}


Join the Framer book mailing list    ( ± 6 emails/year )

GDPR

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing per their Privacy Policy and Terms.



Leave a Reply