在 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 的逻辑感觉是一样的,但结果却截然不同。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
您正在使用 React。
因此,使用“window.document.addEventListener”时请小心。 每次重新渲染组件时,都会创建一个新的事件侦听器,从而导致页面上出现许多事件侦听器。
相反,请考虑使用钩子。你可以在react- Three-drei中找到很多hooks。 我强烈推荐使用react-two-drei。
useEffect(() => { function handleMouseScroll() { //do something } window.addEventListener('wheel', handleMouseScroll); return () => { window.removeEventListener('wheel', handleMouseScroll); }; }, []);就您而言,您正在 useFrame 中使用事件侦听器。然后,useFrame 每秒运行 60 次。您每秒创建 60 个事件侦听器。