I’m using react-three-fiber
, three
and nextjs
to display some birds which is a common example in threejs
! Here is my index file of a nextjs
app:
import React, { useRef, useState, useEffect } from 'react';
import * as THREE from 'three';
import { Canvas, useFrame, useLoader } from 'react-three-fiber';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
function Box(props) {
// This reference will give us direct access to the mesh
const mesh = useRef();
// Set up state for the hovered and active state
const [hovered, setHover] = useState(false);
const [active, setActive] = useState(false);
// Rotate mesh every frame, this is outside of React without overhead
// eslint-disable-next-line no-return-assign,no-multi-assign
useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01));
return (
<mesh
{...props}
ref={mesh}
scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
onClick={e => setActive(!active)}
onPointerOver={e => setHover(true)}
onPointerOut={e => setHover(false)}
>
<boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
<meshStandardMaterial
attach="material"
color={hovered ? 'hotpink' : 'orange'}
/>
</mesh>
);
}
// This component was auto-generated from GLTF by: https://github.com/react-spring/gltfjsx
function Bird({ speed, factor, url, ...props }) {
const gltf = useLoader(GLTFLoader, url);
const group = useRef();
const [mixer] = useState(() => new THREE.AnimationMixer());
useEffect(
() => void mixer.clipAction(gltf.animations[0], group.current).play(),
[gltf.animations, mixer],
);
useFrame((state, delta) => {
group.current.rotation.y +=
Math.sin((delta * factor) / 2) * Math.cos((delta * factor) / 2) * 1.5;
mixer.update(delta * speed);
});
return (
<group ref={group}>
<scene name="Scene" {...props}>
<mesh
name="Object_0"
morphTargetDictionary={gltf.__$[1].morphTargetDictionary}
morphTargetInfluences={gltf.__$[1].morphTargetInfluences}
rotation={[1.5707964611537577, 0, 0]}
>
<bufferGeometry attach="geometry" {...gltf.__$[1].geometry} />
<meshStandardMaterial
attach="material"
{...gltf.__$[1].material}
name="Material_0_COLOR_0"
/>
</mesh>
</scene>
</group>
);
}
function Birds() {
return new Array(2).fill().map((_, i) => {
const x = (15 + Math.random() * 30) * (Math.round(Math.random()) ? -1 : 1);
const y = -10 + Math.random() * 20;
const z = -5 + Math.random() * 10;
const bird = ['stork', 'parrot', 'flamingo'][Math.round(Math.random() * 2)];
const speed = bird === 'stork' ? 0.5 : bird === 'flamingo' ? 2 : 5;
const factor =
bird === 'stork'
? 0.5 + Math.random()
: bird === 'flamingo'
? 0.25 + Math.random()
: 1 + Math.random() - 0.5;
return (
<Bird
key={i}
position={[x, y, z]}
rotation={[0, x > 0 ? Math.PI : 0, 0]}
speed={speed}
factor={factor}
url={`/static/glb/${bird}.glb`}
/>
);
});
}
const MyComponent = props => {
return (
<Canvas>
<ambientLight />
<pointLight position={[10, 0, 10]} />
<Box position={[-1.2, 2, 0]} />
<Box position={[1.2, 0, 0]} />
<Box position={[3, -2, 0]} />
<Birds />
</Canvas>
);
};
export default MyComponent;
My files are in static/glb/… folder! The problem is with the GLTFLoader loader. I tried extend method of "react-three-fiber"
but not helpful!
I think maybe it’s because of SSR. Do you think so?