2

I want to draw a border around an image after it is loaded using new Image()

This works, I see the border, but modifying image.src inside the onload function calls onload again in an infinite loop. But how can I alter the image otherwise?

let image = new Image();
image.onload = function () {
    console.log("onload");
    let canvas = document.createElement('canvas');
    let ctx = canvas.getContext('2d');
    ctx.drawImage(image, 0, 0);
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 5;
    ctx.strokeRect(0, 0, image.width, image.height);
    image.src = canvas.toDataURL();
};
image.src = "https://placehold.co/600x400";
document.body.appendChild(image);

2
  • 2
    Why not a css border? Please include a minimal reproducible example. Commented Jul 24 at 13:28
  • I assume because OP wants to embed the border into the image. Commented Jul 24 at 15:50

2 Answers 2

2

You apply the canvas value to the same <image>, so the onLoad will run again, going into an infinite loop.

I'd use a temporary image to load the src and then in the onLoad apply it to your actual image element

let tmpImage = new Image();
tmpImage.setAttribute('crossorigin', 'anonymous')
tmpImage.onload = function () {
    console.log("onload");
    let canvas = document.createElement('canvas');
    canvas.width = tmpImage.width;
    canvas.height = tmpImage.height;
    
    let ctx = canvas.getContext('2d');
    ctx.drawImage(tmpImage, 0, 0);
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 5;
    ctx.strokeRect(0, 0, tmpImage.width, tmpImage.height);
    
    let image = new Image();
    image.src = canvas.toDataURL();
    document.body.appendChild(image);
};
tmpImage.src = "https://placehold.co/600x400";

Sign up to request clarification or add additional context in comments.

1 Comment

That's what I am looking for, thanks!
1

If you want to keep your code reusing the image variable, you can always reset the onload property, or remove the event listener, like for example:

// set
image.onload = null;

// before
image.src = "something";

2 Comments

Thanks, you are right, that fixes it in my minimal reproducible example. In my real program it is called in a loop with many images so onload needs to be restored after each call somehow. Tricksy...
@JonWilson It'd be best to add that loop to your example. Otherwise, it's too minimal and doesn't capture your actual use case with appropriate fidelity. This approach should still be feasible with multiple images.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.