Estoy tratando de cargar imágenes de mi matriz usando el método de lienzo drawImage. El problema es que a veces me tira el siguiente error
No capturado (en promesa) DOMException: se intentó usar un objeto que no es, o ya no es, usable
↑ firefox ↓ google
No capturado (en promesa) DOMException: no se pudo ejecutar 'createImageBitmap' en 'Ventana': el ancho de la imagen de origen es 0.
Ambos en index.js:13
A veces si vuelvo a cargar la página desaparece el error. ¿Alguien sabe qué podría estar causando este problema?
Mi código:
(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); }) } })();
createImageBitmap(HTMLImageElement)
requiere que HTMLImageElement
esté completamente cargado.
Entonces, espera su evento de onload
o, dado que es una imagen de mapa de bits y no SVG, puede esperar una llamada a su método decode()
que devuelve una Promesa para cuando la imagen se haya cargado y decodificado por completo.
(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); })();
Pero, aún suponiendo que no está utilizando una imagen SVG, y también suponiendo que se encuentra en una situación del mismo origen, entonces lo mejor es no usar HTMLImageElement
en absoluto. De hecho, aquí acabamos de crear 2 ocurrencias de los datos de mapa de bits, una para HTMLImageElement y otra para ImageBitmap. El primero ya no se utilizará, pero aún consume computación y memoria.
Entonces, lo mejor es obtener su imagen como un blob y llamar directamente a createImageBitmap
en ese blob:
(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); })();
Pero, una vez más, esto requiere que su imagen se pueda obtener a través de AJAX (lo que sin duda es su caso, ya que usa una ruta relativa), y que la imagen no sea una imagen SVG, porque createImageBitmap(Blob)
no funciona con SVG imágenes a menos que use mi polyfill .