【问题标题】:Abnormally High Frame Rate in Three.jsThree.js 帧率异常高
【发布时间】:2016-12-30 17:57:03
【问题描述】:

我昨天启动了this site(一个用于实时编辑three.js 示例的网站),发现在更新代码或导航到多个示例文件时,帧速率飙升至大约 1000 f/s。

第一次提到这个是here。我不确定为什么更新后帧速率会增加。 WebGL 画布位于 iframe 内,我正在使用此代码更新 iframe 内容(iframe 的 id 为“预览”):

    var previewFrame = document.getElementById('preview');
    var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
    preview.open();
    preview.write(this.props.code);
    preview.close();

有人知道如何解决这个问题吗?编辑使用CodeMirror 完成,站点使用React 构建。所有src代码都在repo here中。

【问题讨论】:

  • 我无法在 Chrome 版本 55.0.2883.95(64 位)中复制所描述的问题。

标签: javascript reactjs iframe three.js


【解决方案1】:

我猜你正在启动多个 requestAnimationFrame 循环。

例如

let numLoops = 0;
const countElem = document.querySelector("#count");
const stats = new Stats();
document.body.appendChild(stats.domElement);

function loop() {
  stats.update();
  
  requestAnimationFrame(loop);
}

function startLoop() {
  ++numLoops;
  countElem.textContent = numLoops;
  requestAnimationFrame(loop);
}

startLoop();

document.querySelector("button").addEventListener('click', startLoop);
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<button>Click to add another requestAnimationFrame loop</button>
<div>Num Loops Running: <span id="count"></span></div>

我使示例可编辑然后可在http://webglfundamentals.org 上运行的方法是使用 blob 在 iframe 中运行示例。每当用户选择“更新”时,我都会使用他们编辑的源生成一个新的 blob,然后将 iframe 设置为该新 blob 的 URL。这意味着示例会完全重新加载,因此浏览器会丢弃任何旧代码/循环/事件/webgl 上下文等。

你可以看到the code here是有效的

function runLastVersionOfUsersCode() {
  var url = getSourceBlob(usersEditedHtml);
  someIFrameElement.src = url;
}

var blobUrl;
function getSourceBlob(options, htmlForIFrame) {
  // if we already did this discard the old one otherwise
  // it will stick around wasting memory
  if (blobUrl) {
    URL.revokeObjectURL(blobUrl);
  }

  var blob = new Blob([htmlForIFrame], {type: 'text/html'});
  blobUrl = URL.createObjectURL(blob);
  return blobUrl;
}

如果您查看actual code for getSourceBlob,您会发现它做了更多工作,但基本上就是上面的内容。

【讨论】:

    【解决方案2】:

    为了在gman's 有用的答案的基础上进行构建,我在 React 渲染循环(而不是 threejs 渲染循环)中使用了 cancelAnimationFrame。提交在这里:https://github.com/ekatzenstein/three.js-live/commit/2cad65afa5fe066618a7aac179e096ee9e29ed76

    //in the iframe
    window.parent.three_live = requestAnimationFrame(animate)
    
    //in the parent, on render loop
    _resetAnimationFrame(){
         //disables abnormally high frame rates
         if(window.three_live){
             var previewWindow = document.getElementById('preview').contentWindow;
             previewWindow.cancelAnimationFrame(window.three_live);
         }
     }
    

    没有必要做window.parent,但想在全局项目中引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 2017-08-21
      • 1970-01-01
      • 2021-08-27
      • 2019-05-08
      • 2013-07-01
      • 1970-01-01
      相关资源
      最近更新 更多