Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

241
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!