1 | <h1>react-three-fiber</h1>
|
2 |
|
3 | [![Version](https://img.shields.io/npm/v/@react-three/fiber?style=flat&colorA=000000&colorB=000000)](https://npmjs.com/package/@react-three/fiber)
|
4 | [![Downloads](https://img.shields.io/npm/dt/react-three-fiber.svg?style=flat&colorA=000000&colorB=000000)](https://npmjs.com/package/@react-three/fiber)
|
5 | [![Twitter](https://img.shields.io/twitter/follow/pmndrs?label=%40pmndrs&style=flat&colorA=000000&colorB=000000&logo=twitter&logoColor=000000)](https://twitter.com/pmndrs)
|
6 | [![Discord](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=000000)](https://discord.gg/ZZjjNvJ)
|
7 | [![Open Collective](https://img.shields.io/opencollective/all/react-three-fiber?style=flat&colorA=000000&colorB=000000)](https://opencollective.com/react-three-fiber)
|
8 | [![ETH](https://img.shields.io/badge/ETH-f5f5f5?style=flat&colorA=000000&colorB=000000)](https://blockchain.com/eth/address/0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682)
|
9 | [![BTC](https://img.shields.io/badge/BTC-f5f5f5?style=flat&colorA=000000&colorB=000000)](https://blockchain.com/btc/address/36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH)
|
10 |
|
11 | react-three-fiber is a <a href="https://reactjs.org/docs/codebase-overview.html#renderers">React renderer</a> for threejs.
|
12 |
|
13 | ```bash
|
14 | npm install three @react-three/fiber
|
15 | ```
|
16 |
|
17 | ### Why?
|
18 |
|
19 | Build your scene declaratively with re-usable, self-contained components that react to state, are readily interactive and can tap into React's ecosystem.
|
20 |
|
21 | #### Does it have limitations?
|
22 |
|
23 | None. Everything that works in threejs will work here without exception.
|
24 |
|
25 | #### Can it keep up with frequent updates to threejs?
|
26 |
|
27 | Yes, because it merely expresses threejs in JSX: `<mesh />` becomes `new THREE.Mesh()`, and that happens dynamically. There is no hard dependency on a particular threejs version, it does not wrap or duplicate a single threejs class.
|
28 |
|
29 | #### Is it slower than plain threejs?
|
30 |
|
31 | There is no additional overhead. Components participate in the renderloop outside of React.
|
32 |
|
33 | ### What does it look like?
|
34 |
|
35 | <table>
|
36 | <tr>
|
37 | <td>Let's make a re-usable component that has its own state, reacts to user-input and participates in the render-loop. (<a href="https://codesandbox.io/s/rrppl0y8l4?file=/src/App.js">live demo</a>).</td>
|
38 | <td>
|
39 | <a href="https://codesandbox.io/s/rrppl0y8l4">
|
40 | <img src="https://i.imgur.com/sS4ArrZ.gif" /></td>
|
41 | </a>
|
42 | </tr>
|
43 | </table>
|
44 |
|
45 | #### Imports first
|
46 |
|
47 | ```jsx
|
48 | import React, { useRef, useState } from 'react'
|
49 | import ReactDOM from 'react-dom'
|
50 | import { Canvas, useFrame } from '@react-three/fiber'
|
51 | ```
|
52 |
|
53 | #### Define a component
|
54 |
|
55 | ```jsx
|
56 | function Box(props) {
|
57 | // This reference will give us direct access to the mesh
|
58 | const mesh = useRef()
|
59 | // Set up state for the hovered and active state
|
60 | const [hovered, setHover] = useState(false)
|
61 | const [active, setActive] = useState(false)
|
62 | // Rotate mesh every frame, this is outside of React without overhead
|
63 | useFrame(() => (mesh.current.rotation.x += 0.01))
|
64 |
|
65 | return (
|
66 | <mesh
|
67 | {...props}
|
68 | ref={mesh}
|
69 | scale={active ? 1.5 : 1}
|
70 | onClick={(event) => setActive(!active)}
|
71 | onPointerOver={(event) => setHover(true)}
|
72 | onPointerOut={(event) => setHover(false)}>
|
73 | <boxGeometry args={[1, 2, 3]} />
|
74 | <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
|
75 | </mesh>
|
76 | )
|
77 | }
|
78 | ```
|
79 |
|
80 | #### Compose the scene
|
81 |
|
82 | Either use `Canvas`, which you can think of as a portal to threejs inside your regular dom graph. Everything within it is a [native threejs element](https://threejs.org/docs). If you want to mix Webgl and Html (react-dom) this is what you should use.
|
83 |
|
84 | ```jsx
|
85 | ReactDOM.render(
|
86 | <Canvas>
|
87 | <ambientLight />
|
88 | <pointLight position={[10, 10, 10]} />
|
89 | <Box position={[-1.2, 0, 0]} />
|
90 | <Box position={[1.2, 0, 0]} />
|
91 | </Canvas>,
|
92 | document.getElementById('root'),
|
93 | )
|
94 | ```
|
95 |
|
96 | Or use react-three-fibers own `render` function, which is a little more low-level but could save you the extra cost of carrying react-dom. It renders into a dom `canvas` element. Use this for Webgl-only apps.
|
97 |
|
98 | ```jsx
|
99 | import { render } from '@react-three/fiber'
|
100 |
|
101 | render(<Scene />, document.querySelector('canvas'))
|
102 | ```
|
103 |
|
104 | <details>
|
105 | <summary>Show TypeScript example</summary>
|
106 |
|
107 | ```tsx
|
108 | import { Canvas, MeshProps, useFrame } from '@react-three/fiber'
|
109 |
|
110 | const Box: React.FC<MeshProps> = (props) => {
|
111 | // This reference will give us direct access to the mesh
|
112 | const mesh = useRef<THREE.Mesh>(null!)
|
113 | // Set up state for the hovered and active state
|
114 | const [hovered, setHover] = useState(false)
|
115 | const [active, setActive] = useState(false)
|
116 | // Rotate mesh every frame, this is outside of React without overhead
|
117 | useFrame(() => (mesh.current.rotation.x += 0.01))
|
118 |
|
119 | return (
|
120 | <mesh
|
121 | {...props}
|
122 | ref={mesh}
|
123 | scale={active ? 1.5 : 1}
|
124 | onClick={(event) => setActive(!active)}
|
125 | onPointerOver={(event) => setHover(true)}
|
126 | onPointerOut={(event) => setHover(false)}>
|
127 | <boxGeometry args={[1, 2, 3]} />
|
128 | <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
|
129 | </mesh>
|
130 | )
|
131 | }
|
132 |
|
133 | ReactDOM.render(
|
134 | <Canvas>
|
135 | <ambientLight />
|
136 | <pointLight position={[10, 10, 10]} />
|
137 | <Box position={[-1.2, 0, 0]} />
|
138 | <Box position={[1.2, 0, 0]} />
|
139 | </Canvas>,
|
140 | document.getElementById('root'),
|
141 | )
|
142 | ```
|
143 |
|
144 | </details>
|
145 |
|
146 | ---
|
147 |
|
148 | # Documentation
|
149 |
|
150 | - [api.md](/markdown/api.md)
|
151 | - [pitfalls.md](/markdown/pitfalls.md)
|
152 | - [testing.md](/packages/test-renderer)
|
153 |
|
154 | # Fundamentals
|
155 |
|
156 | You need to be versed in both React and Threejs before rushing into this. If you are unsure about React consult the official [React docs](https://reactjs.org/docs/getting-started.html), especially [the section about hooks](https://reactjs.org/docs/hooks-reference.html). As for Threejs, make sure you at least glance over the following links:
|
157 |
|
158 | 1. Make sure you have a [basic grasp of Threejs](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene). Keep that site open.
|
159 | 2. When you know what a scene is, a camera, mesh, geometry, material, fork the [demo above](https://github.com/react-spring/react-three-fiber#what-does-it-look-like).
|
160 | 3. [Look up](https://threejs.org/docs/index.html#api/en/objects/Mesh) the JSX elements that you see (mesh, ambientLight, etc), _all_ threejs exports are native to three-fiber.
|
161 | 4. Try changing some values, scroll though our [Api](/markdown/api.md) to see what the various settings and hooks do.
|
162 |
|
163 | Some reading material:
|
164 |
|
165 | - [Threejs-docs](https://threejs.org/docs)
|
166 | - [Threejs-examples](https://threejs.org/examples)
|
167 | - [Threejs-fundamentals](https://threejsfundamentals.org)
|
168 | - [Discover Threejs](https://discoverthreejs.com)
|
169 | - [Do's and don'ts](https://discoverthreejs.com/tips-and-tricks) for performance and best practices
|
170 | - [react-three-fiber alligator.io tutorial](https://alligator.io/react/react-with-threejs) by [@dghez\_](https://twitter.com/dghez_)
|
171 |
|
172 | # Ecosystem
|
173 |
|
174 | - [`@react-three/gltfjsx`](https://github.com/react-spring/gltfjsx) – turns GLTFs into JSX components
|
175 | - [`@react-three/drei`](https://github.com/react-spring/drei) – useful helpers for react-three-fiber
|
176 | - [`@react-three/postprocessing`](https://github.com/react-spring/react-postprocessing) – post-processing effects
|
177 | - [`@react-three/flex`](https://github.com/react-spring/react-three-flex) – flexbox for react-three-fiber
|
178 | - [`@react-three/xr`](https://github.com/react-spring/react-xr) – VR/AR controllers and events
|
179 | - [`@react-three/cannon`](https://github.com/react-spring/use-cannon) – physics based hooks
|
180 | - [`zustand`](https://github.com/react-spring/zustand) – state management
|
181 | - [`react-spring`](https://github.com/react-spring/react-spring) – a spring-physics-based animation library
|
182 | - [`react-use-gesture`](https://github.com/react-spring/react-use-gesture) – mouse/touch gestures
|
183 |
|
184 | # How to contribute
|
185 |
|
186 | If you like this project, please consider helping out. All contributions are welcome as well as donations to [Opencollective](https://opencollective.com/react-three-fiber), or in crypto `BTC: 36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH`, `ETH: 0x6E3f79Ea1d0dcedeb33D3fC6c34d2B1f156F2682`.
|
187 |
|
188 | #### Backers
|
189 |
|
190 | Thank you to all our backers! 🙏
|
191 |
|
192 | <a href="https://opencollective.com/react-three-fiber#backers" target="_blank">
|
193 | <img src="https://opencollective.com/react-three-fiber/backers.svg?width=890"/>
|
194 | </a>
|
195 |
|
196 | #### Contributors
|
197 |
|
198 | This project exists thanks to all the people who contribute.
|
199 |
|
200 | <a href="https://github.com/pmndrs/react-three-fiber/graphs/contributors">
|
201 | <img src="https://opencollective.com/react-three-fiber/contributors.svg?width=890" />
|
202 | </a>
|