Render an X Axis for a Bar Chart with D3 and React

Andy Van Slaars
InstructorAndy Van Slaars

Share this video with your friends

Send Tweet
Published 2 years ago
Updated 2 years ago

In this lesson, we'll take advantage of our xScale and the bottom margin to create an axis to start giving our data meaning. We'll access ticks from the scale and then use React to render and position the SVG rect and text elements to create the x-axis for our chart.

Andy Van Slaars: [0:00] We're rendering an SVG, and we have bars that represent our data points. We have no indication of what those values are. Let's add a bottom axis, so the width of the bars can start to convey some meaning to people who are looking at this chart.

[0:12] I've added a new component to the project called bottomAxis. Right now, it just renders out an empty SVG group element. Back in chart, I want to import this. I'll import, and we'll pull in bottomAxis from that Vue file. Let's render this in our component.

[0:31] We're going to go down into our chart component, below our group, and we're going to render out bottomAxis. We need to pass in some data for this to work. We're going to start by giving this our margins object, that we pull in from dimensions. We're also going to give it our boundedHeight, and we're going to pass our xScale.

[0:56] Let's switch over to bottomAxis. I'm going to come up here. I'm going to start by destructuring my props. I'm going to define a const margins, xScale, and boundedHeight. I'll just pull those off of props. Inside our empty group here, let's just create a rectangle temporarily so that we can see what we're doing. I'm going to add a rect element, and I'm going to give this a fill of light blue.

[1:25] I'm going to give it a height of margins.bottom because I want it to fill this space down here. I'm going to give it a width that I'm just going to hard code at 445 px. That happens to be our bounded width with our current numbers. We don't need it in here.

[1:44] This is temporary and it'll get deleted. I'm not going to pass that value in as a prop, but I am going to use the hard-coded value here just so we can see this rectangle. I'm going to save this, and you'll see that we have this light blue rectangle.

[1:57] On top in the top left corner, and it's probably the right width, but it's obviously not respecting the margin. We need to get that down here. To do that, I'm going to go into this group element and I'm going to give this a transform prop.

[2:12] We're going to use another translate. We'll translate here and we're going to translate the x. That's going to be based on margins.left. Then we need to translate the y as well. Here, we're going to use our boundedHeight and we're going to add our margin.top.

[2:30] We save that and we'll re-render. You'll see that our bottom axis rectangle is sitting in the place where we expect it to be.

[2:37] Now that our axis is properly positioned, let's add some data text to it. I'm going to drop down under the rectangle here. I'm going to make a call to xScale.ticks. Ticks is going to give us back an array of numbers that are evenly spaced along our axis. I'm going to map over that. For each one of these ticks, I'm going to render out a new SVG group.

[3:02] We'll give each group key, so React doesn't give us warnings and we'll make that the tick. Then we'll close out our group. Inside each group, I'm going to create a rectangle and I'm going to give it a height of 15. I'll give it a width of 3.

[3:24] Then, in order to position these properly, I also need to give it a transform. In my transform, I'm going to use translate. I want to translate the x here, so I'm going to use my xScale, and pass it in the tick and then I need to close out that rectangle element. When we save this, we should get evenly spaced rectangles marking out data points along our bottom axis.

[3:51] The ticks are a good starting point, but we still don't know what they represent. Let's add some text labels in here to show our ticks along the bottom axis. Inside the same group right below our rectangle, I'm going to add an SVG text element. I'm going to give this a font size of say .75 rem.

[4:10] I'm also going to give it a dominant baseline prop. This is going to be set to hanging. This will make sure that where we position this is based on the top of the text, so that it hangs down from whatever that position is. I'm also going to give it a text anchor of middle so that we can center this text horizontally.

[4:30] Then we also need to give each one of these a transform to position it. Our transform here, we'll get a translate and our x position is going to be based on our xScale applied to the tick mark. Because our ticks are 3 px wide and we're trying to center this text, we're also going to add 1.5 to this.

[4:51] Then we're going to set the y to 17. I'm going to hard code this value for now. This is basically adding 2 px to the height of our rectangle here. Then inside our text element, we're going to use our tick value for the actual text. Then we can save that. We should see that we get numbers applied to our tick marks across our axis.

[5:11] There are rendering our tick marks along with our labels. You'll notice that our labels are being cut off and they don't exactly fit within our margins. Let's go back to our app component where we define our margins, and let's give everything a little bit more breathing room.

[5:25] We're going to bump the right margin up to 15. Then we're going to take our bottom margin and we're going to bump it up by 10 px and set it to 35. I'll save that. You'll notice that everything gets squeezed in.

[5:38] We have a little bit of overhang here because we've hard coded the width on our blue rectangle, but that's OK. We're going to delete that. Now our margins give us enough breathing room. Everything else has been recalculated because we're doing everything based on our dimensions and our scales.

[5:52] If I come back over to bottomAxis, I can come up here and I can delete this temporary rectangle, save that, and everything looks just fine.