Adding motion to 3D models with Framer Motion and Three.js
Daichi Izushi
Posted on October 10, 2024
Libraries
Framer Motion
Framer Motion is an animation library for React. The declarative aspect of the library is in line with the React philosophy, making it very comfortable to use. You can see an example in the official documentation below, you can control complex animations with a simple description.
React Three Fiber
A library that enables Three.js to be used as a React component, providing the basic functionality of Three.js as a React component.
Drei
This helper library for React Three Fiber provides useful components and hooks to make Three.js easier to use with React. This makes building 3D scenes easier and improves code readability and maintainability.
Library Installation
Framer Motion
npm install framer-motion
React Three Fiber
npm install @react-three/fiber
Drei
npm install @react-three/drei
Introduction of 3D model
Saving 3D Model Files
First, download a 3D model of your choice from Sketchfab, etc., and save the gltf and bin files under /src/assets/models in your React application.
GLTF model loading
url
property specifying the path to the directory where the 3D model was placed earlier
useGLTF
hook
Loads a 3D model in GLTF format asynchronously from the path of the directory where the 3D model was placed
import { Canvas } from '@react-three/fiber';
import { useGLTF } from '@react-three/drei';
const Model = ({ url }: { url: string; }) => {
const { scene } = useGLTF(url);
return (
<group>
<primitive object={scene} />
</group>
);
};
const ThreeModel = () => {
return (
<div>
<Canvas>
<Model url="/src/assets/models/scene.gltf"/>
</Canvas>
</div>
);
};
export default ThreeModel;
Rendering the model
The loaded GLTF Model scene object is used within the primitive component and added to the scene in Three.js.
Manipulation of 3D models
Brightness adjustment of 3D model
ambientLight
Light up the 3D model
const ThreeModel = () => {
return (
<div>
<Canvas>
<ambientLight intensity={3}/>
...
</Canvas>
</div>
);
};
Adjust the size, position, and tilt of the 3D model
Added scale, position, and rotation properties to the Model component.
scale
Property specifying the size of the model
position
Property that specifies the position of the model. In array format, each element represents a position relative to the x, y, and z axes.
- 1st value of array: 0 (position along x-axis)
- 2nd value of array: -1.2 (position along y-axis)
- 3rd value of array: 1 (position along z-axis)
import { Canvas } from '@react-three/fiber';
import { useGLTF } from '@react-three/drei';
const Model = ({
url,
scale,
position,
rotation
}: {
url: string;
scale: number;
position: number[];
rotation: number[];
}) => {
const { scene } = useGLTF(url);
return (
<group>
<primitive
object={scene}
scale={scale}
position={position}
rotation={rotation} />
</group>
);
};
const ThreeModel = () => {
return (
<div
className='w-full h-[700px]'>
<Canvas>
<ambientLight intensity={3}/>
<Model
url="/src/assets/models/scene.gltf"
scale={0.8}
position={[0, -1.2, 1]}
rotation={[Math.PI / 7, -Math.PI / 10, 0]} />
</Canvas>
</div>
);
};
export default ThreeModel;
Adjust camera position and field of view
camara
property
The object that specifies Three.js camera settings
position
Specifies the camera position. Array format, with each element representing a position relative to the x, y, and z axes.
fov
Specify the camera’s field of view
import { Canvas } from '@react-three/fiber';
...
<Canvas camera={{ position: [0, 0, 15], fov: 30 }}>
Add wave motion to the 3D model
Within the useFrame hook, the y-coordinate of the group is periodically varied using sine waves to achieve an animation of the 3D model moving up and down.
useRef
Create a reference to the group element using the useRef hook. This reference is used to access DOM elements and Three.js objects.
import { useRef } from 'react';
...
const groupRef = useRef(null);
Rendering of group element
group
element
Corresponds to the Group object in Three.js. This element is used to manipulate multiple objects together.
ref={groupRef}
A reference to this group element is set to groupRef.
return (
<group ref={groupRef}>
<primitive object={scene} scale={scale} position={position} rotation={rotation} />
</group>
);
Animation loop processing
useFrame
React Three Fiber hook, used to hook into the Three.js rendering loop for animation and frame-by-frame updates.
Math.sin(state.clock.elapsedTime)
Generate a sine wave based on the elapsed time in seconds since the animation started
groupRef.current.position.y
By setting the result multiplied by the sine wave value, the y-coordinate of group will fluctuate up and down. In this case, the amplitude is set to 0.25.
import { useFrame } from '@react-three/fiber';
...
useFrame((state) => {
if (groupRef.current) {
groupRef.current.position.y = Math.sin(state.clock.elapsedTime) * 0.25;
}
});
Move 3D model with mouse operation
OrbitControls
Control the camera to rotate, translate, and zoom in and out around a central point. Easily available in React Three Fiber using a helper library drei.
enableZoom
property
Disable the zoom function by setting it to false.
import { OrbitControls} from '@react-three/drei';
...
const ThreeModel = () => {
return (
<div
className='w-full h-[700px]'>
<Canvas camera={{ position: [0, 0, 15], fov: 30 }}>
...
<OrbitControls enableZoom={false} />
</Canvas>
</div>
);
};
Add animation to 3D model with Framer motion
motion.div is a component for adding animation using the Framer Motion library. motion.div works like a normal div element, but allows you to add animation settings.
Properties of motion.div
initial
Specify the initial state of the animation. In this case, x: 100 and opacity: 0 are specified.
animate
Specify the final state of the animation. In this case, x: 0 and opacity: 1 are specified.
transition
Specify settings for animation transitions
type: 'spring'
The spring type simulates the movement of a physical spring and provides animation with a natural damping effect.duration
Specifies the duration of the transition in seconds.
However, if type: ‘spring’ is specified, stiffness and damping have priority.delay
Specify the delay in seconds before the transition starts. In this case, the animation starts 0.9 seconds later.stiffness
Specifies the hardness of the stiffness of the spring. The higher the value, the stiffer the spring and the faster the animation.
import { motion } from 'framer-motion';
...
const ThreeModel = () => {
return (
<motion.div
initial={{ y: -100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{
type: 'spring',
duration: 0,
delay: 0.9,
stiffness: 200,
}}
className='w-full h-[700px]'>
...
</motion.div>
);
};
Conclusion
How to add animation effects to a 3D model using Framer Motion
,React three fiber and Drei make it easy to build interactive and visually appealing web applications.Use it to make your website more attractive!
Posted on October 10, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.