Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

239
Visualizações
Is there a way to draw pieces of the image on 2d canvas without transparent parts?

I would like to draw this image on canvas without the transparent parts. The principle of my rendering is that I crop small images from a large image using the createImageBitmap method and store them in an array. I then render them on the canvas one by one. The problem is that it also unnecessarily draws the transparent parts. So if I log my array I get this. Since my map is 10x10 tiles it results in 100 images (of which 96 are useless). Instead, I would like to save only 4 images.

Not only that it messes up my performance but I have more reasons why it bothers me. Is there a way to solve this problem?

My code so far:

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

    let tiles = [];
    let tileWidth = 32;
    let tileHeight = 32;

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

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

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

    console.log(tiles)

    const canvas = document.querySelector("canvas");
    canvas.width = 320;
    canvas.height = 320;

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

    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

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

        // requestAnimationFrame(draw)
    }
    draw();

})();
about 4 years ago · Santiago Gelvez
1 Respostas
Responde à pergunta

0

The best is to prepare your asset correctly, so here that would mean having only the 3 unique sprites in your atlas:

OP's atlas without the transparent slots

Then you can use your simple loop to get these as separate objects.

However it's not uncommon to have sprites of different sizes in the same atlas, in such a case, your simple loop won't do. Instead, you should prepare a coordinates dictionary (e.g as a JSON file, or embedded directly in your js), with all the coordinates of each sprites.

Most spritesheet generating tools will produce this for you.

Here is an example where I just added one big sprite to the atlas:

Atlas of 3 small sprites and one big

(async () => {
    // If you are same-origin, it's better to fetch as a Blob
    // and create your ImageBitmap from the Blob
    // Here we aren't, so we have to go through an <img>
    const img = new Image();
    img.src = "https://i.stack.imgur.com/h7w1C.png";
    await img.decode();
    document.body.append(img);
    // We hardcode the coords of each sprite
    const map = [
      // [x, y, w, h]
      [0,  0, 32, 32],
      [0, 32, 32, 32],
      [0, 64, 32, 32],
      [32, 0, 96, 96],
    ];
    const tiles = [];
    
    for (const [x, y, w, h] of map) {
        const bmp = await createImageBitmap(img, x, y, w, h);
        tiles.push({
            bmp,
            x,
            y
        })
    }

    console.log(tiles)

    const canvas = document.querySelector("canvas");
    canvas.width = 320;
    canvas.height = 320;

    const ctx = canvas.getContext("2d");
    let m = 0;
    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        m = (m + 0.005) % 0.5;
        const margin = m + 1;
        tiles.forEach((tile) => {
            // we add some margin to show these are separate bitmaps
            ctx.drawImage(tile.bmp, tile.x * margin, tile.y * margin);
        })

        requestAnimationFrame(draw)
    }
    draw();

})().catch(console.error);
.as-console-wrapper { max-height: 100px !important }
<canvas></canvas>

about 4 years ago · Santiago Gelvez Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda