├── README.md
├── package.json
├── pages
├── _app.js
├── birds.js
├── boxes.js
├── index.css
└── index.js
└── public
└── glb
├── flamingo.glb
├── parrot.glb
└── stork.glb
/README.md:
--------------------------------------------------------------------------------
1 | # With Three js
2 |
3 | This example uses:
4 |
5 | `threejs`: A lightweight, 3D library with a default WebGL renderer. The library also provides Canvas 2D, SVG and CSS3D renderers in the examples.
6 | `react-three-fiber`: A React renderer for Threejs on the web and react-native.
7 |
8 | ## Deploy your own
9 |
10 | Deploy the example using [ZEIT Now](https://zeit.co/now):
11 |
12 | [](https://zeit.co/import/project?template=https://github.com/zeit/next.js/tree/canary/examples/with-three-js)
13 |
14 | ## How to use
15 |
16 | ### Using `create-next-app`
17 |
18 | Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
19 |
20 | ```bash
21 | npx create-next-app --example with-three-js
22 | # or
23 | yarn create next-app --example with-three-js
24 | ```
25 |
26 | ### Download manually
27 |
28 | Download the example:
29 |
30 | ```bash
31 | curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-three-js
32 | cd with-three-js
33 | ```
34 |
35 | Install it and run:
36 |
37 | ```bash
38 | npm install
39 | npm run dev
40 | # or
41 | yarn
42 | yarn dev
43 | ```
44 |
45 | Deploy it to the cloud with [ZEIT Now](https://zeit.co/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
46 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-three-js",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start"
9 | },
10 | "dependencies": {
11 | "next": "9.3.3",
12 | "react": "16.12.0",
13 | "react-dom": "16.12.0",
14 | "react-three-fiber": "4.0.12",
15 | "three": "0.112.1"
16 | },
17 | "devDependencies": {}
18 | }
19 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './index.css'
3 |
4 | function MyApp({ Component, pageProps }) {
5 | return
6 | }
7 |
8 | export default MyApp
9 |
--------------------------------------------------------------------------------
/pages/birds.js:
--------------------------------------------------------------------------------
1 | import React, { useRef, useState, useEffect, Suspense } from 'react'
2 | import * as THREE from 'three'
3 | import { Canvas, useFrame, useLoader } from 'react-three-fiber'
4 |
5 | let GLTFLoader
6 |
7 | const Bird = ({ speed, factor, url, ...props }) => {
8 | const gltf = useLoader(GLTFLoader, url)
9 | const group = useRef()
10 | const [mixer] = useState(() => new THREE.AnimationMixer())
11 | useEffect(
12 | () => void mixer.clipAction(gltf.animations[0], group.current).play(),
13 | [gltf.animations, mixer]
14 | )
15 | useFrame((state, delta) => {
16 | group.current.rotation.y +=
17 | Math.sin((delta * factor) / 2) * Math.cos((delta * factor) / 2) * 1.5
18 | mixer.update(delta * speed)
19 | })
20 | return (
21 |
22 |
23 |
29 |
30 |
35 |
36 |
37 |
38 | )
39 | }
40 |
41 | const Birds = () => {
42 | return new Array(5).fill().map((_, i) => {
43 | const x = (15 + Math.random() * 30) * (Math.round(Math.random()) ? -1 : 1)
44 | const y = -10 + Math.random() * 20
45 | const z = -5 + Math.random() * 10
46 | const bird = ['stork', 'parrot', 'flamingo'][Math.round(Math.random() * 2)]
47 | let speed = bird === 'stork' ? 0.5 : bird === 'flamingo' ? 2 : 5
48 | let factor =
49 | bird === 'stork'
50 | ? 0.5 + Math.random()
51 | : bird === 'flamingo'
52 | ? 0.25 + Math.random()
53 | : 1 + Math.random() - 0.5
54 | return (
55 | 0 ? Math.PI : 0, 0]}
59 | speed={speed}
60 | factor={factor}
61 | url={`/glb/${bird}.glb`}
62 | />
63 | )
64 | })
65 | }
66 |
67 | const BirdsPage = props => {
68 | useEffect(() => {
69 | GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader').GLTFLoader
70 | }, [])
71 | return (
72 | <>
73 |
80 | >
81 | )
82 | }
83 |
84 | export default BirdsPage
85 |
--------------------------------------------------------------------------------
/pages/boxes.js:
--------------------------------------------------------------------------------
1 | import React, { useRef, useState, Suspense } from 'react'
2 | import { Canvas, useFrame } from 'react-three-fiber'
3 |
4 | const Box = props => {
5 | const mesh = useRef()
6 |
7 | const [hovered, setHover] = useState(false)
8 | const [active, setActive] = useState(false)
9 |
10 | useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01))
11 |
12 | return (
13 | setActive(!active)}
18 | onPointerOver={e => setHover(true)}
19 | onPointerOut={e => setHover(false)}
20 | >
21 |
22 |
26 |
27 | )
28 | }
29 |
30 | const BirdsPage = () => {
31 | return [
32 | Click on me - Hover me :)
,
33 | ,
43 | ]
44 | }
45 |
46 | export default BirdsPage
47 |
--------------------------------------------------------------------------------
/pages/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | width: 100%;
5 | height: 100vh;
6 | background: lavender;
7 | }
8 |
9 | canvas {
10 | width: 100%;
11 | height: 100vh;
12 | }
13 |
14 | h1 {
15 | display: flex;
16 | justify-content: center;
17 | align-content: center;
18 | color: hotpink;
19 | }
20 |
21 | .main {
22 | background: hotpink;
23 | padding: 50px;
24 | border-radius: 4px;
25 | display: flex;
26 | margin: 200px;
27 | flex-direction: column;
28 | justify-content: center;
29 | align-items: center;
30 | color: white;
31 | }
32 |
33 | a {
34 | color: white;
35 | display: block;
36 | text-decoration: unset;
37 | font-size: 20px;
38 | margin: 5px 0;
39 | }
40 |
41 | a:hover {
42 | color: #3f51b5;
43 | }
44 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Link from 'next/link'
3 |
4 | const Index = () => {
5 | return (
6 |
14 | )
15 | }
16 |
17 | export default Index
18 |
--------------------------------------------------------------------------------
/public/glb/flamingo.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjcero/next-js-with-threejs/75475c5da099acafd7aba5c1c2ca804dc2b46b1c/public/glb/flamingo.glb
--------------------------------------------------------------------------------
/public/glb/parrot.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjcero/next-js-with-threejs/75475c5da099acafd7aba5c1c2ca804dc2b46b1c/public/glb/parrot.glb
--------------------------------------------------------------------------------
/public/glb/stork.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fjcero/next-js-with-threejs/75475c5da099acafd7aba5c1c2ca804dc2b46b1c/public/glb/stork.glb
--------------------------------------------------------------------------------