 Welcome to another episode of GUI Challenges where I build interfaces my way and then I challenge you to do it your way because with our creative minds combined we're gonna find multiple ways to solve these interfaces and expand the diversity of our skills and in today's GUI Challenge we're building physics or we're putting physics on stuff or something look at this rock hand just rock out and bounce ooh I hope you're excited about what's happening here alright alright alright alright so what's happening right you're just like why are these bouncing and so GUI like they're little pieces of jello that you hover on them and they jello out or whatever well let's start with this here's the number 10 when I click it and I hold it well if I hold it I'll kind of maximize out the value well let's just do it okay so here look oh did you see it kind of bounce over oh look it even went into a negative value there so it's overextending, under extending it's totally just some bouncy numbers so it turns out that what I've done is I've written a little script that will take a number from to another number in this case it's going to 100 and then given a weight you know like a mass and some friction and some tension and some of these like physical properties of things in the real world this function will take that number 10 up to number 100 over a range and kind of you know apply basic physics to it and so with that number I'm able to assign it to whatever I want and well you know me I'm going to put it on some custom properties and so here's a good example of where we have letter spacing let's have some physics based letter spacing shall we boy oh oh oh oh oh oh oh I am very entertained by this and notice how this one has very little friction a lot of tension and not a lot of weight it's going to sit here and bounce for a while and that was cool what I got to do is when I initialized the number set when I initialized the set of physics I defined the properties that are of this particular physics and numbers I'm trying to do anyway long story short I get a value that takes much longer to resolve and what's really cool about this too is I don't have to deal with duration there is no concept of duration here duration is whenever it's done bouncing and notice it's interuptable I can interrupt these in the middle in fact if I interrupt them when they're like really far little they kind of extremely go the other direction which makes sense right because there's a much wider range that the number has to span that that number is going to span and it's going to overextend based on the amount of distance it had to travel and all the tension and stuff I put on there so this particular one this increases the font size of what you hover on it also increases the font size by half of the letter before it and the letter after it and that's why it gives this kind of effect that there's sort of like I don't know that these are connected and look at this one has the space there's like a space right here getting animated but gooey gooey challenges yeah anyway I thought that was fun this one here is just animating scale so we can kind of do a performant version of this where the custom property is just changing a scale value and when I hold down I scale it down to like 0.5 I don't remember what the value is when I let go I scale it back to 1 and that gives me this really natural looking feel of a bounce here look it's really subtle there's only a couple bounces on it this one must weigh more there's less tension and I'm getting much more subtle animation and it appears to resolve I don't know about a second or something like that so if it's just a number and we can apply it to whatever we want how about a gradient look I have a bouncy gradient bouncy bouncy bouncy that one does a little flashy so I'm not going to show that one too much but it's just to show that you can animate since it's just a number anything right how about border radius let's see a bouncy border radius wah wah wah wah wah this is fun stuff look at this one okay so this is another one and it's a width animation and look at the width on this thing just kind of go looks a lot like the letter spacing doesn't it but that's applying a width animation this element is centered and the width is being animated with this physics value and a custom property super cool here's a rotation example nice this one looks really natural I mean this is the kind of bounce that you want when you're applying a sort of bouncy animation it's not annoying it's subtle well I don't know if it's subtle but this one's kind of a little bit extreme but what's cool is I can interrupt it right when you click again you're sending a new value two and my function will look at the current value of the number and says okay well we're going from the current one to this new one and when I hold it I'm telling it to go to one turn so that's one full 360 turn when I let go it goes back to zero and if I just catch it anywhere in the middle it'll resume wherever it was and go to the new location and what's cool too about this particular implementation is it's contextual on distance just like we were seeing earlier where here in this example in the text when I'm hovering over it and it's out when it's in its natural state it doesn't have to go that far to get to the large state but if I catch it when it's shrinking I can I can increase the amount of like force that it has because it has to travel over a greater distance which means there's more tension and there's more bounce in it so this particular function is very distance relevant so if you're going a small distance you're going to get a different animation than if you go a long distance and that's just really cool I thought. Okay so here's another one we've got these little balls, they'll bounce these ones are kind of fun because look I can like pull them down just with my hover event hiya hiya hiya hiya I'm just like hitting these things they sit there and they bounce and it's really cool almost got like a little sine wave there look at that, that's nice, look at how that's settling so again those are using this particular function to write a translate y value in custom properties in the custom properties just apply these over time just like how we saw this number so again like when I click this number just imagine this particular number is going into a custom property using request animation frame and so the browser is like oh on the time when I'm ready to do some animation I'm being given a new value of this particular number or this particular letter spacing and I'll just apply that transformation and it applies to transformation at the refresh rate that it has and you get a nice little animation okay what about this one this one when you click I shuffle the array of nodes and then give them a new translate position and then it takes that translate position and it goes to the new one with the applied physics and this one is a little bit more bouncy kind of fun there's more tension here you can see that like it almost feels like a stronger rubber band is on this one than is on this one here this one is a looser rubber band and this one is a stronger rubber band you can kind of see the tension that's in there and you get this much faster animation and an animation that resolves a little bit faster but still has some good bounciness to it too so that brings us to the playground let me zoom out so here's where we can kind of play with all of the attributes that go into this so when you define one of these new physics numbers you tell it what the mass is tell it what the tension amount is the friction and the start velocity and these are the four factors that go into applying this animation and so notice that these are all the default values of the function the start velocity is at 0 the friction is at 10 the tension is at 100 and the mass is at 1 and what's cool is I can use this a little playground down here to kind of preview the values that are going on inside of there and again it's like interruptible which is like fun and that's the default stuff that we get and that's a pretty good amount of physics on there it's bouncing back and forth about three or four times it's resting nice and well okay well let's play you want to play a little bit and see what changing these values is let's up the mass to 5 and look at that it's like a heavier item and the tension stayed the same so there's still a good amount of tension but it's heavier so it goes slower but it also kind of swings more which is interesting if we really bump up that mass see we kind of just exaggerate that exact behavior that we got so the amount of tension that we have in here is pretty high but notice how the mass is really affecting the ability for this to settle over time kind of cool so let's go back down to one let's increase let's see yep we're back to original let's increase the tension so if we increase the tension look at that it's like a stronger rubber band is on there but since we dropped our mass down this is like a lightweight item on a really strong tense rubber band and we get this really strong rubber band effect and look how much faster the animation happens so you increase the tension and you increased the speed at which it goes well let's also increase the friction so we increased the tension and now we're going to increase the friction that was weird it reset whatever and now look at this we've increased the friction and there's way less bounce in fact there's like no bounce happening that is really interesting let's drop it down to 28 ah there we go so now we have a fast animation because we have a lot of tension we have a decent amount of friction and there it is getting a nice swift physics based animation super cool okay well what if we drop that tension back down to like what was the default was like a hundred and look at our friction has drastically changed the amount of bounceiness in fact there's no bounceiness it looks like we're even applying like an ease out or something like that it starts out fast and then it slows down we can change this by adding a little bit of start velocity and so now it's going to start even faster it's going to assume that as soon as it begins it's like it was already traveling we didn't see much difference let's really bump that up oh now we got to see some of our our tension is there right we have tension we have a pretty low friction and here we can see that it really overshoots because of that amount of start velocity that's too strong let's drop it down nice okay so look at that it overshoots but then rests let's increase our tension and now we'll see a little bit more stiffness in it but we see still no like bounceiness it's not like it's you know like a feather bouncing on anything like that we've got this effect so okay kind of interesting let's drop our start velocity back down let's what do we have here so we have a nice slow one let's increase our mass look at that now we have some bounciness happening with a much heavier item the amount of tension there finally being manifest because it's heavy enough to kind of over swing can drop the friction and get a little bit more bounce we can increase the friction and get less bounce look at that one that was really soft and nice very soft and subtle that's a cool set of parameters right there so anyway this is what I built today and I can't wait to show you how I built it but you know what we need to do next is go make sure this works in all the other browsers let's head over to the debugging corner ah the debugging corner love it here this is so much fun and I love how these sliders turned out over here on iOS they look so nice this is really nice default slider and then I used accent color to give them all the different color and they just I don't know it feels so happy and candy coated and I don't know I thought they did a really nice job on this UI okay so here it is working on all these different whoa oh yeah I mean look at the mass it's got a large amount of mass high tension high friction that should change it though let's change the tension down ooh oh start velocity that's the one kicking us right there ah that's nice much softer that is good stuff okay so here it is working in iOS and again the reason this is going to work across all these browsers is because it's just a number being incremented in a custom property over time so it doesn't have to do any interpolation it doesn't have to do any animation we've done it all ourselves we're writing a new value for this over time there it is going back and forth over here on iOS here's Android I don't know why that first click seems to be kind of snapping to the other side sometimes look at that it's pretty consistent so I've got a bug in the way that I'm doing it well whatever we still get to see the nice demo here excellent Firefox everything loves custom properties how cool are those alright another thing I wanted to show in here is that I forgot to show keyboard work I'm hitting tab I can move through these which is kind of fun if I hold tab yeah I don't know I thought that was kind of fun and silly but it's just interesting that you can tab through these and hit enter to kind of invoke the different animations that they offer kind of cool oh look at that one we have a bouncy outline interesting pretty cool right now it's going to shift and shuffle love it cool so now that we've kind of seen the demo we've seen a lot of like the effects it can have we can see working across all these different browsers let me break down a little bit of what it takes to code this up so that you can take it home and put some physics on whatever you want with custom properties right up here is the HTML so this first one was just an H1 there's the initial set of text and it's got the class of how it works and interactive makes it so that you get some nice interactions with a mouse and a keyboard but the interesting part here is it's just text so if we look at the JavaScript down here this is the how it works JS module it's going to import my spring physics function from this kind of class that I've created here it also brings in bling bling JS just because I'm going to do a bunch of add event listeners and stuff and it makes it easy so the first thing I'm going to do is I'm going to grab that particular item how it works I have it now in title so this is going to be an element node and I'll say title dot physics so I'm going to add the physics property onto the element object itself here I'm going to say start at 10 which is going to match the text value that was inside of the element and then I'm going to get a callback from spring physics and it says on update here's your new value set the title dot text content into the value dot to fix when you're doing a lot of these physics items there's a lot of float values that come in and so you can say to fix just sort of chop them right off because of this particular instance of like I just wanted to show the number going up and down I wasn't interested in it's like fidelity of you know preciseness I just wanted to see a number kind of overshoot no undershoot and that sets up the physics what you need to do next is set that value to something you need to tell the physics start value to go to somewhere new and it will take so notice I didn't pass any options here I just use the default values that are in the spring physics class but anyway I hit a pointer up or key up I'm going to set physics to 10 so that's kind of kind of restore it but when I push down or hit key down I'm going to set them physics to 100 and that's it you just set physics dot 2 you send it to a new value it's going to call your callback and I just set the text into that particular element to to that value that I get back from this resolver so let's go check out the resolver a little bit here's my index js with all my different demos here's all my different styles going into different layers well they're all going into the same demo example layer but I just thought that looked kind of neat to have that organization and here is the spring physics module so this is if you want to get into the like the inner workings of how I achieved this physics this is what I did so here's the defaults we have a namespace for the custom property that's going to be written you can of course pass something custom here if you like there's mass tension friction and start velocity we saw these already and here's their defaults one one hundred ten and zero here is the class so notice I'm exporting a class called spring physics its constructor is going to take a start value some options in an update we were just looking at that we started at 10 update function and we didn't pass any options we just accepted the defaults so kind of cool the next thing that this does is we call two right and that's what kind of kicks off everything and notice this one's not private so this is a public function tick and resolver or private gotta love the little private members here and we say two so when we go to let's expand this we look to see if there's a current value and there is a current value we set the start value to that tick value and that's what allows this to resume and begin somewhere new if you're in the middle of a previous spring animation this will interrupt it take its current value and go to the new location we have the target we have the solver and this is what does the work that sort of takes that ten and goes to a hundred and sort of bounces it back and forth this is a lot of the physics is involved in this solver and then we have a marker that says this is in motion we have a start time indicator and we have window dot request animation frame this dot tick dot bind this so we're going to tick and we'll stay inside of this class so that we can reference the values that have been instantiated inside of it with this keyword so cool that's how to works let's look at tick so this happens on request animation frame over and over and over again until the animation is done we look to see if this is in motion we return if it is not in motion so that we don't want to be ticking if there's nothing to be displayed we look at it how much time has elapsed so we take date dot now divide by a thousand and then we subtract this dot start time and then we have the change that's happening and so we pass that amount of time that's gone over to that solver and that solver will resolve that particular value for us and we look at this dot tick dot values we look at the start value and we add the target and minus this dot start times the amount of change and we get our new value and then we can call the callback so this dot callback we're going to call it back with the namespace and pass it the value that we've determined from the solver and here's where we kind of determine if we need to finish or not so if the elapsed amount of time is less than five or the change is currently equal to one which usually means it's done if it's not equal to one then we continue requesting animation frame we continue letting this tick otherwise we set motion in a false and we cancel the animation frame so that's what's happening in tick and the last part of this is the solver which I did not write I got it from webkit.org slash demo slash spring slash spring dot js this was made a while ago and it was a prototype made by the webkit team and it's just a function that kind of takes in these different masses so different physics properties mass tension friction start velocity and does the math and the equations to work out what that would be over time and we return a function here called t which is our solver and we can pass that in and get back new values I did not write this function as it kind of looks and I referenced that it came from webkit.org I just made a class out of it and hooked it up to request animation frame and then passed it back into these callbacks like over here so that I can use it to set a custom property well this one sets text context let's look at one that is setting a custom property let's check out letter spacing so here's the letter spacing styles I just give it a font size so it's nice and big and easy for us to read and then I set the letter spacing to our letter spacing which is going to be set by our callback and then a default value of 18 pixels so if I look at the javascript we're importing spring physics we bring in bling bling we grab our particular title element from the letter spacing we're going to give it some physics we're going to say start at 3 so the letter spacing is 3 by default we're going to give it some options and here's a name space called font size we decrease the friction and that's what made it so springy and it sat there and sprung forever it's because we reduced the amount of friction then we have our update functions can take that name space and value and we're going to set a style property on the style object this is how you set a custom property set that custom property called letter spacing to well value plus pixels so we turn the number into pixels here so that we can use it in letter spacing and then here's our key value so when we release our finger we're going to put it back to our starting value and when we press we're going to set it down to 5 and that's how the letter spacing work let's look at the border radius border radius we grab our border radius element we start a new physics item we start at 25 give it some name space here's the friction we set that custom property to that name space with the value with percentage so kind of interesting so 25% is the default and then we animate to 45% and the reason I didn't choose 50% is because you can't really overshoot border radius it just turns into a circle at that point and so I gave it something a little smaller so we could see it sort of overshoot into a perfect circle but kind of settle if you hold the button down there it won't settle at a circle anyway that's just what I did but you can see how this pattern is kind of playing out here's width so we set width the less frictions again remember that one's really springy really bouncy we set the custom property to that name space which is width with the value and if we look over here width we have an inline size set to var width or 300 pixels by default and that's it I used that particular pattern over and over and over again to make all those different demos and it just ended up being super duper fun I hope you liked this GUI challenge I had a ton of fun making it look at all these little fun playful little demos now I can go use this particular class the spring physics class to go just put physics on anything and then use custom properties to have it go somewhere into the browser and do something fun like rotate things make things bouncy boing boing boing boing boing boing oh and a little zoom action yeah and then we'll here we'll spring this one back and forth anyway I hope you had as much fun as I did watching this as I did making it or you had much fun or watching it as I did making it you know what I mean anyway keep your eyes out for more GUI challenges and I'll see you on the next one happy holidays y'all