Javascript Three.js-在不可见/不在视口中时停止渲染场景

Javascript Three.js-在不可见/不在视口中时停止渲染场景,javascript,canvas,three.js,Javascript,Canvas,Three.js,我正在制作一个使用了大量js和动画的网站,第一部分是全屏3.js场景,它随着鼠标移动而移动。场景本身很好,但每次都在渲染,即使我不看three.js webgl画布,它也会造成性能问题,而其他动画在网站上的位置较低 当场景不在视口中时,我需要完全停止渲染场景,这将极大地提高PEWRFORMCNE 下面是渲染函数: const render = () => { requestAnimationFrame(render); camera.position.x += (mou

我正在制作一个使用了大量js和动画的网站,第一部分是全屏3.js场景,它随着鼠标移动而移动。场景本身很好,但每次都在渲染,即使我不看three.js webgl画布,它也会造成性能问题,而其他动画在网站上的位置较低

当场景不在视口中时,我需要完全停止渲染场景,这将极大地提高PEWRFORMCNE

下面是渲染函数:

const render = () => {
    requestAnimationFrame(render);


    camera.position.x += (mouseX - camera.position.x) * 0.05;
    camera.position.y += (mouseY * -1 - camera.position.y) * 0.05;
    camera.lookAt(scene.position);

    const t = Date.now() * 0.001;
    const rx = Math.sin(t * 0.6) * 0.5;
    const ry = Math.sin(t * 0.3) * 0.5;
    const rz = Math.sin(t * 0.2) * 0.5;
    group.rotation.x = rx;
    group.rotation.y = ry;
    group.rotation.z = rz;
    textMesh.rotation.x = rx;
    textMesh.rotation.y = ry;
    textMesh.rotation.z = rx; // :) 

    renderer.render(scene, camera);
};
render();
以下是我试图添加的停止渲染的内容(在另一个线程中找到此内容,但无法使其工作)

另一件事是,但这不应该是一个问题,我使用的滚动和视口可见性检测,这个库是highjacking滚动,所以基本的“滚动”是不工作的

暂停渲染的主要目标是大幅提高性能

如果有人发现此问题。

当元素在屏幕上/屏幕下时,可以使用获取事件

const statusElem=document.querySelector('.status');
屏幕上的常数=新设置();
const intersectionObserver=新的intersectionObserver((条目)=>{
entries.forEach(entry=>{
if(输入。isIntersecting){
在屏幕上添加(entry.target);
}否则{
屏幕上。删除(条目。目标);
}
});
statusElem.textContent=屏幕上的.size
?`屏幕上:${[…屏幕上].map(e=>e.textContent.join(',')}`
:“没有”;
});
document.querySelectorAll('.test').forEach(elem=>{
交叉观察者观察(elem);
});
正文{
字体大小:xx大号;
}
.测试{
填充:3em;
背景:橙色;
}
.地位{
位置:固定;
背景:rgba(0,0,0,0.8);
颜色:白色;
填充:1em;
字号:中等;
排名:0;
左:0;
}
a
Lorem ipsum dolor sit amet,quaestio principes ea eos。这是一种视觉反射。我们将在劳动博物馆为您提供一个智能的替代方案。逆境粘菌vix no,nec amet含量ea。海诺露西曼陀罗。设施类似于欧盟,主要用于治疗。

B 无论是谁,我都不知道该怎么做。没有vim,没有假定的prompta antiopam。不,不,不,不,不,在mel。没有圆顶的小豆豆。特写:圣彼得坦岛上的普赖斯-奥尔纳特斯-普林西比选区。

C
当元素在屏幕上/屏幕下时,可以使用获取事件

const statusElem=document.querySelector('.status');
屏幕上的常数=新设置();
const intersectionObserver=新的intersectionObserver((条目)=>{
entries.forEach(entry=>{
if(输入。isIntersecting){
在屏幕上添加(entry.target);
}否则{
屏幕上。删除(条目。目标);
}
});
statusElem.textContent=屏幕上的.size
?`屏幕上:${[…屏幕上].map(e=>e.textContent.join(',')}`
:“没有”;
});
document.querySelectorAll('.test').forEach(elem=>{
交叉观察者观察(elem);
});
正文{
字体大小:xx大号;
}
.测试{
填充:3em;
背景:橙色;
}
.地位{
位置:固定;
背景:rgba(0,0,0,0.8);
颜色:白色;
填充:1em;
字号:中等;
排名:0;
左:0;
}
a
Lorem ipsum dolor sit amet,quaestio principes ea eos。这是一种视觉反射。我们将在劳动博物馆为您提供一个智能的替代方案。逆境粘菌vix no,nec amet含量ea。海诺露西曼陀罗。设施类似于欧盟,主要用于治疗。

B 无论是谁,我都不知道该怎么做。没有vim,没有假定的prompta antiopam。不,不,不,不,不,在mel。没有圆顶的小豆豆。特写:圣彼得坦岛上的普赖斯-奥尔纳特斯-普林西比选区。

C
非常感谢!一切正常。我还成功地实现了停止和开始渲染,这是最后的工作代码笔,以防有人发现这个问题,因为我在谷歌搜索了很长一段时间,并找到了很好的解决方案:@gnam在代码中发现了wierdes bug,也许你可以帮我,因为你已经在这里了。我不知道为什么会这样,但这正在发生-当我重新加载画笔时,向下滚动停止/启动渲染可以工作-但是,当我首先在画布上移动鼠标,然后向下滚动以停止渲染时,停止渲染根本不起作用,我必须再次点击run(运行),所以wierd是,当我第一次滚动以停止渲染,然后使用“向上滚动”重新启动渲染时,我可以在画布上移动鼠标,stop/starp可以正常工作,当我做的第一件事是在画布上移动鼠标时,它就不起作用了,看起来像是一些层次结构问题,试图修复它,但失败了笔中的代码正在向观察者添加
。您希望将画布添加到观察者。例如
intersectionObserver.observe(renderer.domeElement)
问题在其他地方,即使我像这里一样将该类添加到画布包装器中,它仍然具有相同的奇怪行为。当我在移动鼠标之前向下滚动时,停止和重新启动工作正常,但当我第一次移动鼠标然后滚动出视图时,停止和重新启动不工作:/多谢!一切正常。我还成功地实现了停止和开始渲染,这是最后的工作代码笔,以防有人发现这个问题,因为我在谷歌搜索了很长一段时间,并找到了很好的解决方案:@gnam在代码中发现了wierdes bug,也许你可以帮我,因为你已经在这里了。我不知道为什么会这样,但这正在发生-当我重新加载画笔时,向下滚动停止/开始渲染可以工作-但是,当我首先在画布上移动鼠标,然后向下滚动以停止渲染时,停止渲染根本不工作,我
var stopRendering = (af) => {
    cancelAnimationFrame(af);
    isRendering = false;
};

window.addEventListener('scroll', () => {
    let scrollPosition = document.body.scrollTop;

    //element is almost about to be visible, time to start rendering
    if (scrollPosition >= ("#canvas-wrapper")-50) {
        if (everythingIsLoaded && !isRendering) {
            render();
            console.log('render has been started');
        } else {
            //wait until everythingIsLoaded is true
        }
    //element is not visible, stop rendering
    } else {
        //need to stop rendering here!
        if (render) {
            stopRendering(render);
            console.log('render has been halted');
        }
    }
});