So, how can we make an image drawn on an HTML canvas in a responsive way? There are two different steps here:
- do an initial responsive draw of the image on the canvas
- redrawing the HTML5 Canvas upon resizing
By the end of this article, we will build the below example:
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.