Lesson Description
The "Display Images on a Canvas" Lesson is part of the full, Award-Winning Marketing Websites course featured in this preview video. Here's what you'd learn in this lesson:
Matias discusses the process of animating a sequence of images. Image sequences are more performant than videos because they can animate forward or backward. The images are drawn on a canvas element to improve performance.
Transcript from the "Display Images on a Canvas" Lesson
[00:00:00]
>> Matias Gonzalez: The next topic is finally image sequences. So sometimes we want to attach some kind of video or animation to the scroll, and the way to go about implementing that is actually to split our video into multiple images, one image per frame, and then just update our background using that video.
[00:00:34]
Why not actually using videos is that videos are meant to be played forward, so if you were to try to play the video backwards, it's not going to perform very well because of how videos are compressed internally. Okay, so let's go into the page and let's preview what we are going to build.
[00:00:58]
So let's pull up the solution for this. So I went ahead and downloaded a 3D model and put that into Blender and just animated the camera and then I just rendered all of that into a sequence of images. So what we're going to do is actually implement this scroll sequence with different animations on it.
[00:01:33]
So here on the public folder we can see that there's a folder called sequence and here we have all of the frames compressed as WebP. WebP in general are very good format to use on the web. It maintains a really good, low weight and maintains the quality quite well.
[00:01:59]
So here we can see that we have, as I move on the frames, the image just progresses. So let's go ahead and implement that. So as I can see on the starter, I actually have all of the divs just one below the other stacked. So the first thing that I want to do is to first let's put all of them fixed because I just want them to appear on the screen and then fade in and fade out.
[00:02:34]
So let's just, instead of having them being relative, let's just put them as fixed. So the three sections that we have, I just changed them from relative to fixed so that they are all in place already. So let's start by animating the, creating the sequence and animating it, and then we're going to add animations for the text.
[00:03:24]
So how can we go about actually implementing a scroll sequence? What we want to do is to load all of the images and actually have a canvas, and every time that we progress on the scroll we are going to update that canvas with the image. The reason to use canvas is it's the easiest, most performant way to actually implement that.
[00:03:49]
So let's go ahead and create a component called scroll sequence, and it's going to return a canvas. That's going to make this canvas also position fixed and inset zero. It's actually at the border. Red to see that the canvas is there, and let's just add our canvas to the scroll.
[00:04:38]
So it should be here so that we can see it properly. I'm not seeing the canvas properly. Did I miss something? The border was spelled incorrectly on the canvas. You just missed a D. Canvas, more awesome things. I was about to spend like 15 minutes. Great. So how this part of the course is to spell border.
[00:05:08]
All right, now, let's see how we can use this canvas to actually draw a bunch of images. So let's first create a useEffect that we can use. So the way canvas works, let's actually also add the reference that I would need, so canvasRef, it's going to be useRef. Connect this reference.
[00:06:00]
So let's first start by grabbing that canvas, so const canvas is going to be my reference, so canvasRef.current, and then since this could be null, let's just check that it's not null to make things simpler, so canvas return. I usually like to do early returns with references to make things simpler to work with.
[00:06:30]
And how do we use canvas to paint things? So canvas is a really powerful tool, but it has a simpler API if we just want to just add an image or draw a square into a canvas. It's simpler, so I can just grab the context of the canvas. And when we get the context we can, let's say we are using WebGL to do some 3D stuff, we can grab the WebGL context, the WebGL 2 context, the WebGPU context, etc., etc.
[00:07:14]
We just want the 2D context because we're just going to paste an image of the canvas. We don't want it to do some crazy 3D stuff. So let's just grab the 2D context for it, and we also, I think, need to check if it exists because it could be null. So if the context doesn't exist, just return.
[00:07:45]
I also need to set the width and the height of the canvas, and this is like the, not the physical width and height, but how many pixels does it render, so I need to actually set up canvas.width is equal to the actual width of the canvas, so offsetWidth. Of 68. So by doing this, we're actually setting the rendering properties of the canvas, and we can actually, because if we resize the screen this might get messed up, so let's actually put this inside a callback function, so function resize.
[00:08:57]
Let's check that the canvas exists, so canvas return, and then let's first call it, and then add an event listener, so window.addEventListener resize. So if I resize the screen, I would just resize the canvas. Cool. So we haven't done much yet. We're ready to finally draw an image on a canvas.
[00:09:41]
Let's first load our image that we have on our public folder. Let's start by loading one image and then we're going to implement the complete sequence. So I'm going to create an image with JavaScript, so const image is going to be equal to new Image. We can put an image source.
[00:10:25]
Let's manually set the path, so it will be sequence, 001.webp. One more zero. Great, thanks, and then let's actually create a frame loop. So I'm going to do ticker.add because I would like to draw this image on every frame because we're going to update that later, so let's just do that inside of a frame loop.
[00:10:55]
So the way you would draw an image inside of the canvas, finally, let's first check that the canvas exists. So it's not canvas return or we don't have a context, return. We need to say, hey, context.drawImage, and we need to first provide an image, so I will put the image that I want to draw, and then we need to say where I want that image to be drawn, so I can set up where it will start, so at the zero, zero, so it will start at the corner, and then I can specify the width and height of the image, so let's just say like 50 pixels.
[00:12:03]
So this should draw us too small, let's just make it larger. This would draw my image on a square positioned, so this way we could already maybe make this image follow the mouse or do a lot of tricks like just editing these values, but what I want to do is just to draw the image using the canvas offsetWidth and canvas offsetHeight so that it's just covering the entire screen.
[00:12:40]
We do have an issue here that is that if I resize the screen, the image is going to change its aspect because we're just drawing it full size, so getting the calculation right for the position and width and height can be a little bit tricky. So I already added a utility that can do that for us and it will calculate where these values should be so that the image is covering the entire canvas.
[00:13:20]
It's right here on the utilities, it's called fitContent. So fitContent, if I import it, needs the container width, container height, and then also the content width and content height. This will be the image. So the content width would be the container width, then the content height will be the canvas height, and then we would need to actually access the image width and height, so image.width and image.
[00:14:08]
What this function is going to return, it's going to return an x value, a y value, a width, and a height that we can just use as a configuration to draw the image. So we can just plug in the x and y values, width, and the height. So if you just update this, I can see that right now, if the image is wider than my canvas, it's going to move it to the side, so the x is going to be negative, like the image will start here and then it will cover, the width is going to be way larger so that it maintains its aspect ratio, but if it happens with the height, it's going to draw it where it should be so that it's all well, it's covering the screen correctly.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops