This course has been updated! We now recommend you take the Complete Intro to Real-Time course.
Transcript from the "requestAnimationFrame" Lesson
[00:00:00]
>> [MUSIC]
[00:00:04]
>> Kyle Simpson: How many of you have heard of requestAnimationFrame? Okay, so maybe about a third of you again. requestAnimationFrame is an interesting API because it was designed to fix a problem and that's where the name came from. But I really think this is an example where the name is actually a really terrible name and it's a really poorly named API.
[00:00:30] So, first of all, it's not just about animation, even though the API says the word animation in it. Many people think, the only thing I ever need to worry about is animation. I point you to a blog post that I just recently did, if you search on my blog it was a month or two ago.
[00:00:47] I talked about doing requestAnimationFrame for just plain old normal visual updates. So, requestAnimationFrame is basically an API that says, I've got a function that I am going, inside of that function, I'm going to make some visual updates to the page. I'm going to move a box around or whatever it's not about animation I'm just going to show something, or hide something, or make something bigger, or drop in a banner, a pop a dialog, whatever.
[00:01:16] Any time we're going to make some sort of visual update usually CSS based. You can say to the browser here's the function that's going to do that update. And I would like you, browser, to call this function at the most optimal time for a visual update to occur.
[00:01:31] Because if you think about it, if you write your code in such a way where you are declaring I want you to update this code right now. The browser oftentimes has to assume that you really do want to update right at that moment. But we know that the way the browser works, it's not actually physically updating the screen every single time you write a JavaScript call.
[00:01:51] So we get out of sync between when we're making updates and when the page is actually refreshing. So we have not only our screens that do refresh's like 60 hertz, you know it's doing 60 times a second or whatever. But we also have the browser doing visual updates or repaints to the screen.
[00:02:11] And the browser is really good at keeping itself in sync with the monitor that it's running on. So if you're running on a 60 hertz monitor ,your browser is going to be running an update. Generally speaking it's going to be trying to update about 60 times a second unless something is slowing it down.
[00:02:28] If you use the same browser, same system on a monitor with a 100 megahertz, 100 times a second. In general those newest most modern browsers are capable of updating it faster speeds to keep themselves in sync with with your display. But if you are updating your code, if you're updating, if you're making changes to your CSS in different intervals than what the browsers updating.
[00:02:49] Then now you have three different potential updates that could be out of sync. And so any time you've ever done anything with set timeout based animations or anytime you just made a plain old visual update at any time, you've been doing so slightly sub-optimally. And requestAnimationFrame is a nice API because it says, I don't know when that's going to happen.
[00:03:09] It could happen one millisecond from now. It could happen five milliseconds from now. It could happen an ancient 16.7 milliseconds from now, I don't know when the next updates gonna be. So I don't wanna take time to worry about running my update now. I want the browser to automatically call my function for the visual update right before it does its next repaint, that way I can be in sync with that update.
[00:03:34] If it slows to 30 times a second, my code slows to 30. If it speeds up 100, my code speeds up to 100, you get the point. So requestAnimationFrame's a really nice API, not only just for animations but for any sort of updates that you're going to do.
[00:03:47] You're going to pop in a dialog or whatever, you might want to consider queuing those things up with requestAnimationFrame. But I said the API name is really kind of poorly name because it implies that we are requesting some sort of animation frame update. And my anecdotal evidence for this is at one point about a year ago I logged onto the MDN website, and I looked up the page for requestAnimationFrame, I wanted to know something else about it.
[00:04:14] But I noticed I just glanced, I noticed that the very first sentence of that documentation page said something to the effect of requests the browser to schedule a new animation frame. And I read that and I thought well it doesn't sound right. I feel like I'm pretty familiar with how requestAnimationFrame actually works and that doesn't sound even remotely like what I think it should be saying.
[00:04:39] And so I did some research I asked some people at Mozilla and it turns out somebody was making that documentation for that page and was completely mistaken on what requestAnimationFrame actually does. And I think again, anecdotally, part of the problem was that the name implied something about requesting animation frames.
[00:04:58] Well, that's not really what's happening, the browser's gonna continually repaint all the time. And all you're really doing is queuing up a visual update to occur at the next paint. So what should they have called it? They should have called it visual update or queue visual update or you know perform visual data or something but requestAnimationFrame is just a bizarre thing.
[00:05:16] The point is, you use requestAnimationFrame any time you're making any sort of visual update that you wanna make sure you're doing so as performantly as possible. So I created a facade for the animationFrame API as you would expect, it's called animationFrame as you see there on line one.
[00:05:36] Now I fixed some of the conceptual problems by naming my methods queue because that's what you're doing. You're queuing up a function to be handled with the next repaint. So you call aFrame.queue to queue up a function. And there's this other subtle thing that sometimes you find yourself needing to do.
[00:05:53] Because there is sometimes where you need to make one visual update and then you need to do another visual update. And you need those things to happen in different animation frames, in other words, in different repaints. Because if you do them in the same repaint, like for instance turning something red and then turning blue, guess what the CSS engine likely will do.
[00:06:15] It will never show the red and it will combine it and only show the blue cuz you'll never have a chance to see the red. If you wanted it to flicker from red to blue, you need those things to happen at different times. Another example is if you wanna show something and then use a transition for it to pop-up and then move.
[00:06:34] If you do those in the same animation frame, if you make it pop-up and you apply the transition, so that it will animate itself and move. If you do that, what you will get, is at some point when the animation has completed it will just pop visible in the end location.
[00:06:51] It won't pop and move it will just pop-up in the old location, which is not what you want. So this is a common enough task that I was running into that I realized well, you kind of need to request not only the next animation frame but the one after that.
[00:07:04] The next, next animation frame. And so I add that method directly on to the facade called queue after, so it just essentially does two requestAnimationFrame's nested in each other for you. So line 11 you can do queueAfter and queue and so forth. You can cancel these things just like you can cancel any other intervals.
[00:07:24] But it should make it pretty simple for you to deal with doing visual updates and that's the goal.