Tutorials

avatar

Malik Kotb

Jan 29, 2024 / Beginner / Short

3D Model Interaction
Create an interactive 3d model using Three.js and Next.js

A web animation tutorial on how to use and interact with a 3D model using Three.js and Next.js.

Initialize our project

Let's start the project by setting up a Next.js app with TypeScript and utilizing the app router. Just run npx create-next-app@latest client in your terminal.

Adding the JSX and CSS

We can clear out all the contents in the page.tsx, and global.css files, and add our own HTML and CSS, to begin with a clean slate in the application.

Page Component

We create a full-screen environment and place our SceneCanvas in the center. As a source prop we pass the name of our .glb-file.

page.tsx

1import SceneCanvas from "@/components/SceneCanvas";
2
3export default function Home() {
4  return (
5    <div className="w-screen h-screen items-center justify-center">
6      <SceneCanvas source={"/yacht.glb"} />
7    </div>
8  );
9}
10

SceneCanvas component

The SceneCanvas component is where the magic happens. We can pass down the source to the Model component which we will cover afterward.

page.tsx

1"use client";
2
3import { Canvas } from "@react-three/fiber";
4import {
5  OrbitControls,
6  Stage,
7} from "@react-three/drei";
8import Model from "./Model";
9
10export default function SceneCanvas({ source }: { source: string}) {
11  return (
12    <div className="flex justify-center items-center h-full">
13      <Canvas dpr={[1, 2]} camera={{ position: [0, 0, 100]}}>
14        {/* <color attach="background" /> */}
15        <OrbitControls
16          autoRotate
17          enableZoom={false}
18          minPolarAngle={-Math.PI / 2}
19          maxPolarAngle={Math.PI / 2}
20        />
21        <ambientLight intensity={0.5} />
22        <directionalLight position={[-2, 5, 2]} intensity={1} />
23        <Stage environment={"night"}>
24          <Model source={source} scale={0.01} />
25        </Stage>
26      </Canvas>
27    </div>
28  );
29}
30

Model component

page.tsx

1import { useGLTF } from "@react-three/drei";
2
3type Model = {
4    source: string,
5    scale: number
6}
7export default function Model({ source, scale }: Model) {
8    const { scene } = useGLTF(source);
9    return <primitive object={scene} scale={scale} />
10}
11
We should have something like this:
Wrapping up.

Quick and smooth, right?

Hope you liked the animation and learned something new!

-Malik

Things for creative devs
sent to your inbox every week