我正在移动一个我用三个js开发的项目来反应三纤维,并且在渲染循环方面遇到了一些问题。也许我不完全了解useFrame的工作原理。
这是CodeSandbox:
https://codesandbox.io/s/react-three-test-y0zrx?file=/src/Three.jsx:1824-1835
因此,在此项目中,我使用滚动条在z轴上移动相机并更改当我们到达z位置上的不同点时显示的年份。如您所见,当我们达到这一点时,我们使用了useState设置函数,该函数更改状态但还会产生滞后并暂时停用渲染效果。
这是渲染器功能,用于更改显示的信息(从位置开始的年份):
ThreeComponent.jsx
const getYear = cameraZ => parseInt(cameraZ / -10 + START_YEAR, 10);
const getRoundedYear = year => Math.round(year / 10) * 10;
const shouldDisplayYear = roundedYear => {
return (
roundedYear % 100 === 0 || (roundedYear > 1890 && roundedYear % 10 === 0)
);
};
function Renderer() {
const composer = useRef();
const { scene, gl, camera } = useThree();
useFrame(() => {
const roundedYear = getRoundedYear(getYear(camera.position.z));
if (shouldDisplayYear(roundedYear)) {
// The problem lies here
setDisplayedYear(roundedYear);
}
return composer?.current?.render();
}, 1);
return (
<effectComposer ref={composer} args={[gl]}>
<renderPass attachArray="passes" scene={scene} camera={camera} />
<bokehPass
attachArray="passes"
args={[
scene,
camera,
{
focus: 20.0,
aperture: 1.1 * 0.00008,
maxblur: 0.05,
width: window.innerWidth,
height: window.innerHeight
}
]}
/>
</effectComposer>
);
}
...
return (
<div className="three-component" ref={canvasRef}>
<Canvas
...>
...
<Renderer/>
</Canvas>
</div>
);
set函数是从父组件传递来的,但是如果它在同一组件上,则会遇到相同的问题:
ThreeComponent.jsx
const ThreeComponent = ({ setDisplayedYear, startYear }) => {
App.js(父级)
const [displayedYear, setDisplayedYear] = useState(START_YEAR);
有人能阐明为什么会出现这种滞后吗?或者也许有一种更好的方法,仅通过滚动和更新数字来移动摄像机。
非常感谢您!
答案 0 :(得分:0)
useFrame是一个渲染循环,每秒运行60次,您无法在其中产生任何副作用。 setDisplayedYear会要求React进行所有繁重的工作,进行差异化,通过vdoms等。充其量只能提高性能,或者只会杀死制表符。
您可以在这里做很多事情,最好是在那时和那里更改相机。您可以从useState(state => state.camera中获取它。我会删除所有setState内容。
编辑:
我认为您还在每个渲染器上不必要地在其中重新创建许多对象。例如,每次setState更改时都会创建函数Renderer(),它会从头开始重新创建整个效果。组件应始终是固定引用。
下面是一个向内和向外移动摄像机的示例:https://codesandbox.io/s/r3f-lod-rzuj1
这是另一个可能更接近您需要的图像(凸轮对滚动偏移做出反应):https://codesandbox.io/s/adoring-feather-nk16u