# Reactive Animations with RxJS (@keyframers 1.2.0)

Canonical: https://davidk.dev/talks/reactive-animations-with-rxjs-keyframers-1-2-0/
Video: https://www.youtube.com/watch?v=H7FEK6geguM
Speaker: David Khourshid (@DavidKPiano), creator of XState
Type: Conference talk · Event: CodePen Houston meetup (@keyframers 1.2.0) · Year: 2018 · Duration: 36:34 · Views: 1186 (as of 2026-10-19)
Topics: Reactive programming, CSS & animation

## Summary
This week's @keyframers episode featured David Khourshid giving a short talk and live coding demonstration at CodePen Houston on Reactive Animations with RxJS followed by a Q&A.

## Key takeaways (quoted from the transcript)
- Wherever our mouse is on there it, we're translating that from a value between negative 25 and 25. (10:00)
- What we could do is we could combine this animation frame observable with this mask move observable and sort of, you know, pair them together. (15:00)
- Instead of just changing the value, it's accumulating all of the values and putting them together, and so it's just getting bigger and bigger and bigger. (20:00)
- If you move your mouse around, you could see that sort of, eventually goes to that value and that's what we want. (23:00)
- If I wanted to combine mouse moves and touch moves, so no matter what I'm using. (33:00)

## Chapters
- 0:00 Introduction
- 4:00 Add event listener, you know, mouse move, and then I could
- 9:00 Let's do the same for the Y by equals position X…
- 15:00 To scan, here, let me do this…
- 25:00 Let me try to actually find the React animated link
- 29:00 If I wanted to combine mouse moves and touch moves…
- 35:00 You can find him on Twitter and code Pin super easily…

## Transcript
[0:00] Welcome everyone to code Ben Houston, the very first code thin meetup in Houston. Very happy to have you all here in person. Really. Thank you all for joining us and hello everyone that's joining via the livestream. First, thanks to code PIN for being such a rad platform for writing and sharing code. It's been such a handy tool for me personally and the community that's built up around it has just been awesome to be a part of.

[0:00] Second, thanks to El creative for sponsoring tonight's meetup by hosting us in the beautiful office space and providing some pizza and drinks for everyone. And tonight, we have a very special guest joining us, David course, she'd, is a phenomenal developer with a wonderful eye for animation. He's currently on the Microsoft vs. Code live share team, and I've had the honor of working with him on a collaborative coding live stream. That we've been doing for the past few weeks, called key Framers.

[1:00] And he's just such a blast to work with and as such a nice guy. And he has agreed to meet us here for code Ben Houston to give a live talk. Hey David, how's it going? Hey, good, you hear me? Yeah, yeah, we can hear you, so we've. We've got everyone here and we are ready to go whenever you're, whenever you're ready to kick things off, all right. So, as I said, my name is David and if anyone has any questions at any time, I mean, feel free to just ask me.

[1:00] I mean, right now I'm a computer and you're a human, so you have power over me to do whatever to me. And like, we do have the Twitch chat as well for those that are joining via the stream. So if you have any, any questions there as well, we can, we can check that too. All right, actually, when you go to Twitch chat real quick. So [Music] all right. So what I wanted to talk to you all about today is one of my favorite techniques for animations that I found.

[2:00] Just because, if you think about, like, how we've been the animating on the web so far. A lot of us will reach for something like GZip or velocity, or maybe anime or CSS keyframes, which Sean and I do a lot. But when? It comes to reactive animations, we sort of have to take a different approach. So I don't know if the code pen is on the screen, all right, cool, so I have code pen.

[2:00] Houston. And this link to this library called reactive X, and so reactive X is actually a. It's a collection of libraries. And its main intent is to bring sort of a standard to reactive manipulating, reactive strings. So you could think of it sort of as a lodash or an underscore for dealing with reactive data. Now I keep throwing this reactive word around a lot, so let me just break it down real quick over here.

[3:00] You see in an image where we have an array of values. And if you think about that collection, you get all of those items at the same time. Right? By the stream of values, that's different, each item in the stream comes one at a time. And so let me just do a real quick example before I gets too deep. Because, honestly, if you click that link and you read the documentation, you're going to be like, I don't have enough computer science degrees to understand all this.

[3:00] So I'm just going to ignore it. But the concept is actually a lot simpler than it makes it seem.

[4:00] So let's do this, let's take the ADI from documents. And we're going to create what's called an observable. And so when observable is just like that second picture shows, it's a stream of values that come in over time. And so the way we did that in RxJS is we call our X dot observable, and then we. We could create an observable using various methods that it provides. So in this case, we could do from event, and so we take the body and we say we want to capture the mousemove events.

[4:00] Now, obviously, I need to assign this to add value, so let's do const, called this mouse moves, all right. So right now, this is not doing anything, and that's actually a feature, it's not doing anything. Because it's not going to start listening for events until it knows that someone is subscribing to it or something is subscribing to it. And so the way we do that is just we call mouse moves out, subscribe, and then we're going to get.

[5:00] A stream of these events and then we can do whatever we want with these events. So in this case, I have a span in the heading. So let's put the X value of whenever I move my mouse to that position. So then we could just do, actually, I'm gonna be smart and do. Constance. People's talking about query, select or I cool in their HTML equals events, clients X. And so now straw.

[5:00] If you want to move your mouse around the screen, you're gonna see that numbers start to update. Let me know if you do. Yeah. So a lot of you may be thinking like, I, I could easily do this, I could just do. Add event listener, you know, mouse move, and then I could. I could do all this already. Why do I need this fancy library? So let me ask you, like, what if you wanted to manipulate these dreams of events, like, let's say, you wanted to do it be bounced, right?

[6:00] So if I do [Music] 300, I think this is a right function. Let me see. Probably not. It's probably debounce time. Oh, that's weird, but anyway, you could. Yeah, well, let's be balanced time, yeah, and then try moving your mouse now. So do you see the numbers like updating a lot more slowly, so that only when you stop your mouse, the numbers are going to update? Right? All right, and all we had to do is add one line, this debounce time, and then we gave it like a 300 millisecond things.

[7:00] So all those crazy solutions that you already have for, like debouncing inputs and everything, it's solved in one line of RxJS, which is pretty cool. So let's remove that and let's actually do some animation. And I hope that everyone sort of understands the concept of like a stream of values. Hopefully I can't see you all, but I'm assuming that you're all like, yeah, all right, cool, cool, cool, very simple stuff so far.

[7:00] Let's get to the goats all right now. We're going. Now that we have like these mouse move events, we, we could do a lot of things with this. So first, let's make this in a much easier to digest fashion. We could use an app, just like you would use a radar. Yeah, I write on. That, and we could take that event and we could say X is the events Todd client X, and Y is the event that clients Y.

[8:00] And now we could, take that mouse move and let's actually, let's actually make things move, subscribe. So we get the position. I haven't seen that. Sarah, let's see. Expected token. Ah, semicolon. Okay, cool, all right, here's what I want to do. I want to create those sort of, you know, AppleTV effects where you move your, I guess, your clicker thing around them. Things sort of rotates with the clicker. So I sort of want to create this effect with this goats.

[8:00] And in order to do that, we're going to have to do a little bit of math.

[9:00] So the first thing we need is from the body, we need the clients width and the clients height from body. And so that's gonna give us our dimensions, and so what I'm thinking we could do is we could divide those dimensions in half. And then that will give us like a negative one to one sort of position, right? Bird like, you know, the top and the bottom. So here's how we could do that.

[9:00] Let's let's start with the X value, so comes 14x. We're going to get the Y position. Because I know it's funny when you, when you're going up and down, you're actually rotating on the X axis, even though you're moving up and down the Y axis. It's a little weird. Times 50 and plus 25, right? So this is going to give us a number from like negative 25 to 25. And so we're taking the current position, our Y position, and we're taking the total height.

[10:00] And wherever our mouse is on there it, we're translating that from a value between negative 25 and 25. And so just to show you how that looks, let's do some inline styling. So let's get the card element first equals document query, like there card I cool card, Elm dot style dot, CSS text equals. Now hope we. Ah, yes, there we go. So if you move your mouse up and down, you're going to see that those stream of values are what's moving.

[11:00] Or go up and down. So you can make it say yes, basically, you see that, right? Hopefully it's. Working on your end, all right, all right. So now let's do the same for the Y by equals position X, because we're moving on the X axis, but we're rotating the Y axis. Real weird, I know, with times 50 and minus 25, so hopefully you understand the math behind this 50 and 25. I basically just want a value between, like, negative 25 and 25.

[11:00] So and that's. Those are the amounts of a degrees that I'm rotating. This thing, alright, so now let's do our rotate Y. Well, Y. Okay, cool, now move your mouse around again. All right now, if you've seen our screencasts, you're going to know that Shah and I are perfectionists. We're never satisfied with just the simple results. So, for instance, with this one, when we stop our mouse, the rotation sort of stops really suddenly.

[12:00] And I'm not really a big fan of that. I like it to go smoothly from point A to point B instead of, like, you know, just jerking around. So for that, I'm going to introduce you to something called lurking, and so lurk stands for linear interpolation. And that's a really, really fancy way of saying that. Let's say you want to go from point zero, two, point one, instead of jumping from zero to one.

[13:00] Say you go half way every time. So you go from 0 to 1/2, to 0.75 to 0.85, to 0.99 to 5, and so on, so on. And eventually you'll reach one, and so we're gonna have a lurk function starts and so that you could consider that like R0 and R1, and so the X. This is our Delta X, this is the distance that we are, you know, from our end value. So n dot X minus star PI X.

[13:00] And we're gonna do the same with Y. So, for example, if we're going from zero to one at first, our Delta X is going to be 1 minus 0, which is 1, and same thing with our Y. And so let's also define a rate, it's equal zero point, where we're gonna do zero point five. For now, this is a pretty big rate, but it's easy for understanding just what's going on. And we're going to return X, which is the start plus the change.

[14:00] So for one, Cremeans worth the. One, our start is zero, and our change would be, let's say, half x earth our. Yeah, it would be 1 x the rates, alright, oh y, plus dy times the rate. I know this is a lot to take in right now, I've even lost myself a little bit. But the point is that this whole linear interpolation thing is. It's a really, really cheap animation technique for going smoothly from one points to the next, just by going closer and closer to it, you know, at a certain rate.

[14:00] Okay now, because right now we're only basing this animation on our mass moves.

[15:00] We sort of need something that represents a stream of animation frames, like just a constant stream of values. And so we could do that with animation, we'll creating a stream of animation frames. And so there's a little trick to doing this. In our X observable, our expel observable has this thing called interval, so let's do that one second for now. What this is going to do? It's going to emit a A value, which is like just a number like one, two, three, four, five over this interval.

[15:00] So each second it's gonna go one, then two and three and four and five. What we could do is we could combine this animation frame observable with this mask move observable and sort of, you know, pair them together. And so we're gonna call this smooth move, but we're gonna take this animation frame we're gonna take. With latest from, you know, I'll describe this in a little bit, mmm, but with this, with latest from thing.

[16:00] And I'm actually going to try to find an example. This with Glaze from is an operator that takes two observables, so it takes the first observable, the second one, and it lets you combine them. And so whichever observable comes first, it's going to just carry along the value of the last one. And so I'm gonna show you an image of that real quick, let me find it. And this is just going to appear where the Goat is right now.

[16:00] I know a bunch of you are lost, but that's okay. The point of it is to just be like getting a cursory glance at what you could do. All right, so let's replace real quick with this, all right, so over. Here we see that we have a stream of two different, or we have two different streams. And so with latest from where we're going to be taking our first stream and that's going to be our main stream.

[17:00] And so every time something is emitted from the second stream, it gets combined with the first stream. It's a lot easier to, you know, see it visually, what's happening, hopefully, that sort of cents. But basically, we're combining animation frames with our mouse moves, so instead of whenever our mouse stops, the entire thing stops. It's just going to keep going, that's that's the point of all of that. All right, so we have, we have our combined stream and now we're going to do.

[18:00] And this is another operator that if you want to dig further into this topic, you could learn about. But what scan does is it accumulates values. So, for example, actually let me do this real quick. I just want to make a really, really simple example, because I know I'm probably getting too far into the weeds right now. So let's me, let's take the animation frames, which are right now at one second.

[18:00] And I'm going to, just, well, what I do? One second. And animation frame, subscribe and then we're going to take this, our position element, or HTML me equals train. You're gonna see that every second that's going to update, you see it, you know, just counting, all right, cool. So you know, we see what's going on there. Now to scan, here, let me do this, let's take the animation frame and we're going to scan it.

[19:00] Yeah, how to do this? Okay? So here's what scan is going to take, skin is going to take. Whatever are our, let's called, our full value, in reality, it's the accumulated value, and I don't know the value. Until. What this is going to do is we could take the full value and the value that's emitted and we could sort of combine them together. So let's just do this. This is probably gonna be really, really crazy and we're gonna start with zero, and so you'll see, it's gonna get a little crazy.

[20:00] Undefined. Yeah, I told you it would get a little crazy. Let's see what did the Oh, I have to return. Wow, I'm an. Idiot, Okay, here we go, all right, so you see what's happening now. Instead of just changing the value, it's accumulating all of the values and putting them together, and so it's just getting bigger and bigger and bigger. So hopefully that makes can make a little bit more sense. If any of you have used Redux.

[20:00] It's the exact same thing as a reducer, where you take in action and the current state and you get the next state. And so that's exactly what Scan is doing right there. So the reason I explained all that is because we're going to scan. By taking each one of these values is the move, which is actually, let's, to see what that emits right now, actually, you know, let's just go ahead and scan.

[21:00] So we take me, let's do full value, remove, and we're going to return the lurked full value and move. And to let subscribe to bad see what that is, smooth move, got subscribe and then in their HTML equals what happened? And I have a mistake somewhere. Yeah, semicolon. Oh okay, ah, there's no move. It's called mass moves, all right, this is why live coding is great, all right, so smooth moves. It's not really subscribing.

[22:00] Let's comment this out for now. Ah, we're getting an object, which is definitely not what we want. So let's do JSON Dodds drink. If I promise you, this is all coming to like some sort of grand conclusion, okay? So now, if you move your mouse around the screen, go ahead and do that. You're going to see the value updating and just getting crazier and crazier with its decimal values, right? Okay, so that's because it's moving closer and closer to the resting position, so where the mouse is, and it's updating every second, which honestly, is too slow.

[23:00] We wanted animation frames, so let's change this interval to zero, which means like, go infinitely fast. But let's say, hey, however fast you go, make sure you don't go faster. And the animation frame. And that's what schedulers are for. So now, if you move your mouse around, you could see that sort of, eventually goes to that value and that's what we want. Are you seeing that? Cool? Yep, it's Ellison. So this is exactly what we want all right now, we.

[23:00] Could get to the good stuff. Oh, all we have to do now is instead this mouse moves that subscribe, we're going to do this smooth moves dot subscribe and hopefully everything just works. Let's see we're doing this Lerk thing. Okay, my rate is way too fast, so let's turn it down to 0.05 and you're gonna see how smooth that smooth it works. Okay, cool, now move your mouse around, all right, so you see how we're taking those values.

[24:00] And instead of just applying them directly to the elements and trying to manipulate everything, we're transforming them through streams and then we're applying them to this animation. And so that, in a nutshell, is how you could use our XJS for animations. I know that last part was very hairy, but you know, hopefully this initial now smooth stuff. And you know, just using those mouse move values and applying them to styles sort of makes sense.

[24:00] All right, anyone have any questions? Any, any questions from you guys?

[25:00] With videos? Will this work for videos as well? Is, I'm sure you have a 5-bit new tags ready? What's up UI? Let's try it, let's write where we're saying that, that it's it's just working on any, any kind of element. Right now. You've got it on a on a div, but you could have a HTML5 video or anything like that. And they're right, right, exactly, and that's because it is sitting on a div right now.

[25:00] But let's say that we want to do. I don't know, take a video, and yes, I am going to try this and see what happens. Work it live, those styles, so you could, you could play this video, and yeah, that's actually working. I don't recommend doing this, oh, because you're going to piss your users off a lot with your constantly rotating videos, but I mean, that's definitely possible. Yeah, I actually had no idea that would work, so thanks for that.

[26:00] Trying things. Oh, that's good. Any, any other questions on that on RxJS or some use cases outside of just mouse movement or anything? Applications with frameworks like React, yeah, how would you use this with something like React or view or anything, so I'm glad you mentioned React with React. There is something called animated, maybe you've heard of it, it's mainly using React. Native and it's basically reacts less animation library for, you know, for animations and reacts native.

[27:00] And so they sort of operate on the same principle, they don't use arcs, J/s, but they sort of use their homegrown idea of streams of values. And so what you would do is you would define these streams of values pretty much like we're defining them here. And then you would pass them into magic components like animated octave instead of just a Div, it's an animated octave. And then in your style tag, you would provide those streams of values and then you come, you would animate that way.

[27:00] So let me try to actually find the React animated link. Because the API is very, very similar, and so once you sort of croc like what this API is trying to do, you could easily see how you could apply it to. I'm gonna just post it right here. You could sort of see how that could be applied to RxJS as well. Right on the code pen, it's right over there. Why didn't I Center this?

[28:00] Yeah, um. But also I'm presenting something at React Finland next week, which sorta talks about this idea of using reactive values in reactive streams directly in RxJS, Reacts J/S, which, by the way, React is not reactive. They even say so in their documentation. They say that they should have called React scheduler and instead of Reacts, because it does more scheduling than reacting in the chat.

[29:00] Let's see sir David. When you're getting started with something like this, where you want to react to mouse movement or to the scroll or something along those lines, do you automatically jump into RxJS? Why would you do that over just using the the native event? Listeners? That's a really good question, and it really comes down to the manipulation of time. Which if you're not using something, like, you know, a reactive stream library, then it becomes more difficult and the code becomes a lot less declarative to do so.

[30:00] Have you ever played around, and or maybe someone in this room has, but have you played around with the origami design tool by Facebook? No, I've seen it before, it's it's a motion design slash code exporter kind of tool. Is that correct? So what it's based on, it's based on, basically. Patches, so you have these sources where these sources could come from anywhere, it could come from a mouse movement or your finger movements, or some other sort of event source.

[30:00] And then these patches which transform these event sources into things that you could just render into other things. And it's cool, it's sort of like a really visual way, you know, visualizing this entire thing. And so by treating these dreams of values as just values, like declarative values. It becomes a lot easier to manipulate them and to play around with them and to configure them without needing to hard-code anything. So, for example, if you were making this and you were using an event listener approach in, you just made it follow your mouse.

[31:00] But then the designer got back to you and said, it's a little too stiff. I needed to go smoothly from, you know, one mouse points to another, then the code becomes a lot more difficult. And then, let's say, the designer comes back at you and says, Hey. I also want this shining effect, you know how they have in the Apple video cards, where it shines the opposite direction of where your mouse is.

[31:00] And then you're like, Oh, no, I mean, now I have to add more code to, you know, more places. And so, just having a nice, organized approach, even though this is definitely a bit of a learning curve, is definitely advantageous. So I guess the main thing is separating what the values from what you want to do with the values. So you can kind of pre process all these values and then use them after that.

[32:00] Exactly, that's the other points, too. Is that instead of saying when I move my mouse, do this, instead of thinking that way, you're thinking when I move my mouse? That's the set of values, that's a stream of values, and I could do whatever I want with those streams of values. Then you take those streams of values and you use those to manipulate, soar in the mates or do whatever you want. And then you could go back and say, hey, instead of mouse, mouse movements, I want touch movements.

[32:00] Or I wanted based on audio or based on other streams of data. It doesn't matter where it comes from anymore, because. You don't hard-coded into your event handlers, and RX does have some ways to easily combine, like touch and mouse. Where you're not having to do like, 30 different listeners, and you can unsubscribe them all in one place as well. Exactly, in fact, look, I'm gonna do it like in 30, 30 seconds or less.

[33:00] So let's do a touch MOOC thing where we get the touch move events from the body, and of course, we have to map them to the touches. Because you can use multiple fingers. And so now if I wanted to combine mouse moves and touch moves, so no matter what I'm using. So I can make it work on mobile or desktop, or whatever you lose, here's how difficult it is. We have art style observable, emerge, house moves and lets moves, and that's all.

[33:00] And so now all we have to do is replace this with moves, and it's still going to work. But if you view this, I don't know if you could like. Change this to Debugger maintains its debug you in here. Can you change it to debug View? Is it possible not to keep the collab going? Okay, well, you can probably open your Dev tools anyway, and if you open your Dev tools and change it to like a an iPad or an IPad Pro.

[34:00] Now, you can see that it works with even touch inputs. Yeah, just that pro, yep, got it work in you? So getting it working for mobile, which might have been a huge task before, now, becomes as simple as merging two streams of data. And there you go, that's cool. Any other?

[35:00] Any other questions? No, cool, David I, I think I think we're good over here, ma'am. Thank you so much for taking your time to present this to us. And and help us understand a little bit of RxJS and where we might want to use it, and why? Yeah, really appreciate you man. Yeah, thanks for having me. And feel free to reach out to me on Twitter or anywhere else if you have any more questions about this kind of stuff.

[35:00] Yeah, David's handle on pretty much everything, it's just David Cay piano. So you can find him on Twitter and code Pin super easily there. Yeah, he's changing it live, so super. Cool, all right. Well, I'm gonna end the stream here in just a little bit. Thank you everyone who joined us on the livestream. And we'll have video available of this if you want to go back and watch and see and see this again.

[36:00] So you can kind of understand it and code with it at the same time. So thank you so much, David, really appreciate you guys and I really appreciate you and really appreciate everyone that joined us. Love will. We'll see y'all next time, all right, thank you, thank you.
