【发布时间】:2014-11-04 16:50:25
【问题描述】:
我的问题
我们的目标是确保在新游戏开始之前所有图像都已完全加载。我的第二个解决方案(Fiddle B)比我的第一个解决方案(Fiddle A)更一致、更准确地实现了这个目标。 为什么?
JSFIDDLE A
JSFIDDLE B
方法
这是我的两种小提琴解决方案预加载图像的方法:
- 游戏所需的所有资源都有一组绝对图像 URL
- init() 函数有一个 for 循环,它为数组中的每个 URL 生成一个新的画布 Image()
- 每个新创建的图像都被推入另一个数组
- 所以,我们现在有了包含 URL 字符串的第一个数组,以及包含“HTMLImageElement”对象的第二个数组
Fiddle B 与 Fiddle A 的不同之处在于它利用了 '.onload' 事件以及一个计数器。这两个 fiddles 使用不同的方法来检查是否所有图像资源都已加载:
Fiddle A:比较两个数组的长度。如果他们匹配,开始游戏
for (var i = 0; i < allGameImageUrls.length; i++) {
var img = new Image();
img.src = allGameImageUrls[i];
allGameImages.push(img);
console.log(allGameImages.length);
if (allGameImages.length >= allGameImageUrls.length) {
setUpGame();
} else {
// images haven't loaded yet
console.log('STILL LOADING');
STAGE.fillText("Loading ...", 20, 400);
}
}
Fiddle B: 将第二个数组长度与计数器变量进行比较。每次图像的 '.onload' 事件完成时,此计数器都会增加 1。
for (var i = 0; i < allGameImageUrls.length; i++) {
var img = new Image();
img.onload = function () {
assetCount++;
console.log('assetCount = ' + assetCount);
setUpGame();
};
img.src = allGameImageUrls[i];
allGameImages.push(img);
}
我的问题已扩展
Fiddle A 经常(但并非总是)在完整的图像资产列表正确加载之前触发新游戏的开始,从而导致游戏错误。 Fiddle B 在允许新游戏开始之前始终加载所有图像资源。这可以从写入画布的“完全加载”消息中的两个小提琴中看到。
虽然我可以看到 Fiddle A 比 Fiddle B 工作得更好,但我不明白为什么它更优越。并非所有与加载 HTMLImageElements 相关的教程都使用“.onload”,不使用它的教程似乎完全足够了。
此外,我不明白为什么比较两个数组的长度不如将第二个数组长度与计数器比较准确。
我了解如何这两种解决方案不同,但我想知道为什么解决方案 B 比解决方案 A 更有效。
以往的研究
这里只是我之前为了回答我自己的问题所做的一些研究的例子。
- An article on pre-loading images 没有任何对 .onload 事件的引用
- this question 的公认解决方案不使用 .onload 事件,但它仍然有效
- this other question 的公认解决方案与我的 Fiddle B 非常相似(尽管我后来才发现它)。但是,解决方案的解释并没有帮助我回答我自己的问题。
【问题讨论】:
-
写得很好的问题,+1!
-
你说有,但我看不到.. 小提琴 A 在哪里检查图像是否已加载? AFAIK 如果不使用加载事件,您无法判断是否下载了图像。
-
@Malk,小提琴 A 假设如果图像对象数组的长度与 URL 数组的长度匹配,则图像必须已加载。这样做的逻辑是有缺陷的,但当时我没有注意到,因为我使用此代码创建的游戏仍然有效(除了问题中描述的问题)。
-
您现在看到,仅仅创建 HTMLImageElements 并不意味着图像已下载并准备好使用(这是异步发生的)。另外,我检查了你所有的链接,它们都使用了 onload。
-
@Malk 你是对的链接。我不知道我第一次是怎么错过的,我花了很长时间阅读这个。谢谢!
标签: javascript arrays html5-canvas theory