šŸŽ Checkout my Learn React by Making a Game course and get 1 month Free on Skillshare!

HTML canvas redraw image on resize

So, how can we make an image drawn on an HTML canvas in a responsive way? There are two different steps here:

  1. do an initial responsive draw of the image on the canvas
  2. redrawing the HTML5 Canvas upon resizing

By the end of this article, we will build the below example:
HTML canvas redraw image on resize

If you want to skip ahead here is the full code of the example.

Step 1: Initial responsive draw of the image on the canvas

We have seen in a previous article how to draw an image, such as a png or jpeg, on an HTML 5 Canvas.

But that example draws at the same size as the original image. You give it a 300x300px image, to be drawn on a 300x300px canvas.

Given that we want our end result to be responsive, we will need to recalculate the canvas width and height based on the container's width. In this case the window.innerWidth.

Below is the Javascript code that will accomplish this:

const img = document.querySelector('#img')
const canvas = document.querySelector('#canvas')
const canvasContext = canvas.getContext("2d")

img.onload = ()=> {
    // first draw of the image
    drawCanvas()
}

function drawCanvas() {
    if (img.naturalWidth > window.innerWidth) {
        canvas.width = window.innerWidth;
        canvas.height = img.naturalHeight * ( window.innerWidth / img.naturalWidth );
    }
    else {
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
    }
    canvasContext.drawImage(img, 0, 0, canvas.width, canvas.height );
}

And the required HTML:

<canvas id="canvas"></canvas>
<img id="img" src="test.jpg" />

Step 2: Adding resize listeners and redrawing the canvas

Now, that we've made the initial canvas paint responsive the next step will be to watch for the resizing of the browser's window so that we can update the image that is drawn on the canvas.

Given that redrawing the image is quite a resource-intensive operation it's better to optimize with a debounce interval.

Basically, we are saying to redraw the image only when no other resize was not done in the past 1.5 seconds:

const img = document.querySelector('#img')
const canvas = document.querySelector('#canvas')
const canvasContext = canvas.getContext("2d")

img.onload = ()=> {
    // first draw of the image
    drawCanvas()
    // watch for window resize
    setResizeHandler()
}

function drawCanvas() {
    if (img.naturalWidth > window.innerWidth) {
        canvas.width = window.innerWidth;
        canvas.height = img.naturalHeight * ( window.innerWidth / img.naturalWidth );
    }
    else {ca
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
    }
    canvasContext.drawImage(img, 0, 0, canvas.width, canvas.height );
}

function setResizeHandler() {
    let timerId = null;
    window.addEventListener('resize', () => {
        if (timerId) {
            clearTimeout(timerId);
            timerId = undefined;
        }

        // 1.5sec after the  user stoped the resize
        // redraw the canvas on the new size
        timerId = setTimeout(() => {
            timerId = undefined;
            drawCanvas();
        }, 1500);
    });
}

And this is it! You can see the live example on Github pages and the full code here.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.


Leave a Reply

Your email address will not be published. Required fields are marked *