繁体   English   中英

Three.js - 当不可见/超出视口时停止渲染场景

[英]Three.js - stop rendering scene when not visible / out of viewport

我正在制作一个使用大量 js 和动画的网站,第一部分是全屏的 Three.js 场景,它随着鼠标移动而移动。 场景本身很好,但即使我没有查看three.js webgl画布并且它产生性能问题,而其他动画在网站上发生较低时,一切也一直在渲染。

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

这是渲染功能:

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();

这是我尝试添加以停止渲染的内容(在此处的另一个线程上找到了它,但无法使其工作)

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');
        }
    }
});

这是完整的代码笔

另一件事是,但这应该不是问题,我正在使用机车滚动库进行滚动和视口可见性检测,并且该库正在劫持滚动,因此基本的“滚动”不起作用。

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

如果有人发现这个问题,请在此处使用解决方案

当元素在屏幕上/屏幕外时,您可以使用IntersectionObserver来获取事件。

 const statusElem = document.querySelector('.status'); const onScreen = new Set(); const intersectionObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { onScreen.add(entry.target); } else { onScreen.delete(entry.target); } }); statusElem.textContent = onScreen.size ? `on screen: ${[...onScreen].map(e => e.textContent).join(', ')}` : 'none'; }); document.querySelectorAll('.test').forEach(elem => { intersectionObserver.observe(elem); });
 body { font-size: xx-large; } .test { padding: 3em; background: orange; } .status { position: fixed; background: rgba(0,0,0,0.8); color: white; padding: 1em; font-size: medium; top: 0; left: 0; }
 <div class="test">a</div> <p>Lorem ipsum dolor sit amet, quaestio principes ea eos. Feugait ocurreret mea ea. Wisi altera intellegebat vix an, sed iuvaret tincidunt adipiscing ea, at debet iudico labores eum. Mucius adversarium vix no, nec amet contentiones ea. Sea noluisse mandamus referrentur cu. Facilisis similique quo eu, pri alii noluisse efficiantur in. </p> <div class="test">b</div> <p> Sea cu vidit neglegentur, te pro maluisset accusamus, ad est diceret iudicabit. Honestatis referrentur no vim, per no putant prompta antiopam. Est singulis vituperata no, adhuc nonumy consectetuer quo cu, quas primis at mel. No doming fabulas admodum est. Cu usu ornatus principes constituam, sint petentium at quo. </p> <div class="test">c</div> <div class="status"></div>

然后您可以使用它来开始/停止渲染这些元素

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM