在 React Three Fiber 中,我有一個 React 元件,可以產生一個精靈,我希望該精靈在相機變焦下保持不變。該演算法似乎有效(大小似乎不隨時間變化),但我可以明顯看到它在放大和縮小時縮放。
我在其他地方看到過對精靈執行類似的操作,而且它似乎可以正常工作,並且沒有出現問題的外觀。我認為存在某種滯後,但我不確定滯後在哪裡或如何解決。
我還附上了問題的影片:https://drive.google.com/file/d/121XPY1pB5bNJr5EYNESnyPfLDdtEeIhn/view?usp=sharing
我已附上 React 元件的程式碼。與常規的 React Three Fiber 程式碼一樣,這只是輸入到畫布元件中:
function TestFunction() { const [scale, setScale] = useState(new Vector3(1, 1, 1)); const map = new THREE.TextureLoader().load("src/assets/Joshy.png"); let state = useThree(); let zoom = state.camera.zoom / 100; let scaler: Vector3 = new Vector3(1 / zoom, 1 / zoom, 1 / zoom); const handleMouseScroll = (event: WheelEvent) => { // Perform actions when the mouse is scrolled scaler.set(1 / zoom, 1 / zoom, 1 / zoom); setScale(scaler); }; useFrame(() => { window.document.addEventListener("wheel", handleMouseScroll, { capture: true, passive: true, }); }); return ( <sprite scale={scale}> <spriteMaterial map={map} /> </sprite> ); }
我希望它不會有那種滯後/故障的外觀,因為我正在更新每一幀,所以我不確定問題是什麼。
我正在尋找的是這樣的:https://drive.google.com/file/d/1KtEcrikFJFYboC6LX0mFVttx2eSTia0c/view?usp=sharing 沒有明顯的滯後。產生此無延遲版本的程式碼採用純 JavaScript Three.js。
const cont = document.documentElement; const [w, h] = [cont.clientWidth - 20, cont.clientHeight - 20]; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(50, w / h, 0.1, 100); camera.position.set(10, 10, 10); const renderer = new THREE.WebGLRenderer(); renderer.setSize(w, h); document.body.appendChild(renderer.domElement); const hlp = new THREE.AxesHelper(3); scene.add(hlp); const map = new THREE.TextureLoader().load( 'https://source.unsplash.com/random/200x200' ); const material = new THREE.SpriteMaterial({ map: map }); const sprite_scale = 4; const sprite = new THREE.Sprite(material); /* sprite.scale.set(sprite_scale, sprite_scale); */ const virtual_d = sprite.position.distanceTo(camera.position) *1.4/ sprite_scale; scene.add(sprite); const controls = new THREE.OrbitControls(camera, renderer.domElement); const render = () => { renderer.render(scene, camera); }; const animate = () => { requestAnimationFrame(animate); render(); }; document.addEventListener('wheel', scaler); function scaler() { const scale = sprite.position.distanceTo(camera.position)/2; console.log(sprite.position.distanceTo(camera.position) ) console.log("CAMERA POSITION: ", camera.position) sprite.scale.set(scale, scale); } animate();
普通的 Three.js 和 React Three Fiber 的邏輯感覺是一樣的,但結果卻截然不同。
您正在使用 React。
因此,使用「window.document.addEventListener」時請小心。 每次重新渲染元件時,都會建立新的事件偵聽器,從而導致頁面上出現許多事件偵聽器。
相反,請考慮使用鉤子。你可以在react- Three-drei中找到很多hooks。 我強烈推薦使用react-two-drei。
就您而言,您正在 useFrame 中使用事件偵聽器。然後,useFrame 每秒運行 60 次。您每秒建立 60 個事件偵聽器。