Lines

We talk through a more complex example: animating our line chart when it gets new data. This is trickier than it might seem at first!

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Fullstack D3 Masterclass course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Fullstack D3 Masterclass with a single-time purchase.

Thumbnail for the \newline course Fullstack D3 Masterclass
  • [00:00 - 00:24] Okay, so now that we understand the three, but really two ways to animate our charts, CSS transitions and D through transition, let's look at one more example of how we might add a transition to one of the charts we've already created. So in our example, we have our timeline and we have this new method called add new day.

    [00:25 - 00:50] And every 1.5 seconds, we have an interval running and every 1.5 seconds we run add new day, which takes the data set, slices off the first point in the data set and then adds a new data point. So we really want our line to be shifting over like this, but we want it to animate nicely so it's not just jerking over.

    [00:51 - 01:08] So let's look at our line and maybe you're looking at this and you're saying, well, clearly we can just add transition to this line. So we add a transition here changing to a transition object.

    [01:09 - 01:17] And what we're going to see is our line kind of jittering. It's actually a little bit worse than it was without any transition.

    [01:18 - 01:49] So what's happening is when that new data comes in, the attribute method is basically assuming that each data point is in the same index. So it's switching between, so for this specific point, it animates to the new value instead of shifting to the left because how would it know that our line is shifting to the left instead of just changing its shape?

    [01:50 - 02:05] So we can't use this, but what can we do? Instead, what we're going to do is we're going to take our line and shift it to the right and then animate it shifting back to its original position.

    [02:06 - 02:13] And it's a little bit complicated, but just bear with me. And hopefully it'll make sense by the time we've implanted this.

    [02:14 - 02:29] So what we want to do is calculate the amount that each point is going to move for each update. So what we want to get is the distance between a point and the next point.

    [02:30 - 02:36] So what we want is we want to grab the last two points in our data set. So last two points.

    [02:37 - 02:50] And then we're just going to slice off data set dot slice the last two elements in our data set. So let's log that out and make sure that's giving us what we need.

    [02:51 - 02:55] There we go. We got these last two data points and that's running every time we update.

    [02:56 - 03:19] And then what we want to do with that is we want to get the number of pixels in between these two points. So we can use our X scale to look at the X position of this first point.

    [03:20 - 03:41] Actually let's get the position of the second point and then subtract the position of the first point because we know the points are always going to be from left to right. And then let's name this pixels between last points.

    [03:42 - 03:57] And then what we want to do is grab this and then subtract that X value for this first point. So not this minus itself but this minus the X position for that first point.

    [03:58 - 04:03] Let's get that out. Okay great.

    [04:04 - 04:14] So we're seeing six here. Let's just clear this.

    [04:15 - 04:22] You know sometimes code sandbox gets a little bit iffy with intervals. Like it won't cancel an interval when it refreshes.

    [04:23 - 04:39] So just watch out for that when you're experimenting here but right now we can see there's about six and a half pixels between two points. So there's six pixels between a point and then it's next position when it's updating.

    [04:40 - 04:50] So what we want to do is actually grab our line, transform it. So transform.

    [04:51 - 05:09] And then we want to shift it over by that number of pixels. Translate X and then let's grab this value and it's going to be in pixels because it's a CSS style.

    [05:10 - 05:22] So right now we can see that our timeline is shifted over a little bit. And what we want to do is add transition that will then remove that style.

    [05:23 - 05:51] So we want the transform to be none. So what we're seeing here is it's a little bit tricky but our timeline basically when it updates is instantly shifting over by one data point and then animating its transition over by that amount.

    [05:52 - 06:20] So we can see the first point here, the first line segment kind of disappears and that's when you know it's been shifted over and redrawn and then it kind of animates the transition back over to the left. One thing that's kind of bugging me here though is that the end of our line is appearing kind of all at once and that can be a little bit jarring.

    [06:21 - 06:38] So one way we can combat that is adding a clip path around our chart. So a clip path is basically just a way to change which parts of a shape you're showing.

    [06:39 - 06:56] So we're going to add a clip path that's a rectangle that's the same size as our bounds and anything outside of that is not going to render. So otherwise it'd be harder to incrementally draw the end of that line but this clip path is going to make it really easy.

    [06:57 - 07:11] So with a clip path you want it to be within an SVG element called DEFS and let 's actually take a peek at our SVG cheat sheet. So we have clip path and we want to store in DEFS and DEFS is another element.

    [07:12 - 07:27] It's short for definitions and this is for any elements that you want to use elsewhere. Anything within the DEFS element won't be rendered so it's nice to create our clip path there and then use it somewhere else.

    [07:28 - 07:48] So let's go ahead and add a new DEFS element here on our bounds. Let's just call this clip path.

    [07:49 - 08:17] We won't actually be using this but sometimes it's nice to name variables even if you won't use the reference and then bounds append a new DEFS element and then within that we want to append a new clip path. And then for our clip path we'll need an ID and the ID will help us refer to it elsewhere.

    [08:18 - 08:35] So we'll have this clip path and then anything we want to be drawn within the clip path we'll set clip path CSS style or it's actually it can also be an attribute. We'll set that to refer to the ID of this path.

    [08:36 - 08:45] So we'll want to set an ID attribute. Let's just name it bounds clip path because it'll be the same size as our bounds.

    [08:46 - 09:05] And then here we'll want to draw a shape inside of our clip path that is going to be the visible region within our clip path. So if we have nothing drawn within our clip path basically nothing is going to show up if it refers to that clip path.

    [09:06 - 09:33] But if we have a circle then only that circle will show up but now we'll want a rectangle that is the size of our bounds. So we're going to append a rect and then let's set it to be the width of our bounds to attribute width dimensions dimensions that bounded width.

    [09:34 - 09:44] And then the height is going to be dimensions that bounded height. All right so now we have our clip path.

    [09:45 - 10:01] How do we use it? So the way we use this clip path is we're going to want to put our line instead of something that doesn't show outside of the clip path.

    [10:02 - 10:25] One way we can do this is to add a group and then add any elements that are clipped to use it within that group. So let's bounce, let's append a new group here and then the way we actually here let's do it this way.

    [10:26 - 10:36] So we have this clip group and so everything we want to be clipped let's throw in there. So instead of appending our path to the bounds let's append it inside of our clip element.

    [10:37 - 10:54] And as we can see the size doesn't change very much because it's not referring to that clip path. So the way we tell our SVG element to be clipped by a specific clip path is by the clip path attribute.

    [10:55 - 11:17] So for the value here we want it to be URL and then something that points to the clip path. We've been using a lot of selector strings hash refers to an ID so we're going with the ID and then whatever string we have for the ID of our clip path.

    [11:18 - 11:39] So let's throw that in here. So it's kind of a subtle change but if we look we'll see that that end of the line new segment is kind of coming in and being drawn as it moves over which is just a little bit more polished than having it thrown in there all at once.