簡體   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