如何在不降低 EaselJS / CreateJS 中的帧速率的情况下实例化大型 MovieClip

How to instantiate large MovieClip without slowing framerate in EaselJS / CreateJS

一点背景: 我在 Flash Pro / Adob​​e Animate 中创建了一个带有时间轴动画的详细 MovieClip,并导出到 CreateJS / EaselJS 库。当我在运行时实例化它时,它需要比一帧或 'tick' 更长的时间才能完成此实例化,并且动画播放会在前进到下一帧之前等待。这会导致正在播放的动画出现问题。这是一个在我的项目中经常出现的问题。如何在不简化 MovieClip 中的框架艺术的情况下克服这个问题?

代码:如果不清楚,我说的就是这个...

var instanceMC = new lib.bigMovieClip_mc(); // <-- LONG DELAY, OVER 1 TICK IN TIME

stage.addChild(instanceMC); // <-- from here on it seems to run smoothly
instanceMC.x = xPosition;
instanceMC.y = yPosition;
stage.update();

我的想法:

  1. 如果异步实例化是一个选项,那将很适合我的情况,但我不知道是否可以以及如何完成。我看到它可以为 SpriteSheetBuilder 完成,这是类似但不同的情况(我不能使用 SpriteSheetBuilder,因为我嵌套了独立控制的 MovieClips)。
  2. 我可以将 MovieClip 分解成更小的 MovieClip 并独立实例化它们,然后 assemble 将它们组合在一起。这有点烦人,但可行。如果我这样做了,我会想要监听每个实例化完成的事件。这样的事件存在吗?我在文档中找不到。
  3. 加载JS。我对 LoadJS 很陌生。我查了一下,好像是管理下载的,不是其他的初始化任务。但是,如果它可以将一系列大型实例化添加到加载队列(或者如果有类似的东西),并且在实例化期间不阻止时间线播放,那会很好。
  4. 多个canvasES和阶段?如果我添加第二个 canvas 和它自己的阶段,我想每个阶段都会有独立的帧代码,因此,通过在一个阶段实例化我的 MovieClip 并在另一个阶段播放我的动画,我可以分离实例化和回放。在我的特定情况下,应用程序的每个部分都是非常独立的,因此在使用过程中切换 canvas 在某种程度上是可行的。我宁愿不处理将应用程序分成两部分的杂耍,但这似乎也是一种无需深入研究功能即可解决问题的直接方法。这在技术上是否可行,还是我做出了错误的假设?

求助:您可以建议哪种方法(列出或未列出)来解决我的问题?

首先,希望有人补充比这更好的答案,我会很乐意更改选择的答案。

我在某种程度上研究了各种选项,了解到这实际上是一个非常根深蒂固的问题。它与浏览器的单线程特性有关,UI 更新使用相同的线程并且必须等待轮到它们。参见:here, here, here, and here.

从头开始设计 CreateJS 等库以尽可能清除调用堆栈并利用回调队列可以避免在它们自己的操作(如 MovieClip 的实例化)期间锁定 UI。 (实际上,这会暂停每一帧的复杂操作代码。)这是对付这种野兽的最佳方法。据我所知,MovieClips 的实例化在 CreateJS 中没有这样的支持,尽管在 运行time 中构建 spritesheets 有一个 'async' 选项,当然,LoadJS 运行s 是异步的很好(但据我所知不支持代码的执行)。据推测,我的非常大的 MovieClip 将被认为超出了创作者的预期用途范围。

我的解决方案是在 运行 应用程序之前预加载所有动画片段并显示预加载器。这不是一个理想的解决方案,因为它有很长的等待时间,但它比我需要的替代方案效果更好(即更少的劳动力)。更好的方法可能是将有问题的 MovieClip 分解为不会独立引起问题的较小 MovieClip,然后像这样实例化它们:

setTimeout( function(){ firstMovieClip = new lib.firstMovieClip(); },0);
setTimeout( function(){ secondMovieClip = new lib.secondMovieClip(); },0);
 and so on....

这导致他们不是直接入栈,而是进入回调队列。这又允许 UI 在这些较小的实例化之间进行更新,因为堆栈已清除。

对于它的价值,还有 运行 浏览器中带有网络工作者的额外线程的选项。它对我的目的不起作用,因为无法将这些 web worker 中的对象移动到 UI。对于具有简单结果(如数字)的复杂计算,这将是一个很好的解决方案。