createImageBitmap 仅在页面重新加载后执行
Posted
技术标签:
【中文标题】createImageBitmap 仅在页面重新加载后执行【英文标题】:createImageBitmap only executing after page is reloaded 【发布时间】:2021-11-28 02:08:25 【问题描述】:当我加载我的网页时,createImageBitmap 行没有运行并且我的承诺列表为空,但是当我重新加载页面时,承诺在列表中,并且列表似乎在函数被调用。这会导致问题并使我的游戏崩溃,因为没有将承诺解析为图像。
为什么会发生这种情况,我可以做些什么来解决它?
这是修改后的代码摘录:
Spritesheets =
tileset_grass : new Image(),
tileset : new Image(),
player : new Image(),
crawler : new Image(),
creature : new Image(),
items : new Image(),
particles : new Image()
;
Spritesheets.tileset_grass.src = "images/tileset_grass.png";
Spritesheets.tileset.src = "images/tileset.png";
Spritesheets.player.src = "images/player.png";
Spritesheets.crawler.src = "images/crawler.png";
Spritesheets.creature.src = "images/creature.png";
Spritesheets.items.src = "images/items.png";
Spritesheets.particles.src = "images/particles.png";
// separates spritesheets into separate sprites
Images =
tileset_grass :
spriteW : 16,
spriteH : 18
,
tileset :
spriteW : 16,
spriteH : 16
,
player :
spriteW : 16,
spriteH : 16
,
crawler :
spriteW : 16,
spriteH : 16
,
creature :
spriteW : 16,
spriteH : 16
,
items :
spriteW : 16,
spriteH : 16
,
particles :
spriteW : 16,
spriteH : 16
,
;
console.log(Images)
function loadSprites()
for(let i = 0; i < Object.keys(Images).length; i++)
for(let k = 0; k < Spritesheets[Object.keys(Images)[i]].naturalWidth / Images[Object.keys(Images)[i]].spriteW; k++)
Images[Object.keys(Images)[i]][k] = createImageBitmap(Spritesheets[Object.keys(Images)[i]], k * Images[Object.keys(Images)[i]].spriteW, 0, Images[Object.keys(Images)[i]].spriteW, Images[Object.keys(Images)[i]].spriteH);
;
;
console.log(Images)
;
loadSprites();
【问题讨论】:
【参考方案1】:当将 htmlImageElement 作为createImageBitmap()
的源传递时,该元素必须处于解码状态,即其load
事件必须已触发。
当您重新加载页面时它会起作用,因为您很幸运,并且图像从缓存中加载得足够快。
因此,您可以在调用所有 createImageBitmap()
之前等待所有这些 HTMLImageElements 的 load
事件,或者您可以通过将所有资源作为 Blob 获取并创建 ImageBitmap 来重构代码以使其更快*直接来自这些 Blob,但是您需要将图像的大小以及裁剪选项存储在 JS 中。
Spritesheets =
tileset_grass : "images/tileset_grass.png",
tileset : "images/tileset.png",
player : "images/player.png",
crawler : "images/crawler.png",
creature : "images/creature.png",
items : "images/items.png",
particles : "images/particles.png"
;
// separates spritesheets into separate sprites
Images =
tileset_grass :
// add the image's width and height info here (or somewhere else)
width: XXX,
height: XXX,
spriteW : 16,
spriteH : 18
;
async function loadSprites()
const keys = Object.keys(Images);
for(let i = 0; i < keys.length; i++)
const key = keys[i];
// fetch as Blob
const blob = await fetch(Spritesheets[key]).then(resp => resp.ok && resp.blob());
const img = Images[key];
for(let k = 0; k < img.width / img.spriteW; k++)
img[k] = await createImageBitmap(blob, k * img.spriteW, 0, img.spriteW, img.spriteH);
;
;
console.log(Images)
;
它不一定会像花更少的挂钟时间来执行那样“更快”,但它可以让浏览器做更少的工作并同时优化其他任务。
【讨论】:
以上是关于createImageBitmap 仅在页面重新加载后执行的主要内容,如果未能解决你的问题,请参考以下文章
如何仅在 Angular 的某些页面上显示标题组件(现在它仅在重新加载时显示)
仅在 html 代码中使用 javascript 重新加载特定页面一次
Jquery Mobile:“pageshow”事件仅在 Shift F5(完全重新加载)时触发,但在加载另一个页面或具有不同查询的同一页面时不会触发