1

So I am in the middle of a project and needed to paste some pixelart icons I made in asesprite into my HTML. I tried it with an img-tag at first but it became blurry, so I found this website and got the idea of making a general function wich I could use on several images and canvases. Then I made this function:

const pasteOnCanvas = (imageSource, canvasID) => {
const canvas = document.querySelector('#' + canvasID);
const context = canvas.getContext('2d');
    base_image = new Image();
    base_image.src = imageSource;
    base_image.onload = function(){
    context.drawImage(base_image, 0, 0);
}
}
pasteOnCanvas("images/heart_icon.png", "hp-icon");
pasteOnCanvas("images/sword_icon.png", "attack-icon");

It does work on one canvas, but when you call the function several times it just pastes the last image on every canvas. Is there any way to fix this so that it works?

Here is my HTML code:

<canvas id="hp-icon" class="pixelart-image" width="16" height="16"></canvas>
<canvas id="attack-icon" class="pixelart-image" width="16" height="16"></canvas>

And my CSS:

.pixelart-image {
height: 128px;
width: 128px;
image-rendering: crisp-edges;
image-rendering: pixelated;
}
Betelgeuse
  • 11
  • 2
  • 1
    You are missing the `const` keyword before `base_image = new Image();`. So this `base_image` variable is in the global scope and it's always the same only one that gets overwritten. So when the various `onload` events fire, they'll use the last `Image` that got assigned to that variable. Use `"use-strict";` to avoid this kind of mistakes. – Kaiido Mar 16 '21 at 02:27

1 Answers1

0

You should set the image src after you've added the eventListener, like so

const pasteOnCanvas = (imageSource, canvasID) => {
    ...

    base_image.addEventListener('load', () => context.drawImage(base_image, 0, 0));
    base_image.src = imageSource;
}

...

This way, the eventListener is already waiting for the image.

For all we know, the image could be so small that immediately you set it, it's done loading, so it's best to do it this way.

It's also advisable for you to stop using onevent and use addEventListener

a.mola
  • 3,883
  • 7
  • 23
  • Actually per specs browsers have to effectively set the `src` value in the next microtask. This allows to set event handlers and to avoid useless requests if you set it ten time in the same task, but more importantly it allows to set afterward properties like `crossOrigin` which have influence on how the fetching should be done. There used to be some browsers who would fail to attach an event handler on img's declared in HTML markup (), but I believe they all did fix that too now. – Kaiido Mar 16 '21 at 02:20
  • I understand what you mean, but if the image has already loaded before the `eventListener` is even set. The function wouldn't run. @Kaiido – a.mola Mar 16 '21 at 02:33
  • yes, that's the point. Because the `src` isn't set before the next microtask, if you do `img.src = url; img.addEventListener("load", fn)`, you are ensured that the load event handler will fire, even with dataURLs or cached images. – Kaiido Mar 16 '21 at 03:03