[英]I'm trying to use Threejs in React. What did i miss in my code?
I tried to convert a project from vanilla Three.js to React.我试图将一个项目从 vanilla Three.js 转换为 React。
here is the project, https://codepen.io/Mamboleoo/pen/rNmRqeK这是项目, https://codepen.io/Mamboleoo/pen/rNmRqeK
and this is my code这是我的代码
codesandbox: https://codesandbox.io/s/peaceful-field-i1ft30?file=/src/surfaceSampling.jsx代码沙盒: https://codesandbox.io/s/peaceful-field-i1ft30?file=/src/surfaceSampling.jsx
const pos = [];
const cols = [];
const Sampler = ({ dotCount, setDotCount }) => {
/**
* animations
*/
useFrame(({ clock }) => {});
/**
* options
*/
const palette = [
new THREE.Color("#FAAD80"),
new THREE.Color("#FF6767"),
new THREE.Color("#FF3D68"),
new THREE.Color("#A73489"),
];
const tempPosition = new Vector3();
const colorMap = useLoader(
TextureLoader,
"https://assets.codepen.io/127738/dotTexture.png"
);
/**
* whale
*/
const whaleMaterials = new THREE.MeshBasicMaterial({
wireframe: true,
color: 0x000000,
transparent: true,
opacity: 0.05,
});
const obj = useLoader(OBJLoader, "/textures/whale/Mesh_Whale.obj");
obj.children[0].material = whaleMaterials;
const samplerWhale = new MeshSurfaceSampler(obj.children[0]);
samplerWhale.build();
// const cols = [];
const [positions, colors] = useMemo(() => {
samplerWhale.sample(tempPosition);
pos.push(tempPosition.x, tempPosition.y, tempPosition.z);
const randomColor = palette[Math.floor(Math.random() * palette.length)];
cols.push(randomColor.r, randomColor.g, randomColor.b, 1);
return [new Float32Array(pos), new Float32Array(cols)];
}, [dotCount]);
useEffect(() => {
if (obj === "undefined") return;
const t = setInterval(() => {
if (dotCount < 100) {
setDotCount((prev) => prev + 1);
}
}, 100);
return () => clearTimeout(t);
}, []);
return (
<group>
<primitive
object={obj}
wireframe={true}
color={0x000000}
transparent={true}
opacity={0.05}
/>
<points>
<bufferGeometry attach="geometry">
<bufferAttribute
attach={"attributes-position"}
args={[positions, 3]}
/>
<bufferAttribute attach={"attributes-color"} args={[colors, 4]} />
</bufferGeometry>
<pointsMaterial
attach="material"
size={1}
alphaTest={0.2}
map={colorMap}
vertexColors={true}
/>
</points>
</group>
);
};
I made it like the example code.我使它像示例代码一样。 However, every time a point shows up, the Sampler component re-renders.
但是,每次出现一个点时,Sampler 组件都会重新渲染。
how could I make it better?我怎样才能让它变得更好?
and also,并且,
const SurfaceSampling = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
const [dotCount, setDotCount] = useState(20);
useEffect(() => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}, []);
return (
<StyledTHREEContainer windowSize={windowSize}>
<Canvas
camera={{
fov: 75,
near: 0.1,
far: 1000,
aspect: window.innerWidth / window.innerHeight,
position: [0, 100, 230],
}}
gl={{ antialias: false }}
>
<OrbitControls />
<Suspense fallback={<Loader />}>
<Sampler dotCount={dotCount} setDotCount={setDotCount} />
</Suspense>
</Canvas>
</StyledTHREEContainer>
);
};
why there is an error in Suspense?为什么Suspense有错误?
the error is错误是
Cannot update a component (`Loader`) while rendering a different component (`Sampler`). To locate the bad setState() call inside `Sampler`, follow the stack trace as described in
State or props changes trigger re-renders in React. State 或道具更改触发 React 中的重新渲染。 To avoid updating state in your example, you could try using a ref instead of state and calling the function that adds entries to "pos" and "cols" array and use them instead of "positions" and "colors".
为避免在您的示例中更新 state,您可以尝试使用 ref 而不是 state 并调用 function 将条目添加到“pos”和“cols”而不是“colors”数组。
In SurfaceSampling:在 SurfaceSampling 中:
const dotCount = useRef(20);
const setDotCount = (count) => { dotCount.current = count };
And in Sampler:在采样器中:
const addDot = () => { samplerWhale.sample(tempPosition); pos.push(tempPosition.x, tempPosition.y, tempPosition.z); const randomColor = palette[Math.floor(Math.random() * palette.length)]; cols.push(randomColor.r, randomColor.g, randomColor.b, 1); } useEffect(() => { if (obj === "undefined") return; const t = setInterval(() => { if (dotCount.current < 100) { setDotCount(dotCount.current + 1); addDot(); } }, 100); return () => clearTimeout(t); }, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.