Ben Lesh - Advanced RxJS: State Management and Animations

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everybody uh I'm really happy to be here I was here last year absolutely love Switzerland Sharad is a pretty funny guy he likes to make jokes he insulted Swiss chocolate the other day unjust and like this is this even it work out let's do this this happened so he got he got he got knocked down don't mess with Swiss one um it's really this was just a circumstantial photo I don't know what what man wouldn't had he was doing and tried to get up like an old man and but yeah it looks like Maddy was just like dude Bob it's pretty good so yeah I'm Ben Lesh I I work as a software engineer at Google I used to work at Netflix with a few of these other folks including Brian Holt you find me on Twitter at Ben Lesh github the same same nickname uh so this is a talk again about advanced RCS I'm going to just gloss over what RCS is here I've done a lot of talks on very beginner based stuff in an Rx and I'm excited about this talk because I'm going to talk about doing some more advanced things I don't expect everyone here to be able to follow along it's fine you can you can catch me afterwards and I'm happy to answer any questions this talks a little bit more for people that might have used rxjs a little bit but just to gloss over what our case is as Brian stated in his talk Arceus is lodash for events it's it's a set of operations in whatever that you can do to control event is set to things so RCS is about observables and operators you can find more information at a few of these spots there's there's arcs gs5 on github that's where the repo is is at this spot it reactive x /o RCS the doctored the reactive x io web website and then you can actually look up the tc39 observable proposal at the bottom like there I'm github as Brian had mentioned it's it's stage one I think they're pushing for Stage two very very very soon but our five is a reference implementation of this proposal there's there's some minor differences but it's it's made to match the observable that might land in the browser someday so ideally you know I would have I would get to stop supporting you know writing the observable part I could just let the browser handle that so in observable what an observable is just a really quick version it sets of values over time so you subscribe to an observable and when you subscribe to it it takes the observer that you've given it or takes a bunch of functions that you've given it makes it wraps it in an observer and which is just an object and then ties that observer to something that's producing data whatever that is it could be a for loop over an array could be a WebSocket could be anything and then on completion or when someone says I want to unsubscribe from this thing because it gives you a subscription back or when it completes it's able to tear that down so you can use kind of expensive things like WebSockets and close them when you're done or in this case we're going to be talking about animations you can do things like abruptly stopped an animation or something like that the most important part about this is that observables are steps this is why they're powerful so you know this is I don't know how many folks here have ever like looked into things like category theory if sometimes you hear people get up to talk about observables and I've sworn that I would never say these words in a talk but they'll say things like monad Mahanoy these sorts of things these are just names of sets that have certain properties that's it there's like for example a mono it is just a set that you can concatenate and has an identity property so an array falls under this category you can concatenate arrays together an empty array concatenated to an array you come back with the same array so that's an identity that when you hear those sorts of words it's just someone trying to sound smart I'm not going to do that anymore but the thing about is they're sets and because they're sets and because brilliant mathematicians have come up with all these wonderful things you can do with sets we have all sorts of great things you can do with sets you can transform them this is what operators are so operators are just functions really that transform one observable one set into another observable a different set so you can map and filter and fly and do some of these other wonderful things join them so really to think reactively when people think about reactive programming usually that's explained as let's put some some event fires and then I react to that event and then I fire another event and something else reacts to that event it when you're when you're talking about it with rxjs you're really what you want to do is think about transforming sets you start with some one set of events and you try to transform it into the set of events that you actually want but the stock is actually about animations I'm excited about this because I do talk a lot about our exes like all I talk about when I come to these conferences and and the the thing is I'm always up here into mic you know animations like what are the major sources of sets of events in your apps there's Ajax there's user interactions there's animations there's WebSockets and so on and then I go on to show examples of user interactions WebSockets Ajax all these other things I rarely rarely ever touched on animations and you know animations are sometimes viewed in the development community a little bit of fluff like it's not the important part of your app it's not the functional part of your app there's talks about why it is important there's some wonderful talks about that but I think Sarah drafter and some other folks but it's it's it's also technically interesting and we're going to get into the technical side of doing these with our X GS so there's different methods of creating animations in an application the first one a lot of people go for nowadays is CSS you can do some cool stuff with like CSS transitions and keyframes and other great things and then also there's a lot of ways to do this with JavaScript there's raw JavaScript just like go in and I'm going to use you know animation frame or set interval back when I first started people as you set interval or set time out and and you know physically move the Dom element there's a limit the web animation API I think this is really only available in Firefox right now I don't think it's actually made it through its entire proposal process for what what WG is the standards body for that there's jQuery a lot of people have used jQuery to animate that was one of the things that made jQuery really popular I think is like wow look at this I can make stuff move and it's one line of code right d3 used for a lot of data visualizations green sock and just so many more there's tons and tons of libraries most of these these other JavaScript methods and also the CSS methods you can just use them like normal and kind of wrap them in an observable and that's just wrapping an API in observable that's the same thing you do with the web sock or anything I'm not really going to focus on that so much but I'm going to focus on in this talk is using raw JavaScript in just rxjs to create these animations so it's what is an animation animation if you look up at the definition is the technique of the actual definition the technique of photographing successive drawings or positions of puppets or models to create an illustrator to create an illusion of movement when the movie is shown as a sequence so it's pretty clear we want to deal with set so I keep talking about sets of things so I can see by this definition that we've got a set we've got a set of puppets over time right now this may be not puppets positions over time is really what we're concerned with in web development so what this actually looks like if you're to kind of just take snapshots of an animation is it's really primitive here you would see if I'm moving something object I'm moving this little ball it's going to move it starts at position 0 and then goes to position 1 and so on you can represent this as an observable I've got this completely synchronous observable of 0 1 2 3 at the bottom same thing for rotation you're just changing degrees over time so you can say have an observable of those degrees and scale it gets a little bit more interesting when you do more than more than 1 right so you can you can scale it in two directions that basically since every one of these the width and height is exactly the same I could you know kind of narrow that down to the same sort of observable but you get the idea moving to two directions same things just you've got values over time and that's precisely what observables are we need values over time but every all the observable they just showed you the bottom when you say servile of and some values and then you were to subscribe to that it would just play them all like that like you're looping over an array it's it's that doesn't have that temporal element doesn't have the element of time in it and we need that for animations and that's where it gets tricky so there's there's really two elements of time that I want to talk about when it comes to animations and these are not formal definitions I didn't go out and look up some collegiate version of definition of animations and the types of time involved this is just my breakdown of this there's one type of time that you want to deal with which is your frame rate and up the other the other thing you want to deal with is some sort of duration or velocity so let's talk about frame rate really quick or what a frame is so a frame is just a moment in time at which to just adjust the position of something before you rerender it so it's it's they you have many many many frames to make up a movies I'm sure you've seen a film strip before and there's multiple frames in a film strip that's all frame is and to get a frame an appropriate frame in a modern web browser you use requestanimationframe this is the API for requestanimationframe you call it you give it some sort of callback that will actually be fired when the browser says basically what you call this it's telling the browser I want to do some sort of animation browser when you're when you're ready when you're not too busy and you're about to do a about to do a render cycle right before that let me run some code so I can make some updates so I can I can schedule this to be rendered in and updated make a movement so you call requestanimationframe it can give you back an ID you can cancel it later if you if you choose so it's kind of like a set timeout sort of our cs5 actually has a scheduler that wraps this that actually handles this for you I'll get to what schedules are in just a second but it's you can find an R X dot scheduler dot animation frame and it's it's just this really simple API it's got a schedule method in and next method when you call schedule you've provided a function that you want to fire on the animation frame and it returns back an rxjs subscription that you can call unsubscribe on later if you want to cancel the animation frame for some reason it's actually really rare that you'll end up using schedulers raw like this and and rx but I just want to show kind of what the API is so what a scheduler is in are X's schedulers just control the timing of when your observable events fire so an observable again when you subscribe to it you give it some callbacks in it and it it'll fire your next call back every time it has a new value or if it gets an error it'll it'll fire your air callback and so on so this actually controls when those things are allowed to fire so if your observable says hey I've got a new value for you I'm going to next this at you and it's and it's being controlled by a scheduler it will wait for the scheduler to allow that value to come through to the air handler so it's schedulers are kind of a gating mechanism because you won't you don't want to just play it right now what we want to do ideally in this situation is oh wait until there's an animation frame now give me the value because I'm ready to make some changes to my view so using schedulers nrcs is it's pretty straightforward it's it's available in most observable creation methods as the last argument now skills schedulers are not something that's part of the tc39 proposal at all I wish it was because then I wouldn't have had to write a scheduler at some point that could stop maintaining it they're just few one natively but it's always it's always the last argument to these creation methods and basically it just says you know this this observable whenever whenever you subscribe to it wait until the scheduler says it's ok to subscribe and then execute the subscription whenever whenever this observable buyers evaluate me wait until the schedule says it's ok and let the value through again a gating mechanism there's also some operators available in our x5 to use scheduling so you can take any arbitrary observable and say I want you to observe on this schedule which is you know fire your events on this particular schedule I want you to subscribe on this particular scheduler not really important for this talk but just so you know that that's another way you can use schedulers if you want to try them out there's a few different schedulers these are these the ones that currently exist animation frames the one we'll be dealing with today there's a queue scheduler which is like a breadth-first sort of thing to keep you from getting stack overflows ASAP is the next job or microtesla that's the same as promised so that's always going to beat set timeout zero if you do if you use the ASAP scheduler at zero and then async which is just the same as set time so if you were to say async schedule of zero it's going to it's going to do like a set time at zero basically but again animation frame wraps requestanimationframe that's the one we want to use so back to frames so what we want to do is we want to create like an observable of frames because that's when you're doing reactive programming you start with a set of things we started with a set of frames but maybe we can somehow transform that into a set of transformations we want to make to the view because it's they're all going to happen as soon as as soon as this the whatever's at the head of this fires it's going to go all the way through synchronously in you know you're going to try to manipulate this into a different set of values that you're going to use to update the Dom this is one way to do it so there's there's an observable creation method called observable range and you provide a start and an end so if I wanted to create a value an observable of zero through nine I could say you know range zero to ten so it's give me ten values after zero in it and you you get this instantaneous observable range of zero now if I was to just say observable range zero to number positive infinity and I subscribe to this without scheduling just going to lock the browser it's basically a for loop that's the upper bound of is infinity I don't have time to wait to see if that's going to complete so we use we use an animation for an animation frame is then going to say yeah I want an infinite number of these sure but each one of them I want you to wait for the next animation frame so there's going to be a pause between between there it's not going to lock up your browser and it's going to wait for the next animation frame so this is going to give you an observable of 0 1 2 and so on frame numbers that happen on animation frame another way to do the same thing this is my preferred method is to use observable interval so you say observable interval 0 and then you run animation frame and it's identical it's the same thing it's going to give you frames of 0 1 2 and so on when animation frame fires so we can we can actually take this and we can actually take this and just run it we could just say well every time the frame changes let's just change the position of something so it's going to move one pixel every time an animation frame Pires so it looks like yeah not very exciting but at least we get the ball to move right and this this isn't this isn't great this is great because I did this on kind of an old MacBook Air so the ball moved at that speed if I was to go grab you know say Brian's brand new MacBook and run the same thing the MacBook Pro it's gonna go and fly right off there because you've got a much faster processor this the problem with requestanimationframe is it's non-deterministic you're waiting for the browser to say I'm not busy so if your app is a really busy thing what's going to end up happening is it's going to wait a long time between requests animation frames you might get four frames in a second maybe you get 60 frames in a second so you don't want to animate by a frame number that's that's not great we have to do something better than that but at least now we've got that temporal side of things handled we've got an observable of frames so let's let's talk about doing something with this that makes it a little bit more usable let's talk about the other side of the time equation here which is velocity or duration so both of these things are related they're related through a very very simple very simple algorithm I think everybody is probably seen in grade school which is velocity is distance divided by time right so time being the the duration here technically so if you if you know any two of these things you can figure out the other one right but when we were talking about animating by velocity of great or duration we're kind of taking different angles on this so the simplest one law that I'll start with is just animating by velocity and what I mean by this is I want you to move by V units over T amount of times so moved by so many pixels per second or so many pixels but per millisecond or so many inches per per minute or whatever it's it's it's just you're giving it like here's the speed at which I want this this ball to move or this thing to rotate or this whatever to fade out and you don't know you're not giving it a time for how long it's going to take you're saying this could last forever so this is really good for never-ending animations like games that are running or loading spinners that sort of thing the other one is just just too contrasted animate by duration that's that's to move you know X divided by you want to move some x distance over T amount of time so you know how far you want to go and you know what how long you want it to take and then you have to figure out the velocity right and that's better for more that's more useful for what I think most of us work on as far as apps go because then you're talking about I want to move this thing from here to here it's like it's great for transitions for data visualizations that sort of thing so we need to build a more useful frames observable so we've got this frames observable this gives us frame numbers that beam to already know we don't really want to animate by frame number it might be useful for some sort of logging or something but move it's other than that it's not it's not that useful so what we can do is we can actually get an observable of time pass for each frame so we take the exact same the exact same observable we had before so this is our observable of animation frames or frame numbers and what we can do is we can say well let's let's get this I got the friends of frames out over so we get we get a start for like right now we'll just take a timestamp for whenever we're going to start this observable and then we're going to just do some really simple math and figure what the difference is at each at each animation frame like how many milliseconds has it been since I've started this observable now but there's there's a little problem with this which is this this thing here is all going to run it's going to get that timestamp before you're actually subscribed to your observable so here's a little trick with observable defer I don't see people use this a whole lot but it's a very very powerful method in in RCS which is just saying I'm going to create an observable that where I'm going to execute the body of this function here and I'm going to return to you this observable on the bottom so when I subscribe to the resulting observable from this observable defer it's going to actually get that timestamp or start and then it's going to return this other observable that is using that that timestamp internally uh I can make this slightly more useful by creating a higher-order function of it so if you're not familiar with a higher-order function really it's a function that makes a new function so it's a it's a way to to get some more reusability out of out of useful functions you're going to see that a lot in this talk so this is just saying you know what maybe I don't maybe I want to test this later with a test schedule or something so I'm going to actually provide the scheduler but I'm going to default it to the animation frame scheduler so most of the time I'm not actually going to pass the schedule in but just in case I want to test this later I'm going to provide it in this manner so now I have this milliseconds elapsed function that will give me an observable of time that's as its passed since I've subscribed so if I want to if I want to actually move something by a velocity I can set some velocity in this case I've got this velocity named pixels per second and what I can do is just some simple math I can I can take the the milliseconds of time passed and then I know it's milliseconds but I have pixels per second so I'm going to divide those milliseconds by a thousand then multiply it by my pickles of pixels per second now I've got an observable of how far should I move this object right I can make that into a higher-order function to to make it more useful again I told you if you're going to see a lot of this so now I have a pixels per second function instead of just a constant value where you can provide the velocity you want and it's going to return to a function that you can use inside that map so this is doing exactly the same thing we're saying over the time elapsed I want to move by 50 pixels per second so that just a demo this is the exact same code now it's moving it 56 50 pixels per second it's a more control rate if I was to run this on Brian's brand-new laptop it would still move at the same pace if I was to run this on a really janky old laptop as long as it supported the browser supported all the features that I'm using it's it's going to run but you might see it jump but it's still moving it roughly 50 pixels per second so it's always going to be where you where you would expect it to be at that velocity so just a quick recap on velocity based animations because that's all there is to it they're very very simple it's a set of time you get it you get a sort of set of time differences on animation frame and then you want to map those time differences in tube into position differences based off of some simple math around velocity these are easily the simplest way to play with animations is just let's see if I can move this by so much over so over a certain amount of time but that brings us to the more useful version of animations which is duration based animations so we we could just take what we did with velocity and just add a take Wow right this is going to do this the same basic thing it's saying move by this velocity but just take take all of the take all of the the milliseconds elapsed while they're less than two seconds let's say and then do your movement so you remove it this velocity for this long so this this is going to this is one way to do it but I'm going to go ahead and say that I don't think this is necessarily the best solution a solution it's a very simple solution if it works for you great but I think we can do a little bit better so what if what if all the duration based animations were that were the same we know we know that durations obviously always have a start they always have an end because it's just a segment of time and it's they're all all we have is numbers right so we can say you know one seconds past two seconds past and so on or however many milliseconds of path like we have sets of numbers and numbers can be easily transformed and scaled so I think we should try to treat them as percentages and what I mean by percentages are decimal values between zero and one so now I know if you give me a duration of 10 seconds so you give me a duration of 5 milliseconds if I'm if I'm getting a whole bunch of animation frames what I want is I want to know that it's always going to be values between 0 and 1 because that that gives me some flexibility and what I can do with this observable I always know that it sets its range of values it's going to be between a certain certain range so let's build this duration observable and what we're going to do here is we're going to take our milliseconds to lapse function the same one we made or when you're working on velocity and we're just going to map it by saying we have this duration function where we provide this m/s variable this is the duration this is how we long we want our animation to last and we're just going to take the the the amount of time that's elapsed and divide it by the the milliseconds we want the duration to be all right very simple mass and then we just say take it while it's less than or equal to one so now we can still pass the scheduler through just in case we want to provide that's the same thing just in case you want to test it later very simple but what we end we end up with is this range of value so you see along the bottom here it starts at zero and then you get some kind of arbitrary decimal amounts as animations frames fire again non-deterministically and then eventually you get a one at the end so moving over a distance then becomes very very simple multiplication if I'm saying that my duration is is is done when you get the value one then if the distance I want you to travel over that duration is 300 or whatever you just multiply 1 by 300 right it's it's you can just multiply that the the percentage it's gone by the distance so if right now the the the frame I'm at is say 0.5 we're halfway through our duration then point five times our distance of 300 is going to be 150 it'll be at 150 pixel mark it's exactly where we want to be so very very simple mask just some multiplication again we can do a higher-order function with this so instead of having a distance constant that's set to a specific distance we could actually make this into a function that takes the distance and then returns the the the function that we want that multiplies that distance x times the the time that's elapsed or the percentage of time that's elapsed and we provide that to our mapping function so down at the bottom we're saying over the duration of two seconds I want you to give me a range of values between zero and three hundred so if we go ahead and we use this and this is again we're just going to move our ball again it's exactly the same observable it moves a certain amount and then stops so that that moves three hundred pixels over two seconds or 200 or 2000 milliseconds here's why I wanted to make this percentage based so moving things in just the kind of plain boring line is it's great and all but it's it doesn't have the pizzazz that a lot of people like to see in their apps most the time people see these nice animations where things will kind of bounce into place or they'll go slowly come in and like and like cruise to a stop or those speed up and accelerate in or whatever these these things are called easing this is this is so you're you're saying I've got this animation I want to ease it in a certain way or like an elastic one or something like that so if our duration observables are always zero to one no matter how long the duration is then another thing to think about is you can also represent distance traveled if you've got a specific distance you want to go you can represent that by a percentage right if you want to go almost said five miles because of American we're going to go five kilometers right you could say I when I'm starting I'm at zero when I get to five kilometers I'm at one if I'm at you know two and a half kilometers I'm at point five and so on that you can you can scale because it's just numbers you can scale any number in this manner so we can represent distance in the same way and that's really what an easing function does so now that the values might if you have say an elastic and elastic easing function it might go over one a little bit because it's going to go past the point it's supposed to go and then eventually come back right so this is this is what we're going to do we're going to transform our duration of time into a kind of percentage of distance traveled over that time and we're going to set this again with easing functions so the easing functions that you're going to see come from the skid hub repository at the bottom by matt des L I like these they're there also based on Rob Penner's easing functions you can follow Rob Penner on Twitter like every easing function you've ever probably seen used was kind of pioneered by this guy he's really really an interesting guy to follow on Twitter very nice guy too but this or this elastic out method again came from that that that eases repo and I've modified a little bit to be an arrow function but all it does it just takes a value and transforms it to another value it takes a value between one and zero and transforms it to another value that's roughly between one and zero and this is an elastic out so that means it's going to go and kind of wiggle to a stop and we can use this by simply using a map and in in in rx you just map that duration to this distance traveling but it's really important that you do that before you do the distance because again it's expecting values between zero and one right if you do it after the distance you're gonna get devout values in this case between zero and three hundred and that's it's not going to work out quite right so just to show what this does is now this is a little bit more exciting right and all we did is just to just add one simple function it's composed in there you could comment it out we could do a different mapping function whatever you like so you can make animations more reusable and you can make you me even more reasonable than what I'm showing here with this higher-order function type methodology that I keep I keep illustrating but we can do things for example like you could move the rendering side effects to a do block and that's going to make your animation more reusable because that means you've got this observable with it now it actually is controlling the side effects when you subscribe to it you could allow passing the duration right to the entire animation a higher-order function that wrapped the whole animation that you built but again the idea is that you you want to use higher-order functions to get more reusability at it so if we want to make this particular animation this is the one we just did a slightly more reusable we could do something like this well now we have this this move ball function that takes it takes a duration observable so now I could I could give it any duration I want I could say you know give me a duration of 10 seconds an observable a duration observable of 10 seconds or a duration observable of half a second or whatever and I can pass it into this function and it's going to return to me and observe like and subscribe to to perform the animation and then you see it used at the bottom I'm saying move ball and I'm passing in that observable so here's a here's an example this is seems scaled way off I don't know if this is going to animate yeah so it's exactly the same thing it's so it still works but see Oh am I going backwards what happened oh I have duplicates I think I'm going the wrong direction anyways sorry for that yeah it's exactly the same even more reusable here we go so we can make this even more reusable by using another higher level function that says well what if I what if I don't always wanted to animate that same ball what if I want to tell it which ball I want to animate well you can just make that an even a another higher order function where now I call it by saying move move down I give it the ball that I want to animate with which is a just like in this case it's a div a div element and then you pass a duration to it then you subscribe to the result of that but we can make that a little bit better with our X jet so this is exactly the same code but down at the bottom I want you to notice that and now I'm using less instead of calling things this way what let is is let allows you to give it a function that takes an observable and returns a new observable so let is an operator arcs yes that kind of lets you compose things more and a left to right or top to bottom sort of way so this this is going to say this basically says over the duration of two seconds let's let's move down we want to move down this ball and then we subscribe to it and it should work so let's run that and now we can now we can run more than one animation at the same time these are all different divs that we're moving with the exact same animation and I'm using a merge map with this in order to coordinating them to all run at the same time now without changing very much you can you can now use the power of our x2 sequence animation so I didn't change much here all I did was change the merge map to a concatenate and what a concatenate it it says hey let's play let's map to a new observable and plays that one and not not do the next one until that one's done so it's kind of it's going to run them in sequence so if I if I run this this one even though I change about oh six characters it's going to run them in order and I did I did another little thing here which is I'm using the index to kind of augment that duration every time like which you see down in line 43 at the very bottom so again as they as they play they get a little slower each time and I'm just from but I'm still reusing the same animations that I built earlier so that's duration based animation so a quick recap on that is that you want to create a duration observable that takes your duration and representative as a percentage so the values between 0 and 1 and what you want to do then is you want to you want to map that to a distance you can use easing functions to do this but a percentage distance if you're using easing functions if you don't want to change the distance traveled over time it was easing then you just skip that map step and you run it directly but then it's just simple multiplication to calculate the difference the distance and then again to make these things more reusable you want to use higher-order functions in order to you know just be able to change or tweak little bits and pieces of it so you can kind of functionally compose these these interesting things but duration animations are all well and good duration animations like mostly what you'd see for a duration animation is things like in d3 you might see you know some elements are changing over time and every time they change you want to instead of just having it jump you want it to smoothly move to the next value that it's supposed to be set up so you know in honor of being in twist when I made this really primitive clock and this is this has no animation this is just I used rx - used RX - just have this this timer and the timer is changing values over time is saying 0 1 2 and so on and I'm mapping it to degrees to kind of divide it by 60 and just have it tick around in a circle I'm rotating it so this is just this isn't any of the animation stuff I showed you before it has maybe the illusion of animation because you see it moving but it's not really moving it's actually just kind of jumping to the next spot right as it goes around it would be a lot cooler if we could make this kind of smoothly go to the next thing so what we can take is we can use what we've already built and we can make some toilet wean function so in order to make your tween function I've kind of busted this into two functions the top one is called pre even current so this is going to this is going to take an observable stream of values and make it into an observable stream of arrays that the first argument is the previous value the next argument is the current value and the reason we need that is we need to know how far to move our whatever our second hand in this case we need to know how far to move that thing and in order to know that we have to know where it was at and where it's going so this that's just a simple a very simple transformation there I'm saying start with some initial value and I use a buffer count with 2 and 1 and that's going to give us these these arrays of two values again an observable of arrays that previous value current I and then after that down here I've got this tween function tween is going to say give me some milliseconds of how long I want this to last give me an easing function which is our little elastic thing that we like to do and then we say give us some some source so I'm source observable and our source observable is expected to be you know a duration and we're going to say let pre even current so we're saying give us the previous and current values of the I'm sorry the source the source observable is actually the source of values that you want to change between we get the previous and the current values from that so now we have a set of previous and current values and then I'm going to use switch map and switch map is going to say create this animation and down in here in the bottom you see duration map map map that that part is our animations like just what I showed you in the previous example we're going to use that inside the switch map and it's basically going to say you know over this over this duration we want to map with this with this easing and then we want to move by this distance the distance as you can see is calculated by subtracting the the next or the current value from the previous value and then we we also want to add the the previous value to the value that came out of that as well because you want it to start from where it was before it moves to the next spot otherwise it's going to jump back and then go and jump back and then go that's not what we want and then to use it we use our let operator again and we just call tween and we provide it a the milliseconds and what easing function we want to use and this is exactly the same now like this between functions reusable you'd only rewrite that you'd only write that one time I've I think I've got repositories out that have this exact same tween function that you could use if you like but it's it's you never have to write that again now any where you want to add this tweening behavior and some observable stream of values you would just use let you give it a duration of how long you want the tweening behavior to last and you'd give it some easing function that you wanted to use and then other than that it's exactly the same as the previous observable we just kind of declaratively added it in there so to see what this looks like now it's going to be a little bit smoother so it's still going to tick along but you notice it has a little movement and it kind of rocks back and forth like a like a real crappy not Swiss watch mine right my Timex uh but yeah it's it looks a lot nicer it actually has the illusion of movement but you can apply this to any sort of value like if you have a graph that changes over time or but a bar that moves or a progress bar or something you could use the same methodology to tween the values that between updates of what you're doing so this is just a recap on animations darks yes the animations are done with miss observables in this case obviously because using rxjs observables again are just sets of values over time and animations are set to values over time that's why this is a good fit you need to deal with two forms of time again you have to deal with frames which is the instant at which you want to update a position before you render and you also need to deal with some mass around duration and velocity so you can kind of control those things use the animation frame schedule in our cs5 it's it's in order to get that frame that that's observable of frames use animation frame scheduler with interval is my favorite interval zero or you can use range from zero to infinity if you like because some people just you know they get a kick out of using the Infinity constant Oh Wendy when you get to do that right so and then the other thing is you want to use a lot of higher-order functions to keep these things reusable so it keeps you from kind of hard-coding things it's it's not that much more code it's sometimes even less code to do things that way so that way you can kind of reuse animations in between different things like the ball example I showed you with where we moved each one in sequence and most of this so again it's just really really elementary math it's mostly just a little bit of division a little bit of addition a little bit of multiplication so it's all I've got in animations thank you very much you
Info
Channel: Jazoon TechDays
Views: 17,341
Rating: 4.9768114 out of 5
Keywords: RxJS, Javascript, Angular
Id: X_RnO7KSR-4
Channel Id: undefined
Length: 41min 52sec (2512 seconds)
Published: Fri May 05 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.