为什么 THREE.ColladaLoader 会停止站点上的所有 activity?
why would THREE.ColladaLoader halt all activity on the site?
我正在加载一个动画 .dae 文件,我使用了 'onProgress' 参数来查看它的加载进度。文件在 2 秒内加载到 74%,但随后整个页面在模型实际加载之前又暂停了 23 秒(以及所有其他 activity 暂停,包括 css 动画)。我添加了一个 setInterval() 来显示进度,但一旦加载程序达到 74%,它也会停止。
在页面加载时,这是我的代码:
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('models/swing_dancing.dae', function(collada) {
dae = collada.scene;
dae.traverse(function(child) {
if (child instanceof THREE.SkinnedMesh) {
var animation = new THREE.Animation(child, child.geometry.animation);
animation.play();
}
});
dae.scale.x = dae.scale.y = dae.scale.z = 0.002;
dae.updateMatrix();
init();
animate();
}, function(xhr) {
console.log(('progress ' + xhr.loaded / xhr.total * 100) + '% loaded')
});
有什么想法吗?我正在构建 example here and documentation here
那是因为JS是单线程的,一旦加载文件,什么是异步的,它就开始解析它并创建一切,这就是所谓的"blocking"进程,因为它使用一个线程在完成之前可用于 JS。之后您的动画将恢复。虽然这样的进程是 运行,但 UI 被冻结或阻止。发生这种情况是因为处理时间比单帧的持续时间 (1000/60ms) 长得多,因此浏览器无法更新 ui 和所有其他动画。
唯一的出路是将解析和创建任务拆分为多个较小的任务,可以在每个动画帧一个一个地执行,或者设置超时。这样您 运行 动画将在此期间获得一些处理时间。
举例说明:
ms | frame | task
------+-------+-------------
0 | 0 | update preload animation
..........................................
n | m | update preload animation + start to process data from server
------------------------------------------
h | m+1 | processing (parsing *dea, creating objects)
------------------------------------
h+3s | m+2 | processing done, animation and UI updates continue
所以帧 m+1
将长约 3 秒,但应该是 100/6 ms
,这就是你的动画卡住的原因。
要在初始化为 运行 时显示动画,您需要每一帧都需要这样的东西:
frame n update Animation, process subtask (<-- this must not take too long)
frame n+1 .
frame n+2 .
frame n+3 .
Until all substasks are executed
菲利普说的是对的。但是我只想补充一点,除了使用 setTimeout 之外,您可能还想尝试在 webworker 中解析 collada 文件。有一些库已经可以执行此操作,您可以使用:https://github.com/jagenjo/collada.js/tree/master
我正在加载一个动画 .dae 文件,我使用了 'onProgress' 参数来查看它的加载进度。文件在 2 秒内加载到 74%,但随后整个页面在模型实际加载之前又暂停了 23 秒(以及所有其他 activity 暂停,包括 css 动画)。我添加了一个 setInterval() 来显示进度,但一旦加载程序达到 74%,它也会停止。 在页面加载时,这是我的代码:
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('models/swing_dancing.dae', function(collada) {
dae = collada.scene;
dae.traverse(function(child) {
if (child instanceof THREE.SkinnedMesh) {
var animation = new THREE.Animation(child, child.geometry.animation);
animation.play();
}
});
dae.scale.x = dae.scale.y = dae.scale.z = 0.002;
dae.updateMatrix();
init();
animate();
}, function(xhr) {
console.log(('progress ' + xhr.loaded / xhr.total * 100) + '% loaded')
});
有什么想法吗?我正在构建 example here and documentation here
那是因为JS是单线程的,一旦加载文件,什么是异步的,它就开始解析它并创建一切,这就是所谓的"blocking"进程,因为它使用一个线程在完成之前可用于 JS。之后您的动画将恢复。虽然这样的进程是 运行,但 UI 被冻结或阻止。发生这种情况是因为处理时间比单帧的持续时间 (1000/60ms) 长得多,因此浏览器无法更新 ui 和所有其他动画。
唯一的出路是将解析和创建任务拆分为多个较小的任务,可以在每个动画帧一个一个地执行,或者设置超时。这样您 运行 动画将在此期间获得一些处理时间。
举例说明:
ms | frame | task
------+-------+-------------
0 | 0 | update preload animation
..........................................
n | m | update preload animation + start to process data from server
------------------------------------------
h | m+1 | processing (parsing *dea, creating objects)
------------------------------------
h+3s | m+2 | processing done, animation and UI updates continue
所以帧 m+1
将长约 3 秒,但应该是 100/6 ms
,这就是你的动画卡住的原因。
要在初始化为 运行 时显示动画,您需要每一帧都需要这样的东西:
frame n update Animation, process subtask (<-- this must not take too long)
frame n+1 .
frame n+2 .
frame n+3 .
Until all substasks are executed
菲利普说的是对的。但是我只想补充一点,除了使用 setTimeout 之外,您可能还想尝试在 webworker 中解析 collada 文件。有一些库已经可以执行此操作,您可以使用:https://github.com/jagenjo/collada.js/tree/master