Animation With Svelte
with Scott Tolinski
Resources & Links
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
Hello, everyone, and welcome to another episode, the last episode of 2020, of Learn With Jason. Today we have a very special guest, Scott listen thin Tolinski. What's up, man?
Getting ready for the holidays.
I'm absolutely thrilled to have you here. It's going to be a lot of fun. About to go on a holiday break. I'm done after this. I'm taking, like -- I'm not coming back until January 4th.
Nice. Yeah, we recorded our podcast up until, ooh, like mid-January, so we're good for that, but I personally have --
Like 16 videos to edit still for my latest series. So I don't know when I want to do that. My deadline is January 1st. I don't know. Take my time with it.
Yeah, no kidding. Cool. For those of us who aren't familiar with your work, you want to give us a little background on yourself?
Yeah, I am the creator of level Up Tutorials. That's at level Up Tutorials on YouTube or even on switch. Or leveluptutorials.com. I've been creating video tutorials for the web since 2012 and have been doing so at a pretty high pace for a long time, so it's sort of natural for me me I've moved into doing premium courses. I'm doing almost a magazine subscription type deal. Each month if you subscribe, you get access to a new tutorial series on something new. The most recent ones being -- the one I'm working on right now is on snow pack and modules.
The last one before that was on dino and the other one is animating Svelte.
That ES module stuff is super exciting. Chris is in chat. He's been doing a lot of work in that space. It really just feels like where, you know, you want to use that Wayne Gretzky saying, like, you can skate where the puck is going, I feel like ES Modules is where it's going, right?
Dude, it is. So this might be a little bit of an exclusive here. We're rewriting our stack pretty heavily. We're keeping our UI really the same.
But I've switched up a lot of aspects of it, from the API is going from Apollo to Mercurius.
I haven't heard of that one.
No optimizations. Super fast. Our API is in ES Build.
Which not only uses ESM, but it's just written in go, so it's very fast, and then our front end is now entirely within Snowpack. So we just got upgraded to be, like, 50 millisecond saves for everything. I almost don't know what to do with it. I'm used to waiting, like, you know, a minute in between save, okay, wait. Okay, whatever. And then now it's just, like, oh, wow, this is crazy fast. And I'm actually building this, like, sort of stack on it that I'm calling Avalanche that includes database, it includes a UI, it includes an API in a one-click deal and it includes a lot of emoji in the CLI, so that's always great.
That is always great. We got a question in the chat. Someone says it sounds like your microphone is set to the one that is maybe not your good mic. Oh, yes.
Oh, look at it go.
Yes, thank you for whoever mentioned that. The microphone you were just hearing was my DSLR's microphone or my mirrorless camera microphone. So not even my Macbook microphone, which would have at least been decent.
I'm not here to judge, right?
Yeah, yeah, yeah.
Maybe he likes that reverb sound. I don't know.
Why in the world would it have faulted to the cameras? I never use that. I feel like with OSX or Mac OS in the audio sources, it just chooses. Every time I open my computer, I don't know, we'll roll the dice today. It's hooked up to a random number generator.
Zoom is especially bad at this, where I feel like Zoom will always pick the microphone that I've literally never used.
It's like, you know, I heard that you had a virtual microphone in Chrome. I'm going to try that today. That's literally not a thing. That's never existed.
I totally get that because specifically, like, the only thing I use Zoom for is syntax. We use Zoom for syntax every week, and it should always be this microphone, so -- that's just how it is.
Oh, man. Yeah, they're asking if you can boost your gain just a tad. I did not --
Boost my gain? I'm gaining here.
Here we go. This is now an audio tweaking session.
You need to boost your speakers because, no --
Everybody, turn up right now.
I've literally never touched this stuff.
Yeah, that's correct.
Now, Svelte is also those really beautiful "New York Times," like, data visualizations and stuff. Svelte is the stuff under that, right? The beautiful animations?
As far as I know. I know Rich does a lot of stuff there, but I'm not too privy to how that stuff is built. I know that a lot of people are using it specifically for that, as well as "The New York Times."
Yeah, yeah. And so, you know, we did a show with Rich. I'll leave a link to that in the show notes. That was kind of the high-level view. It's part of the Let's Learn series where we touch on everything. I thought what would be fun today, to dig into the animation. You got the course on it. You can show us some of the ropes. If we get to it, we can dive deeper on your course on leveluptutorials.com. So what do you find yourself practically using Svelte animations for? Is it something that has found its way into your day-to-day work at all?
Myself, personally, I find animations creep into my everyday work. If you go to leveluptutorials.com, even though the site is built in React, there is big emphasis on animations. Overall, we were talking briefly before the show started about After Effects was mentioned and I told you After Effects was actually where I saw my career going. I went to school for media production. I had a job as a video editor and motion graphics artist, and I really wanted to do commercial visuals, 3D, but primarily motion graphics for TV commercials. Like, that was where I wanted to be.
So because of that, I've always thought very animated in terms of my user interfaces, like, you know, back in the day when Flash was just everywhere, pervasive, and the crazy high-tech Flash animations or whatever, I always really liked that. Even though it had this sort of cheese ball look to it. There is something in me that is like, oh, man, I really loved when animations were a thing on the web. So when we got really nice CSS transitions, and I remember getting the transition property in CSS and just being like, this is the best thing ever.
So now that I can control animations on mount and unmount of actual Dom structures, I can do things like flip animations, for those of you who don't know, flip animations, what is it, first, inverse --
It's first, last --
Oh, first, last, inverse, play?
Yeah, yeah, yeah.
So you find the first position, the last position. You reverse the animation and then you play it back. So that way it has all of the positions it needs to know to do the animation performantly, but it's easy now. At least it can be easy using the right tools in any framework, really, whether that is React or Svelte or whatever. So, yeah, that, to me, it's always part of the process is coming up how to animate something. I almost never just, like, straight up toggle something and have it disappear. It's accordion. It's a fade-out. It's this or that. And that's something that I really can't live without in my user interfaces when I'm writing the code, you know?
Yeah, I've definitely found that, like, the better I get at animations, the more I feel weird when I don't take the time to put them in.
It's something that, like, you know, over this last year, one of the things that I've been getting a lot of is, for example, like, I've had a bunch of people come on and teach Greensock. So I've been learning about the Greensock tweening and timelines. Now that I know how that stuff works, I'm like, I could give this a little life. What if I did give this some nice easing instead of a straight, linear transition? And now that I can do that, now that I've seen it, I'm like, oh, I don't know if I can go back now. I think I have to do this forever now.
Yeah, yeah. And once I got into, like, physics-based animation stuff, like React Spring, that stuff to me is just so good. I ended up writing, like, a host of -- it's like an internal plug-in, as this isn't open sourced. We don't -- just because it's like a folder, my project that I've aliased. I do that sometimes, I create a folder and alias it to be animations. That way it feels like an external module, but really just a handful of components. I should really open sources in React specifically. I've made all these, like, component helpers for Level Up Tutorials. Whether that is a strayed in wrapper, you wrap in something, it net mounts unmounts, takes care of the flying in, flying out. Really basic stuff. I have a YouTube video on this, actually. A wraparound React router that just adds a nice little animation. You use animated routes. That's it. And it just works, right? So, like, for me, making the animations, like, know -- like, I don't need to think to put them in. Besides the fact you want to think about what they're doing for your users, but, like, making it that easy. Making it easier on yourself to not have to, like, really try to plan out every tween or everything every single time has made it super easy for me.
To bring it back to Svelte, that's one of the reasons I like Svelte in their animation realm. As you'll see in a little bit, it's very easy to just drop something on and just not even think about it. You always just say, okay, this is a fade thing. It's a fade thing. That's it. No wrappers, nothing else, nothing fans.
Excellent. Yeah, so, with that, I think it's probably -- that's a good a time as any to switch over and start looking at this in pairing mode so that we can start doing stuff. So a couple of little pieces of housekeeping. Make sure you go and follow Scott on Twitter, if you're not already. We're going to be talking about Svelte. So that's gonna be the Svelte website. Remember, this show and all episodes Learn With Jason or live captioned. We've got Jordan helping us out today. You can find those at lwj.dev/life. Generous sponsors from Netlify -- thank you all being a part of that. As Scott said, he runs level Up Tutorials so make sure you head over there and check that out. I saw -- thank you, Nate, for the sub. And Jimena, you mentioned the hat. This hat is a gift from Lindsay Levine who came on and taught me Minecraft last week. I'm so excited about this. This is one of a kind Learn With Jason merch. So thank you very, very much, Lindsay. She's also on my team at Netlify working on the next on Netlify plug-in. I'm ready. Before we started, I ran npx degit. This is what comes in this folder, and I'm ready to roll. What should we do first?
We should first -- let's go ahead -- can you make maybe, like -- let's do a straight up box. Just like a, you know, 100 by 100 box.
Okay. So let's -- let's do this. We'll do animation in Svelte, and we don't really need a name, but we can -- let's get this out of here. So we'll do a div. We'll give it a class of box. I don't need any special names for things, right?
Yeah, nothing fancy. And one of my favorite things about Svelte is that all of the styles in this component are scoped. So, like --
Yeah. I mean, granted this is the app component, but it's really nice for those of you who haven't used it before. The default scoping for everything is really how I would love to have CSS be written in general. You know, like, I would love to just pop a little style tag beneath all of my React components in, like, a single file. Just pop a little style tag down there and have it be scoped to that file, that would be very nice for me.
Oh, no, what have I done? Rollup. Command not found. I don't think I did an npm install. Probably need to do that. Okay.
I started aliasing a lot of my stuff so it runs npm install before I do anything. I forget that so many times.
How is this broken?
Okay. Let's get over here. We've got our animation in Svelte. So here is our box we made.
All right. Let's throw a button under that bad boy, too, so we can --
Where did my -- oh, it reordered it.
Oh, that's interesting.
I don't know if I actually have a Svelte -- I do. I have some kind of opinionated Svelte thing in here.
Cool. All right. You can just do stuff. So, I think we're -- a good basic example would be to, like, have this button mount and unmount on click of button.
So to do that, we would just head up to your script tag.
I'm going to collapse this so we can see what's going on.
Yeah. So head up to your script tag. Go ahead and create a let. You don't need to export it. It's not going to be a prop. We can just say let isActive or something.
You can have it be true by default or whatever. And now in our main HTML, you can -- the cool thing about Svelte is that it uses template tags. It's like angular or anything like that or view, mustache, any of those things. So you can, before the box, do a�#if inside of brackets. So, like, brackets --
Like these kinds of brackets?
Yeah, curly boys, if and then isActive after a space. And then to close that, you need a closing tag that is also the curly brackets and then/if.
So we could just do something like this?
Okay. So, let me close that up so that we can see the whole thing. Here's our whole app. I don't need this anymore, so I can get rid of this?
Yeah, I think so. As long as the component is not using it somewhere.
I don't think it is. We'll see what happens. So now default is active. So when I click this button, it should hide our box, right?
Yes, okay. So it's doing that. And we can make that a little more obvious as well by doing like let's see if I can do this. Do a curly boy and do isActive, we can say hide box. Or is it else like this or do I need a�# or?
That's actually a good question. I think it is -- I always head to the API here.
That doesn't seem right.
I never think about else tags. Sorry, this is a weird one. This is why it escaped me. It's :else.
We are basically going to change the text. If it's active, we'll hide it. If it's not active, we'll show it. So, hide box. Oh, show box.
Excellent. Look at it go.
Look at it go. Cool. So, let's get to the easy part, which is the animation. We can head up to the top of your script tag.
And import --
Holy buckets, did that just work?
Yeah, and, you know, especially with, like, the setting of variables and stuff, you don't have to worry about, all right, any sort of special syntax to get the correct previous value from the state to manipulate it to do whatever, right? It's just, here's a variable. We're setting the variable, the UI updates. Okay, so, we want to import a named package from Svelte transition, which is going to be -- we'll do fade. Fade is an easy one.
Fade from Svelte/transition.
Okay. And then on the box, it's -- yes, the box. On the box, we want to say transition --
Like straight up?
Yeah, just straight up. Colon. So we're declaring there is going to be a transition on this box.
And then to say what transition, we just say fade. Give it a save. Give it a rip. Hey! There we go. Now, in addition to --
Oh, my God.
-- fade. There is blur, slide, scale and fly, and those all come out of the box. So that's --
Wait, you said blur?
I don't even know what that one would be. Wow!
Blur. Blur, blur, blur, blur. Yeah.
Okay, this is -- man, I love it when stuff just works. Like, that's so nice to see that sort of stuff right out of the box.
There's a question. Can you use more than one at once?
You can't use more than one of these at once, but many of them have lots of parameters. So, like, let's say you wanted to do a -- well, actually, I take that back. You can use more than one of them at once, but not on the in and the out. You can have a fly on the in and a fade on the out. You can't do a fly and a fade. That said, within any of them, you can adjust many of the properties as parameters to them. So, let's go ahead and let's give fly a rip.
We can import fly and just change that to fly. You'll see what I'm talking about really soon here. You'll see it does nothing but fade it out, right?
Then we can set any of our properties for essentially the out state of this thing. Because it's kind of assuming that we want the instate to be its natural position.
There are custom animations to write that are extremely easy to. If this is not what you're looking for, there's more to it. We can say, like, Y: 100. And Svelte does the really nice ability of using x and y rather than having to translate 3D and have to remember that stuff.
Ooh, look at it go.
Look at it go, right?
That is beautiful. So then, you know, if we wanted to do something like, let's have it go off-screen, we'll go to negative 100. There it goes.
Do whatever you want.
Out of there.
I love this.
There's even a draw for drawing SVGs, but to be honest, I haven't used draw before.
Yeah. That is so nice. I love this stuff. Keep in mind, this is happening on mount and unmount. If you want it to do CSS transitions the normal way, you can do CSS transitions, too, just by changing class. This gives you the added benefit of being able to control the mounting and unmounting. To me, the unmounting aspect is something that React doesn't do well. I like how easy to unmount a component and have that thing animate.
Yeah, that's kind of one of the standing complaints you'll see about React, especially when you get into heavy animation, is that you don't really get to do animation in React. You have to escape React to do animation.
While that's fine, it doesn't -- it feels like something that's bolted on, where as this is very obviously a piece of how this was designed. It's, you know, you can tell that Svelte was created with animation as kind of a first-class consideration.
Which is, you know, when you start weighing what you're gonna choose for a project, that should factor in, you know? Like, not everything is the right tool for the job. And if you are planning on doing something super animation heavy, it probably makes sense to look at something other than React because React is gonna force you to, like, really put a lot of tools in place to get animations to work, whereas something like this, you know, you just kind of get to import one thing and it works.
Yeah, no kidding, right? I know. Fly, okay. Sure, whatever. And, like, so I say one of the cooler parts is, too, if you need custom animations, man, the options are there for that as well. And, like, are just as easy, almost. Do you want to give something like that a whirl?
Yeah, absolutely, I want to give something like that a whirl.
And Mark is putting some things in the chat for us to look at.
Let's take a look at a few of these. This is a draw animation. There it is. There is the SVG being drawn. And, I mean, that's super slick, right? That is --
It's pro, yeah.
That's the kind of stuff that, you know, I would have thought I needed to get Greensock or something to make this sort of thing work. And I know, like, for you SVG, like, pros out there, I know that you don't need that. Please, don't email me, but --
Adjust the dotted line and -- yeah.
But it's super cool that this is an option. It's kind of, like, built right in. So we imported draw. We have our drawing here. And, what, to draw it we say -- oh, my God. Draw duration, one second. Unbelievable. That's wonderful. Like, that's so nice.
I love that.
Yeah, I love it. Okay, so, I'm feeling this. This is -- this is great. We were going to try something custom. Here's our Svelte app. I'm ready for something custom.
And this is your normal function, normal type of function. Only this function -- let's see, the parameters will be -- let's see, it will have one parameter. The first parameter will be -- you can name this anything you want. You can call it Jason. You can call it -- yeah. Perfect. Oh, my God. Okay.
So the first one is going to be the node itself, which we're not going to use in this example. We can have a comma and some parameters that get passed into the animation.
So these params, we can destructure these, and I think the only one we'll need is -- actually, never mind. We won't even need these parameters for what we're doing.
We won't need any parameters.
Just get rid of them all. Yeah, cool. So, from this, we're going to return an object. And this object is going to have a CSS property.
This CSS property is going to be a function. You can do an arrow function with one parameter of T for time.
Okay. And let's just go ahead and open that thing up. This might even be fun for the audiences to maybe throw a council log on that T so we can see what it's doing.
Works for me.
Okay. Let's go ahead and on your box down there, where we had transition fly, you can just change that fly to be anything I want.
Oh, so we would need to add code. That is slick. So, effectively then, if -- to kind of work this back to what's happening under the hood, each of these transitions that I'm importing is a function that gets a node in parameters?
Yep. And the parameters are whatever the things you passed in there. Whether it's the x, the y, the delay, the duration, those types of things.
So with my fly that was happening, then I would have been able to pull out, like, the x?
Okay. So, that makes a lot of sense. And, also, this makes this even more approachable to me because now I know what's happening. And so we're getting this t for time, and so when I run this, nothing's gonna happen, but we should get a bunch of console logs, so let's give it a shot.
What do we see?
Here is a bunch of console logs. Let me make that a little bigger so it's legible. Yeah, so, we start at 1 and then it looks like it's firing a few times -- like, what, like 20, 30 -- is it 30 frames a second, probably?
To be honest, I don't know.
Yeah, it's probably rolling on request animation frame or something like that.
This gives us a decent number of steps. So I assume each one of these is gonna be our step toward whatever our next value is.
Yeah. The best part about getting -- so, on transition out, it goes from 1 to 0, and on transition in, it goes from 0 to 1. Meaning that in our CSS function, let's say we were to return -- if we were to return -- sorry, it's not an object, it's a string with back ticks. So that way we can use the t value. And we could do something like opacity. Is equal to. Yeah, bracket t.
Oh, so we would need to add code.
So I'm just returning actually CSS, right?
Correct. Because of that, that now means we have a fade animation. You've just implemented fade. With that t value, you can have it do anything you want it to. You can have it scale at a certain scale. You can -- man, you can literally have it do anything you want as long as you have that value. You can invert that value, that 0 to 1 and have it do something fun there.
Whoop, whoop, whoop.
But it gives you fell control. It's amazing.
Yeah, this is really slick. This also lets us do something like if we wanted to, I don't know, we could do -- we could do a translate x, probably. Because if I don't use -- if I don't use this, the translate 3D stuff, Sarah gives me bad performance reviews.
Wait, if you use what?
Because we need to use the GPU. We can't just animate, like, the left or right, right? Because she'll yell at me.
You can't use translate x either because -- unless you have a translate z of nothing.
So is it translate and then you get the three values?
Yeah. Or translate 3D is the one you want.
Translate 3D, okay.
All right. Then it's gonna be x, y, z. So we can do times --
-- I don't know, negative 100. So that will start us -- no, we would need to do it -- hold on. So if we want it to go out, we would want to start with nothing.
And then -- we would do, like --
If you want it to go -- wait, if you want it to zoom when you click the thing, you're right here. Because it's gonna be 0 at its resting point. Right? Oh, no, it's gonna be 1. It's gonna be 1. That's a good point. Let's give it a try.
Wait, I broke this.
Because that one doesn't have any pixels have it. We need some px. There we go.
Okay, so, yeah, what I think we need to do is, like, negative 100 minus this. That should start us where we want it to start from and progressively subtract more as this number gets bigger.
I think you're right. I always have to do all this math in my head when I'm doing it.
There we go. Look at it go.
It's not perfect but it's not, you know, for a little bit of mental math and me not remembering how CSS works --
It's perfect because you made it. That's the way I look at all my stuff.
I love it. It's perfect because you made it. I want -- I need a sound clip of that. That's gonna be on my daily affirmations.
Yeah, right. And another cool thing here, I know you mentioned, like, easing curves. Svelte also has a substantial amount of easing curves baked in. That's one the easiest things about Svelte, all the easing curves.
Okay. It's not going to get bundled into the library. So just go for it.
Mm-hmm. That's perfect. So if I wanted it to do that, like, if I want to grab some easing, do -- is it transition or is it like another subfolder?
Okay. So let's go with the -- let's go with an easy one like -- there is probably a bounce, right?
I think there's a bounce. But there might be bounce in, bounce out, bounce in/out. I think those are the --
Let's try that. It's gonna be super weird.
There's bounce in, bounce out, bounceinout.
Okay. So let's get bounceinout, and instead of doing this math.
No, you can leave the math.
I can leave my math?
Leave the math. So what we do in the custom animation, where we have the return, one property is going to be CSS. The other property is going to be, I believe, yeah, it's going to be easing.
And do I just leave this?
This -- yes. Yeah.
All right. Let's try it. Let's see what happens.
Let's try it, yeah.
Okay. I'm gonna do this with something less terrible because I feel like part of the -- part of the problem here is that we are doing something that's only, like, sort of functional.
So let's do this instead. We'll do our scale. (Laughter) I screwed that up. Okay, so --
You just need t. So that doesn't look like --
Yeah, so it happens really fast. What if I want to slow it down a little bit?
You can add a delay here as well. Or duration. So you can say duration.
Say let's go slow.
Okay. So do you see what just happened there? Where it's doing that bounce. So, let me change this to just bounce out. I think that will look nicer.
Yeah, the bounce out definitely is. Boop. It's like a basketball. Boop, boop, boop, boop, boop.
I love that.
So that's great. Then if we want to change this to -- like, what's your favorite ease?
Oh, what is my favorite ease? I almost always end up using like a quint, a quart.
Okay. Let's do a quint out.
So you get that kind of smooth. It like eases on the way out. These are -- easing -- if you've never used easing before, easing is kind of -- there's a lot going on with it. It's basically like math. Like drawing a graph. You can see it. My favorite way to look at it is cubic-bezier.com. This is what an ease looks like. Going from 0 to 1. If we drag this around, the numbers change. This would be like a whoop, whoop? So that's an easeinout. Where it would start slow and then go fast and then down on the way out.
I don't know what this would be. Smashinout.
If you had it down like that, it would be an ease -- oh, no, wait. Time -- I don't even know anymore. But it is, it's like -- the ease is, like, an easein is it's closer at the start and easeout is slower at the out. And the bezier functions just augment the character of it ever so slightly. I would almost never use in any of my animations a default ease in and out. Use something a little fancy. Probably nothing like bounce crazy, unless it needs that kind of treatment. I would use a quad, a quint, something like that. Just to give it a little bit more character than the straight-up standard ease.
Or heaven forbid, a noneased linear animation. No thank you.
But, yeah, as you can see as I'm pulling these around, this pink one is kind of changing with whatever happens here. You can get pretty weird with these.
Sorry to interrupt here. I have a link to share here as well. Here is a very similar interface written in Svelte, using Svelte easing.
Oh, excellent. I'm between two computers, so we have to do it this way. But, exampleseasing. Okay. Then if I look at the output. Look at all these. That's really nice.
So this allows you to see all of them as they are in Svelte, even though they are standardized pretty much.
Wow, that's really nice. Yeah. But, yeah, these are -- these are really slick, right? This is really nice because also you can go through and look at these and decide, you know, what do you want to do? So here's bounce. This is what we were doing before. Elastic is actually kind of fun. So let's throw that in here. We'll go elasticOut probably. Look at that thing go. That's fun. It just kind of snaps and gets a little bit bigger than its containing space, which is fun. It gives it kind of a sense of presence. I think that's a lot of fun.
Yeah. I find this stuff to be so much fun. It is -- there is something just, I don't know, a little less technical and a little bit more playful.
Getting to, you know, toss some stuff on these things so easily and see the results happen this quickly. And, yeah, I love this stuff.
Same. I -- this is -- and, like, this is where I think, you know, when you start to see the web feel alive.
When the animations are not just kind of stiff, robotic, but point a to point b, you start to see, oh, it wiggled a little bit or it calmed down. We had Jhey Tompkins on last week. How do we randomize blinking so it doesn't feel like a robot on a strict timer? When you start to see those little bits of life, you're like, what else can I do with this? How else can I make this feel alive? And it pulls out so much creativity, I think.
Yeah, recently, I edited animation standard cards, sort of like a credit card. I was thinking they dip and do this increase in size when you hover over them. I was thinking, ooh, this would be a great place to show a little more depth here. So I added on the depth, I added a one-pixel border to the bottom-right of it, and it looks like a credit card, and then as it does it, there's also a gradient that's transparent over the top, that I just fade in and out.
And it almost looks like the light's catching it when it increases in size.
These little tiny touches. Just goofing around on a Sunday night. It doesn't feel like work. And, honestly, it's not adding a ton of value to my platform, but it's adding a lot of fun.
I don't know about that, though, because I feel like the thing that we notice is -- I feel like we don't notice it consciously, but we notice that as being the -- that little bit of polish that takes something from being good to great. Like, when you -- you know, it's why we like Apple's advertising and Apple's products. They do these tiny little things that we don't note, but we see something that all together feels super cohesive, super considered, and it feels like it's all part of, you know, a very we designed experience. Versus, you know, if you look at a lot of kind of like discount stuff, when you use it, you're like, this does the thing that I want, but none of this feels -- it feels like it's there to solve a job, right? You're not going in for an experience. You're going in for a solution to a very particular problem.
And I do think that is -- it makes a difference. It lets you add, you know, brand value or if you're trying to become a luxury brand, like, that's what makes a luxury brand. All those sorts of things. There's a lot that goes into that.
The chat's saying their experience with Apple has been all bad. You must have started recently. (Laughter)
Speaking of, like, I've had some major Apple issues as well, but I still keep going back to them. I just got my phone back after, like, the third time. And, luckily, because -- it's so funny, I had an issue where my Macbook Pro,. The Apple keyboard and it broke. I take it in to get it fixed. One of the Apple repair reps broke my screen while they were repairing it.
So it was supposed to just be a keyboard change, right? Broke the screen. And here's what they did. They were like, okay, no one can find out I broke this screen, so I'm just gonna set this laptop on the shelf somewhere and forget about it. It was like three weeks later and I still hadn't gotten my computer back. My whole business is running on this thing. I'm using a 13-inch Macbook Pro from ancient times. I had to call them and be like, all right, what is the deal? They scrambled to find it. They were like, we lost your computer. We had to find it. They found it, the screen broken and pieced it together. Luckily, I got two sets of air pods out of it for free. What else did they give me? The good news is any time I have any problems, I retell that story and they look at my account and, like, for instance, I broke my phone. I told them that story and they're just like, oh, we'll get your phone fixed right away. Don't worry about it. So I got almost an Apple pass now for any time that is an issue.
I love that. Okay. So -- that's a good tangent. I like that. I feel like that's a really good example of, like, making lemonade, right?
Yeah, right, sure. At the time, not so much. Yeah, now, a lot of fun.
How powerful do you want to make this thing? Do we want to add some -- do we want to make it to be, like, a draggable square?
I want to strap this thing to a rocket ship.
Okay. Let's get ready for something called actions which are not animation-specific, but a way essentially to write your own plug-ins. This is something we do in our course, to some degree -- well, to a large degree. So we can go ahead and create another function. And this function --
Sorry, I just realized I can center this and it would work. I'm gonna do that so it looks nice. Professional. Look at this, too. When we did our easing, that box lightly overlaps our button. It just feels polished.
You can add, like, a shadow that goes -- gets bigger.
We can do all of that, like, here, right? We can just throw it in.
Oh, you bet you could.
Should we do it? Let's do actions. If we have extra time, we'll come back. So I'm going to create a new function.
This is just any action?
Let's call it drag.
Just because that's what it's gonna be doing.
This function is gonna be getting two parameters. Well, let's just give it one for simplicity's sake. Node. Nothing crazy about this.
And to kind of clarify why you're saying that, it's -- a lot of frameworks have, like, virtual dom nodes or some kind of proxy to the dom. So Svelte is giving you direct access to the actual dom, is that correct?
Yeah. In this instance, to build something that's draggable or whatever, we're working with straight-up dom APIs. We're not working with anything fancy. We aren't reaching into any libraries. We are going to reach into one library, but it's a Svelte-specific library and only to create the values we want out of this thing.
So before we even do anything, let's go ahead. We can set two variables. We can just say let x and let y.
Let x, let y.
And how should we do this? So we want to add -- we'll want to have functions for mousedown, mouseup, mousemove.
So, three functions. Mouseup, mousedown, mousemove.
And do I want to just create three functions with those names?
Yeah, let's go ahead and do that just to keep it --
Okay. So, now we need an event listener outside. We can do that -- you can do the event listener just underneath the let y. So we can say node.-- sorry.
We'll do a document one in a minute. Let's do node.eventlistener. This is listening for an event. Have it just be mousedown, which is all lowercase. We can just have it do the mousedown function.
Okay. Then we can do one for each, right?
Actually, we don't. We don't need to.
Oh, okay. All right. I'm getting ahead of myself.
For mouseup and mousemove, we'll want those to be on the window.
Got you. So should I still add them here or do we want to add them in the mousedown?
Let's have them be in the mousedown.
Import something up here?
Up top, yeah.
We're gonna want to import -- it's called spring, and it's from Svelte/motion. And what you can think about spring is, it's basically a way to subscribe to values and have the values interpolate between. While giving you so in a physics-based way.
So when you say interpolate, to put a very broad stroke on that, this is similar to how when we call this t function, if we console log it, it doesn't just go 1 to 0, it goes 1 and then we get 30 frames in between 30 and 1 where we get intermediate values.
Yeah, perfect. Let's go below our let x and let y, we can define our coordinates. We're creating a draggable thing. Basically creating a plug-in where you can do a one-liner on to anything you want and have it be draggable, right? Since we get access to the node itself, that allows us to attach it to any old node. You can call this coordinates. I use the word coordinates. You can use anything. Coords is good.
I'm not confident in my spelling.
Another tangent here, I tested into English as a second language in college. They were like, uh, are you sure you're an English speaker? (Laughter) My preparatory things were so poor. I think I got an 18 on my reading or something on the ACT. It was bad. So the first parameter's gonna be an object
And the object is going to be the values we're interpolating. X is equal to 0 or x:0 and y:0. That's all we need. That's basically creating the initial coordinates. What that gives us is the ability to do something like coords.update. Almost like a set state function in React, but the special added benefit of it giving us the values in between the values.
Got you. Okay.
So now when we -- when this gets called, we have our node. We set up some initial coordinates which are basically wherever you are on the screen, I'm assuming, is x and y?
Then we're setting this mousedown. So if I click on this box or the nodes, we haven't attached it yet. When I click on a node, it will fire this mousedown function which right now doesn't do anything except add our empty mouseup and mousemove.
Well, let's have it do something and then we can finish that mousedown move. We'll do two reassignments. First, we need to get the event from the function. So, the event will be the parameter.
And the event gives us all sorts of neat animation stuff. One of which is client x and client y. So we can say x is equal to event.clientx. This is the x and y. That way when we move the mouse, it is getting essentially the initial position when you click mousedown. So these are setting essentially the initial positions.
Gotcha. Okay, so, then this is not where it is -- this is just kind of, like, we're initializing it. We're not gonna use the 00, we're gonna use this?
Well, it's allowing us to eventually find the what's called the delta or, like, the distance travelled.
So the distanced travelled would be like -- yeah. So, like you said, the subscribing or the initial part when we set it with the coords, that was to give it the initial values, but that's sort of just the initial. Like, if you were to drag and leave it somewhere, then the next time you clicked and dragged to move it, you would want it to start at its new spot.
Kind of want to look for those right at that handle down. The next thing we want to do is get the deltas and everything else on the mousemove. Which is really the most fun part. Once we got mousemove, we can really start to see stuff happen in the dom in a second. So, we can create two values. One of which is dx and dy, standing for delta x and delta y. Dx is equal to, once again, the event, which we'll need.
And this will be event.clientX once more. So we're getting essentially the amount moved minus the x value.
And the same with y.
So, now if I click this and I move it 100 pixels, we don't want to know that it moved 100 pixels. We want to know that it's now positioned at, you know, x. If it was x100 before, it's now at x200?
So, same thing with y.
Oops, minus y. Okay. So, dx, dy.
Now, once again, we want to update the x and ys.
It's kind of interesting how this works. X is equal to event.clientX.
Same with the clientY. Now we get to do the spring update part.
So we can do coords.update. And this gives us a -- we'll want this to be essentially a call Boston -- callback function.
Okay. The first property is the current value. You can have it oh be current.
I named it wrong.
No, it's all good.
And we're going to return from here in object.
I assume we want to have our x and y, right?
Okay. Let's see if I can reason through this. So our current is gonna be wherever we started, right? So, at the beginning it would be, you know, 0. We want to figure out where it's moved to so we want to add the delta. So we're gonna say current.x plus dx.
Hell yeah. Oh, h yeah.
If we save this hi should be able to drag it around.
One, we haven't attached the drag to anything. Two, we haven't attached the properties to anything either.
So a good one would be -- so let's go all the way up top to where we had our coordinates defined. And we can do -- so just below that, we can do something called a subscribe.
So we can do coords.subscribe, which means every single time there's a change happening, this function will run, which once again will give us the current coordinate values as a callback.
So, current.x pixels? Current.y pixels, and we'll do 0 for the z.
Perfect. So now I think we should be able to see this in action if we did everything right by adding this to the component.
This is where it gets fun. Just head to that box, any dom item you want, whether it's the box or button and you can just do use:drag, whatever the name of the function is.
So -- yeah, in our course, we make this dragging plug-in.
Oh, my God.
We show you that you can add it on the -- now, you want to do something even cool here? Because I'll show you how cool this can get. It's very -- okay, so, let's step it up. And on the mouseup, you can remove the event handlers.
Holy buckets, did that just work?
On the mouseup, we can window.removeeventlistener.
Yeah, and you'll want to remove the mouseup.
Mouseup,mouseup and mousemove. Okay. So now it's basically like a click and drag, right? So when I do this, I stop. Now it's stuck.
How would you -- if you wanted to get -- have it go back to its origin, what would you do?
I would set the node style transform to 00?
We want to use our spring based animation interpolation. So we get to do the coords.update.
And I don't need this anymore so I can just return x: 0, y: 0.
Yeah, but you want to wrap that in a parens.
And probably do the x and y equal to 0.
You are correct. That is definitely what I want to do. So let's return that. But what we will also do is just set x0, y0. Are you gonna clean that up for me? You're not?
Okay. So, now it's cleaned up. Okay, so, now it has --
Zip. And here's something fun. Go -- go back to your HTML and head to that animation in Svelte h1 and does just, use drag on that baby. Drag it.
But that spring stuff makes it so much nicer to use, that, like, you can kind of want that, right?
How would you feel about adding a custom event to this thing.
I would feel so good about it.
Okay. Let's go to that handle mouseup. On the mouseup, we want to fire an event that says we've stopped dragging this thing.
I have but I can't tell you why.
I had never used this before getting into Svelte animations. Where we actually create our own custom event. By saying node.dispatchevent. We can ask the first parameter to say new, capital C Custom. Call it drag stop or whatever you want. And then comma. The second parameter is going to need detail -- sorry, it's going to be an object. I should say that. And detail is gonna be an object. And now this could have any property you possibly want. Let's say when you dragged and stopped this thing, you wanted to get the current x and current Y value.
Of which you could just say x and y here. Although, you'd have to move this up.
I guess you wouldn't because you didn't -- oh, sorry. That x and y that's in your coord, that should not be in the coords update. That should just be in the mouseup function.
Oh, I got you. So we'll just move it down here.
Yeah, perfect. In that detail, you can literally put in anything you wanted in here. Like anything you can possibly dream of. But it's just the information you would want on return of that event.
And so, like, examples for why you would actually use this is, like, if we -- if we wanted to do something where, say, when we dragged this, when we let go, we wanted to stick a new box there that was kind of, like, ghosted. So you could sort of keep a track of where you would drag two or something.
Yeah, we did that really easily.
Yeah, all right.
Yeah, let's do it.
Head on into your HTML. I think the rest might be HTML stuff. Well, just about. So, let's do it on that box.
I'm just gonna break this up so we can still read it on screen.
Use: Drag --
I think we called it dragstop.
Yeah, this is just gonna be a function. Have it be inline or external, whatever you want. And, yeah, classic --
What just happened? What was that?
I know. It does that to me, too.
Okay. And so our event here, now, this part I don't remember. Can I just get event.details?
Detail. Oh, did it need to be detail up here, too?
Yeah, did you do details?
I think I did. No, you did not steer me wrong and I actually listened, so, here we go. So, now whenever we do a drag, what we should see is -- there it is. There is our x and y.
Essentially setting the state of that box to be hidden.
So, we'll start here. Nothing changes. Oh, there it goes. I dragged it too far. And it's back.
So, if you think about it, if you only animate the x property of this, only left and right instead of up and down, you would have effectively built the tinder interface, right?
The whole swipe card thing.
So we would just end up adding -- so right now what we're doing is we're having it disappear like that. We would just add a different animation to throw it to the right or to the left.
That's pretty powerful stuff. I also love that we're kind of able to reset here. So if we throw it off -- and I did not expect that to work. Logically it makes sense now that I'm seeing it happen and we're using that isActive. The fact we were able to build this complex state where different actions cause things to change, moving this around. It gets hidden and just have a button to say, okay, you can reset that. Beautiful. This is really well done.
In and out of the dom.
That's a good point. Let's look at the dom. So if we pop this open a little wider so we can actually see what's going on, and we look at our body -- we've got our h1, our button and our div. That is really slick. So, the amount of script that we're actually loading. Let's take a look at how much we're actually loading here.
This is in --
This is a dev bundle.
But in prod it's like nothing.
So 183 kilobytes.
So, like, currently, the Svelte team is working on moving Svelte and their full-stack solution for Svelte over to Snowpack using something called Svelte Kit. Can you imagine the stuff getting smaller and faster? To me, it's already small and fast. This is gonna be great. It's just gonna keep getting smaller and faster.
Yeah, that's really, really nice. As we can see, I just dragged that out and it disappeared from the dom entirely. It's not set to opacity zero. When I hit the button, it comes back in, does its transition and we're good.
There are certain use cases where CSS transitions are more appropriate or removal is more appropriate and all that CSS class-based transition stuff works just as well in Svelte.
This is -- this is really slick stuff. Like, I feel like I can see so much potential for what is possible without having to learn a bunch of external libraries. I think the thing that is exciting about this to me is, like, I know that no matter what you're using, you can do animations like this. What I think is really exciting about this approach in Svelte is that we have not used a single third-party dependency yet. We have only use built-in Svelte stuff, and when we use this built-in Svelte stuff, it allows us to, you know, we can write our own custom transitions, we can write our own custom actions and this is powerful stuff, that we can just, you know, immediately put together and drag and drop with this nice effect. Like, that is really cool that that works.
If you wanted to make it more complex, any of your actions can take parameter values as well. You can always pass in an object full of parameters. That action function -- the second argument in that action function is the parameters. So in my course, one of the things we do when we build this drag and drop thing we say -- what did we have? The two parama are basically like is y active or is x active? And by default, they both are. You can have only drag on the x. Only drag on the y just by adding a single parameter to it.
So I'm just playing here. If we add a parameter for color
Then we'll be able to send that color out with the custom dispatch event. And so then down here, if we use drag, we can give it a color of let's go purple.
And once it's done, we could say event.target, probably?
I think so. Style.color equals color.
So what should happen now is if I drag this, it should turn purple. No, I broke it. I think it might be because of the event.target because I don't know what the -- do I need to pass it a node? Color is not defined. I defined you.
Style.color. I actually don't know about this.
Not read property of undefined. I'm doing something wrong. Background.
Oh, somebody is saying event.detail. So, does this event return the node itself? You could have this return the need itself.
Oh, yeah, just, like, throw the node right into it?
Let's do that. That seems fine. So we'll get the -- instead of event.target.
Because this is a custom, yeah --
So then what we can do is we'll do event.--
I haven't done this before. This is interesting.
Cannot read property of undefined. No, I'm telling -- I'm giving you.
Can't read property color of undefined.
Oh, oh, oh, I know why. It's because we're not providing a default. Let's go back up to our drag. Because this might be undefined, we need to also default that.
Oh, man. Yes. Perfect.
Okay. So, now what should happen -- this is what I get for trying to be clever. Color is not defined. Where? Color is not defined on -- did I not destructure this out properly?
I don't know. It's hard for me to tell from here.
No, it's just me being bad at stuff. Event.detail.color. This one's gonna work. Get ready.
Look at it go.
No, I have to reload, but, you know, this is slick, right? So, you can see that with a little bit of fumbling, I haven't opened the Docs ones. We were able to figure out how to mess with that, so that when you activate the box, basically by dragging it, you get a color change.
And you know what? If you didn't want to do that whole node passing business, you could even have that node color change happen in the action, the drag action as well.
And the coolest thing about any of that as well is that the spring motion, the motion spring thing that comes with Svelte doesn't just work on, you know, straight-up numbers. I think you can -- you can interpolate between colors as well. I have not used but I think you can. Let me see. So, the spring -- I'm pretty sure you can transition between colors as well.
Ooh, that's cool.
So, I know you can with the tweened version of it. So that would give you the able to add that physics-based tween to the -- like, if you were to put the color in --
Like, in my coordinates or something?
Yeah, I'm wondering if it this would mess up the drag parameters.
Yeah, you know what? Let's not worry about it. Because what I'm actually more curious about, I'm actually really curious to see what happens when we deploy this. So what I'm gonna to is I'm gonna back this decision out. So we will not do the color anymore.
I'm just gonna leave the color off so that we don't have to deal with that. And I'm going to drop it out of our custom event as well. So we don't need those anymore. We're not using them. And I'm gonna drop out our -- where's my drag? Let's just get rid of all of that. Okay, so that was fun, but that's not what we're interested in. What I'm interested in is what happens when we build this thing. And so build is just a command like this. So, let's pull up here I'm gonna run npm.run.build. Okay. Now I want to serve this and I just want for see how small the bundle is. So, let's reload. And I'm gonna go to my network tab. And I think this is the updated version here. 14 -- so the rest of that is HTML CSS, you know, the actual document itself, but that is really slick. Let me make this a little bit bigger so we can see. 9.1 kilobytes. While I'm doing that. I know you just did a course on this. What else would somebody learn if they took this course?
There is a lot of neat stuff. We mentioned beginning there is flip animations, this thing called cross fade which is really tricky because the Docs aren't great on it. Cross fade allows you to essentially take an item that is in one container and an item -- I mean, let's say you have two containers. Items in a container, let's say you want to move a jelly bean from one jar to the other. Well, it's gonna allow you to animate, like, basically what you do in the HTML is you say jelly bean, go in other jar. What cross fade does is allow that animation to be automatic between those two locations so you don't physically have to tell the jelly bean, all right, translate 800 pixels this way. Here is the end state in the dom, and now fade between the two. And my man Mark's got a nice little REPL in the chat there.
Let me pull that up.
You'll get those kinds of things. Cross fade. I also talk a little bit about staggering animations, which are shockingly easy.
Ooh, that's really nice.
Yeah, we go a little more in depth into the actions bit of creating that drag plug-in. We talk a little bit more about the custom animations. And there's a whole bunch of, like, little things here and there with subscribing to events. So the course is really built on the idea of practical animations. So we built this really, really nice-looking model. And it functions exactly how you like. Sort of like all the animations where it just kind of fades up and in, fades up and down, you know, when you close and open it. Gives you several click points to close it, whatever. We built, like, a toast app, like a little toaster. Like, a toaster --
Where you can bring in alerts and it's just so simple. We talk a little bit about subscribing to values. So in this, we did a little bit of that, where we subscribed to the -- what did we subscribe to? We subscribed to the values for the spring animations. The course we get into subscribing to do more practical things. For instance, the toast message should close itself after three seconds. So how do we listen for that animation to have happened or those values to have changed to then trigger that listen to then close the message or whatever? So it's really focused on hyperpractical animations. Stuff you're going to use in everyday sites. I think we introduced some scroll-based animations. So, it's very, very practical. And you'll get a lot of stuff out of it. By the end of it, you'll feel confident animating pretty much anything in and out in Svelte.
So, we've got animating Svelte. This is the tutorial. What you can learn. Yeah, I mean, it's -- oh, dang, it's marked down now, too. So, that's exciting.
Yeah, I left the Black Friday sale on -- it's not advertised being on. I have some things on discount from Black Friday. Maybe another week or so until I feel like turning it off.
Nice. Get that before Scott gets around to cleaning up his discounts.
Exactly. When you have, like, 50-some tutorial series and you have to do that manually, I guess I'll take everything off discount.
But, yeah, so, check this out, y'all. I was able to -- this is live. This is up on Netlify. I was able to deploy this. It's working. If we go off to the right, it disappears. We're able to bring it back. And this whole thing runs on, like, nothing.
I mean -- and even if, like, not to throw shade on frame or motion because that's the first thing I would do in React, to install frame or motion and throw some drag properties on there, right? This is essentially the same thing you would get from there but, again, no shade on frame or motion. It's my favorite React animation tool. That's still a huge bundle of code to be adding, probably more than this entire site just in one plug-in alone.
500 seems reasonable when you have sites shipping several --
But, so --
It's the world we're living in. It's cool. We're getting server components in React, so --
Yeah, I mean, I was able to build Level Up Tutorials and design it by myself. That should tell you because I'm not a back end developer. I wrote the API in the back end for this and whatever, but that's not my specialty, you know? My specialty is CSS and animation stuff.
So, like, if somebody like me can create something, like, this full-featured from scratch, then, like, man, I'm -- that was actually the big thing for me with React. It was like it allows us to create the types of things that our clients always asked us to do.
And we were always like I don't know. Like, what? I guess I can build, you know, a chat app for you. Facebook had 500 engineers or something work on. Sure, I'll take it on.
Yeah. Well, I feel like I could talk about this for days, but, unfortunately, we are out of time. Let me do a quick shout-out to the sponsors. We've hat White Coat Captioning. Thank you, Jordan, for doing captioning today. White Coat Captioning is the company that does it. Jordan is our captioner today. Made possible by our sponsors, Netlify, Hasura and Auth0, all of whom are kicking in a little extra cash because I definitely couldn't afford it on my own. Scott, where should people follow you? Anywhere else you want them to go?
Head on over to syntax.fm, which is not something we mentioned yet, our podcast we do with Wes Boss.
We do two episodes weekly and we are ready for 2021. We have just a crazy amount planned for episodes next year. So, very excited. And we've been kicking on that for a couple of years now. And it's going really well. So that's -- those are the places to find me.
Awesome. Well, thank you so much for taking time out to do this. I know you got a lot of videos to get edited before you can take your holiday break. For all of you watching, thank you so much for hanging out with us today. I hope you enjoy your holiday break. Make sure you check out the schedule because we've got a lot of -- we've got a stampede to end the year. Excellent timing. Let's go look at the schedule while we're watching that stampede. We have when we come back in January, Orta is coming to teach us TypeScript. We've got Emma coming back and we're going to continue talking crap to each other about Tacos. Alley is going to teach other React. Scott moss is going to teach us next JS. Then we got Sarah's gonna come and do -- this is gonna be a little bit of a different formatted. Mark your calendars for this. Especially if you're looking for a job. Sarah's gonna come and do a Q &�A about how she -- she's the VP of developer experience at Netlify. How is she hiring people and how can you as a developer make yourself stand out to get hired? We've got so much stuff coming. Keep your eye on this schedule. It just gets better and better. I'm always blown away by the people who are willing to come and teach us. You can add this to our calendar. We've got a Google Calendar. Which is, oh, boy, what is it? Lwj.dev/calendar, I think. Let's find out. Nope, that's not it. If one of the mods remembers, that would be super useful. On that note, we're out of time. Scott, thank you so much for hanging out with us today. Y'all, stay tuned. We're going to go find somebody to raid. We will see you next year