Three.js异常高帧率

时间:2016-12-29 15:59:41

标签: javascript reactjs iframe three.js

我昨天发布了this site(一个实时编辑网站three.js示例)并发现在更新代码或导航到多个示例文件时,帧速率猛增至1000 f / s左右

首先提到这一点是here。我不确定为什么更新后帧速率会增加。 WebGL画布在iframe中,我正在使用此代码更新iframe内容(iframe的id为'preview):

    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

2 个答案:

答案 0 :(得分: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,你会发现它会做更多的工作,但基本上就是它。

答案 1 :(得分:0)

为了构建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是不必要的,但想在全局项目中引用。