【问题标题】:createImageBitmap only executing after page is reloadedcreateImageBitmap 仅在页面重新加载后执行
【发布时间】: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();

【问题讨论】:

    标签: javascript promise imagebitmap


    【解决方案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)
    };
    
    • 它不一定会像花更少的挂钟时间来执行那样“更快”,但它可以让浏览器做更少的工作并同时优化其他任务。

    【讨论】:

      最近更新 更多