Lesson Description
The "Custom Cursor Animation with Lerp" 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 creates a custom cursor animation. A div element follows the course, but uses a Lerp animation technique to animate to the new position each time the cursor moves. This adds easing to the animation and creates a "follow" effect.
Transcript from the "Custom Cursor Animation with Lerp" Lesson
[00:00:00]
>> Matias Gonzalez: So the thing that we're going to build next is a little effect that will follow my mouse and then it will do that smoothly and then when I hover over this start button, it will just snap into it. So we'll see how we can combine different effects in order to achieve this trick. Go ahead and know it's a solution.
[00:00:36]
Go ahead and pull out the starter. So as you can see here on the styles I already set up the cursor component. It's basically a square div and I can control the components using different variables. I can control its width, its height, the x property, and then the y property. So I can see that it's been like right there on the corner if I move it.
[00:01:07]
Like this, I can just see how it will move. So it is to measure where my mouse is and then just animate that element into my mouse. Let's go ahead and reset this. So as we saw before, in order to detect a mouse movement, we can just add an event listener, so let's add the effect.
[00:01:46]
And then let's do first create a controller as we saw before, so const controller is equal to new AbortController. Let's already clean that up so that we don't forget later. And then let's create our events listeners, so that will be window.addEventListener. And I want to listen for the mousemove.
[00:02:22]
And then I want to get the position of the mouse every time I just move it so event. And then const x is going to be event.clientX and then the y position is going to be event.clientY. Let's go ahead and update my CSS variables to match with these two, as we saw before. I'm going to create a reference to const mouseRef.
[00:03:02]
It's going to be equal to useRef. No, I always like to type my references, so HTMLElement. And let's connect my ref to the cursor. So if the reference exists. I'm going to update its styles. It says mouseRef.current.style.setProperty. And I'm going to set the x property to be x.toString and I also need to set the same for the y-axis.
[00:03:57]
So here, this is just a number, and we actually need pixels, so we have two options. I can either add pixels to my string or what I can just do is go ahead and multiply this number by 1 pixel. So let's just remove the number from the defaults and. So it that way. So as we can see, the element is following perfectly my mouse.
[00:04:37]
But this is not exactly what we saw before before we were, it was following but kind of smoothly. So the last trick, the next trick that we are going to see is how to smoothly interpolate two values. So let's say that I have a value of a and a value of b and I want to animate that value from a to b smoothly.
[00:05:07]
So one thing that I can do is to lerp those values, so I'm going to pull quickly back the presentation. So how does lerp work is I'm going to have a value a and a value b and. Lerp is basically going to take value a and b and I will provide a number between 0 and 1 and it's going to give me a value that is on that range and exactly using that third value as a factor.
[00:05:45]
So if this value is 0, the result will be 0 and if this value were to be 1, the result is going to be 100. So in this case, since I am just using 0.5, it's kind of an average. So the lerp function is basically a linear interpolation between two values. Usually you can interpolate either like numbers, you could do it with vectors, for example, and you can also do that with colors, but this by itself wouldn't be an animation.
[00:06:21]
It would just get a value in between. So what I need is to repeat this operation so. If this is my cursor follower and this is my mouse, what I would do is I would first lerp the position and then lerp it again and then lerp again and then again and again and again until the animated object reaches perfectly my cursor.
[00:06:50]
And not only that, but as we can see it will like smooth out because as it gets closer, the distance that it progresses will be smaller. So it's useful for like things that follows other things because if they are farther away they will move faster and they will slow down. Let's go and implement that functionality, so what I want to do is, I'm going to store this x and y values into a reference first.
[00:07:38]
So let's go ahead and grab this const cursorPosRef. It's going to be just ref. And so what I want to do is I'm going to create an object inside a reference with an x and y values. So x and y are going to be 0 at the beginning. And then I want to have a second object that's going to be called the target.
[00:08:03]
So what I'm going to do is, every time I move my mouse I'm going to update the target position that I want to animate into. And then on every frame, I'm going to animate the actual position of the mouse so that it will like smoothly follow it. The reason again for using references is that if I were to use states I would just need to do setState on every frame and that will just cost a lot of rerenders for just updating one value so I usually just use references for storing objects and then just doing some math with them.
[00:08:50]
So how do I run this smooth interpolation on every frame? Let's first update this, so it's coming this out. I'm going to grab the cursorTarget.current.x. And I'm going to set that to the x position and then I'm going to do exactly the same for the y-axis, so x and y. So every time I move the mouse this reference.
[00:09:26]
It's going to be updated. So now how do I run a function on every single frame? Well, there is a JavaScript function called that for that called requestAnimationFrame. So the way requestAnimationFrame works is that I would create the callback so const callback. And I'm going to run requestAnimationFrame inside of that callback.
[00:10:01]
So what this function does is it will call this function on the next frame. It will not call it immediately, it will schedule this function to run on the exact next frame that we are on. And since we are calling the same function that we are on, this function is run like it's going to run like again and again and again and again in each frame basically.
[00:10:32]
So we need to first execute it like the first time. And then I'm going to go into Chrome again and let's just do like a console.log to check that everything is working, so frame. And we got a function that's constantly running. So inside of here, what I can do is actually perform the lerp calculation.
[00:11:11]
And I already added a lerp utility here in map. So it's just this little formula. So let's grab it and. Use inside of here. So I want to edit the cursor position.current.x. It's going to be equal to lerp. The first value a is going to be the current position that we are at. And we want to interpolate that value into wherever the cursor is, so we're going to grab the target position as the b parameter.
[00:11:55]
And then let's put a value like 0.1 maybe to see what's going on. And if I save, this is not going to do a lot because we're just like editing this number, but let's just log it. So I can just log this value and. To see if it works. Okay, so if I go into the end of the screen I can see how it's changing all of the time and then if I go to the center of the screen it approaches 0, but it does that in like a smooth way, it doesn't immediately go to 0 or to 864 in this case.
[00:12:44]
So we can grab this code that we did before and we can update. The x-axis of the mouse, so. Let's put a little return here, so if the mouse reference is not defined, let's just return. Well, it's just write, so let's check that the mouse reference is defined first. And if it is defined, I am going to.
[00:13:30]
Update the cursor position to the smooth value, which is cursorPosition.ref. And let's just do the exact same thing for the y-axis. So y? Now if I save. Oh, we forgot to interpolate the y-axis, so let's interpolate also the y-axis here, so. So as we can see, our element is just following our mouse smoothly.
[00:00:00]
And again the way we do that is that we are smoothly interpolating one value using the actual mouse position.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops