• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Evaluaciones
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

315
Vistas
Problem with loading assets into canvas - Uncaught (in promise) DOMException: An attempt was made to use an object that is not, or is no longer usable

I'm trying to load images from my array using the drawImage canvas method. The problem is that it sometimes throws me the following error

Uncaught (in promise) DOMException: An attempt was made to use an object that is not, or is no longer, usable

↑ firefox ↓ google

Uncaught (in promise) DOMException: Failed to execute 'createImageBitmap' on 'Window': The source image width is 0.

Both on index.js:13

Sometimes if I load the page again the error disappears. Does anyone know what could be causing this problem?

My code:

BOE_tile_set.png

(async () => {
    const img = new Image();
    img.src = "./img/BOE_tile_set.png";

    let tiles = [];
    let tileWidth = 28;
    let tileHeight = 36;

    for (let i = 0; i < 77; i++) {
        let x = i % 8;
        let y = Math.floor(i / 8);

        let bmp = await createImageBitmap(img, x * tileWidth, y * tileHeight, tileWidth, tileHeight); // index.js:13

        tiles.push({
            bmp,
            x,
            y
        })
    }

    const canvas = document.querySelector("canvas");
    canvas.width = 224; // img.width
    canvas.height = 360; // img.height

    const ctx = canvas.getContext("2d");
    draw();

    function draw() {
        tiles.forEach((tile) => {
            ctx.drawImage(tile.bmp, tile.x * tileWidth, tile.y * tileHeight);
        })
    }

})();
almost 3 years ago · Santiago Gelvez
1 Respuestas
Responde la pregunta

0

createImageBitmap(HTMLImageElement) requires that the HTMLImageElement is fully loaded.

So either you do wait for its onload event, or, since it's a bitmap image and not an SVG one, you can await a call to its decode() method which does return a Promise for when the image has been fully loaded and decoded.

(async () => {
  const image = new Image();
  image.src = "https://upload.wikimedia.org/wikipedia/commons/c/cf/Black_hole_-_Messier_87.jpg?" + Math.random();
  try {
    const bmp = await createImageBitmap(image);
  }
  catch(e) {
    console.error("Before load failed:", e.message);
  }
  await image.decode(); // wait for the image to be fully loaded
  const bmp = await createImageBitmap(image);
  console.log("After load succeeded", bmp);
})();

But, still assuming that you are not using an SVG image, and also assuming that you are in a same-origin situation, then the best is to not use an HTMLImageElement at all. Indeed here we just created 2 occurrences of the bitmap data, once for the HTMLImageElement and once for the ImageBitmap. The former isn't going to be used anymore but still consumes computation and memory.

So the best is to fetch your image as a Blob, and call createImageBitmap on that Blob directly:

(async () => {
  const resp = await fetch("https://upload.wikimedia.org/wikipedia/commons/c/cf/Black_hole_-_Messier_87.jpg");
  if (!resp.ok) {
    return console.error("Network error", resp.status);
  }
  const blob = await resp.blob();
  const bmp = await createImageBitmap(blob);
  console.log(bmp);
})();

But once again this requires that your image can be fetched through AJAX (which is certainly the case for you since you use a relative path), and that the image is not an SVG image, because createImageBitmap(Blob) doesn't work with SVG images unless using my polyfill.

almost 3 years ago · Santiago Gelvez Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda