
Embedding a Simple 3D Model into a React Website with Animation
Translation Note
This article was translated from Japanese with the help of Claude Opus 4.5. For the original content, please refer to: Reactで書いたWebサイトにシンプルな3Dモデルを埋め込んでアニメーションさせてみた
This article is Day 22 of the Iwaken Lab. Advent Calendar 2023!
Introduction
Hi there! I'm nisshi from Iwaken Lab.! I've been working with WebXR and writing React lately.
This time, I redesigned the website for "Code for Yamaguchi," a tech community in Yamaguchi Prefecture that I founded, adding 3D elements. It turned out to be surprisingly easy to implement Web3D, so I'm going to share the implementation process.
What I Built
I redesigned this site with two goals: "Create a simple yet cool-looking website" that would attract local people interested in technology, and "enable everyone to edit content without touching code." For the first goal, I used R3F to embed simple 3D models, and for the second, I used Notion as a headless CMS. (I won't discuss the headless CMS aspect in this article.)
The GitHub repository is available here:
How to Embed 3D Models?
WebGL (Web Graphics Library) is the standard specification for displaying 3D models in web browsers.
WebGL is supported by all browsers including smartphones, allowing you to deliver rich experiences to many users through the web—a space that anyone can easily access.
Recently, WebGPU (Web Graphics Processing Unit), the successor to WebGL, is also being standardized. (Currently only supported in some browsers)
Libraries like Three.js, Babylon.js, and PlayCanvas have emerged to work with these technologies efficiently, making it easy to handle them in JavaScript.
How to Use WebGL with React?
Recently, many sites are being developed using declarative UI frameworks like React, Vue, and Svelte. I personally use React for almost all my web frontend implementations. To use WebGL with declarative UI, various WebGL libraries have published compatible wrappers. For React × Three.js, React Three Fiber (commonly called R3F) is the famous choice. I'll use R3F for this implementation.
Tech Stack
Now that I've covered the base technologies, here's the full tech stack I used for this implementation. This article will focus primarily on R3F.
- Next.js
- TypeScript
- Three.js
- React Three Fiber (R3F)
- Framer Motion
- shadcn/ui
- Notion SDK for JavaScript
- Cloudflare Pages
Implementation
To embed a simple model into the site, I followed these steps:
- Create a 3D model and export as .glb
- Implement a React component to load the .glb
- Implement the full React component for the 3D model display
1. Create a 3D Model and Export as .glb
For step 1, if you're comfortable with 3D modeling software like Blender, go ahead and create your model. For those who aren't familiar with Blender, I'll introduce Spline—a service that lets you do 3D modeling easily in your web browser.
You can follow the tutorials to create models, or grab something from the default library like the one below and export it as glb.
For this site, I used a .glb model that another community member created in Blender.
2. Implement a React Component to Load the .glb
Let's implement a component to load the .glb file. Here, I'll use @react-three/gltfjsx, a CLI tool that converts GLTF to JSX components.
To generate TypeScript code, run the following command:
npx gltfjsx fuku-san.glb -tThis generates code like the following:
3. Implement the Full React Component for 3D Display
Finally, let's write the React component for the 3D model display section. Using components like Canvas and Environment from @react-three/drei, you can easily build a 3D space complete with lighting and shadows. *By the way, "drei" is the German word for the number "3."
By combining components while referring to the documentation, you can easily implement a site with embedded 3D models.
The animation is implemented using the following function.
useFrame is a hook that executes on every rendered frame.
-
state.clock.elapsedTime * 0.3Returns the elapsed animation time (in seconds) multiplied by 0.3. This adjusts the responsiveness to time progression. -
Math.sin(state.clock.elapsedTime * 0.3)Converts the previous value to a sine wave. Since sine waves periodically generate values from -1 to 1, the resulting rotationY value also changes periodically over time. -
(Math.sin(state.clock.elapsedTime * 0.3) * Math.PI) / 3Multiplying by Math.PI expands the range to -π to π. Finally, dividing by 3 reduces the range to -π/3 to π/3. In other words, the animation rotates between ±60°.
Conclusion
So that's my article about embedding a simple 3D model into a React website! The takeaway is that you can create a website with a richer experience just by making a 3D model for your community or yourself and embedding it. It's awesome—everyone should try it!
I think 3D is a domain that's hard for web developers to get into, but once you try it, you'll find there's a pretty good ecosystem that makes implementation surprisingly easy. (If anything, the challenge is more on the 3D modeling side... 😇)
With Apple Vision Pro and spatial computing becoming more popular, I'm convinced that mainstream content will shift from 2D to 3D. I don't think there are many fields that can adapt to this trend as easily as the web. I wrote this (slightly late) advent calendar article hoping that more people would become interested in Web3D!
VRが好きなWebエンジニア。WebXRやVR・機械加工などの技術が好きでものづくりしている。WebXR JPというコミュニティやWeb技術集会というVR空間内の技術イベントを運営中。
Comments
Feel free to share your thoughts or questions about this article