我在react(next js)中使用Three.js,并且我创建的网格被多次复制
import * as THREE from 'three';
function Index() {
if (process.browser) {
const scene = new THREE.Scene();
const camera = new THREE.
PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
console.log(scene.children);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
console.log(scene.children);
camera.position.z = 12;
renderer.render(scene, camera);
return <div> </div>
}
return null;
}
export default Index;如下所示:

则控制台选项卡具有:

目标是在没有滚动的情况下在屏幕上显示一个立方体(水平和垂直)。
我怀疑这是由document.body.appendChild决定的,我也没有找到替代它的方法。
发布于 2021-09-29 05:18:29
您将希望在React的useEffect中保留有效的内容。这将在组件挂载时在浏览器上运行,并在其依赖项数组更改时重新运行。依赖项是一个不可变值,表示从useState等钩子派生的状态。
您也永远不想直接接触DOM,因为React不会知道您在那里所做的更改,这会导致重复和其他副作用。相反,您可以通过useRef钩子访问带有ref的DOM。这让我们可以使用canvasRef.current获得一个可变的画布访问器。
import * as THREE from 'three';
import { useRef, useEffect } from 'react';
function Index() {
const canvasRef = useRef();
useEffect(() => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({ canvas: canvasRef.current });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
console.log(scene.children);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
console.log(scene.children);
camera.position.z = 12;
renderer.render(scene, camera);
// Cleanup on unmount, otherwise stuff will linger in GPU
return () => {
renderer.forceContextLoss();
renderer.dispose();
cube.geometry.dispose();
cube.material.dispose();
};
}, []);
return <canvas ref={canvasRef} />;
}
export default Index;注意effect是如何返回回调的。这是一个在组件卸载时执行的清理函数。我们这样做是因为three.js会将几何体和材质着色器程序上传到图形处理器,这些程序不会被垃圾回收,并且会一直存在。因为你必须自己管理生命周期,所以我强烈建议你使用像@react-three/fiber这样的three.js渲染器,这样你就可以更好地使用React生态系统。
import { Canvas } from '@react-three-fiber';
function Index() {
return (
<Canvas frameloop="demand" camera={{ position: [0, 0, 12] }}>
<mesh>
<boxGeometry />
<meshBasicMaterial color={0x00ff00} />
</mesh>
</Canvas>
);
}
export default Index;发布于 2021-09-29 05:18:48
这是因为只要组件呈现,脚本就会运行。因此,最好的方法是创建一个画布元素,如果它是一个类,则使用useEffect钩子或componentDidMount方法。
但就我个人而言,我建议使用react-three/fiber或react-three-next
https://stackoverflow.com/questions/69367213
复制相似问题