A simple dashboard using React hooks and D3 — Part III

The Line Chart Component

Alessandro Cristofori
3 min readMay 31, 2020

--

The Line Chart component is basically a line connecting a series of dots placed on the coordinate system of our svg canvas. In this example, on the x axis we have the years referred to the sales of items and on the y axis we have the amount of sales for that year. On top of the line we will plot the dots in correspondence with their x,y position, the dots fill colour will be white except for the minimum and maximum y value, these will be red and green respectively. Let’s have a look at the code.

Translated in React and svg, the LineChart component will combine the Line and the Dots components. The first one is a <path> element which x,y coordinates are adequately scaled to our data with d3, the second component encapsulates an array of <circle> elements placed on top of these coordinates, hence they will be scaled in the same way as our line. The react components have their own useEffect hook that will fire up a method to animate the svg element inside them, using the d3 DOM manipulations methods and transitions. Our LineChart component will have its own data source in a separate file, the props passed from the parent App will update the props on the children component that will in turn trigger the useEffect hook and the animations, the same way we designed it for Our Donut and Slice components.

While the process of animation of the Line component is not much different than the Slice component (d3 updating the d attribute of the our path svg element) when we will animate the Dots we will have to follow a slightly different process. The animateDots function expects both the group <g> svg element, containing all our <circles> together, and the selectedData containing the array of data which is updated on each slice selection.

const animateDots = (xScale, yScale, dotsContainer, dotsColour, selectedData) => {
const dotsCoords = selectedData.map( (item, index) => {
return {
x: (xScale(index) * 0.10),
y: (yScale(item.measure) * 0.10)}
});

const dots = dotsContainer.selectAll('circle');
dots.each(function (d, i) {
select(this)
.transition()
.duration(650)
.attr("cx", dotsCoords[i].x)
.attr("cy", dotsCoords[i].y)
.attr("fill", getDotColour(i))
.attr("stroke", dotsColour)
.attr("stroke-width", 0.150)
});
}

Since we expect the number of dots to be the same as the number of data items, we first iterate/map our data in the dotsCoords variable; calculating the updated x,y coordinates for each data item using the xScale and yScale functions. Secondly, using the d3 function selectAll('circle') we select all <circles> in our group and we iterate through them, again using the each function of d3. We will apply the new coordinates in dotsCoords to the cx and cy properties of <circle> matching the index of each element in both arrays, each has as second argument the index of each item in the selected group.

The Line chart component contains more text and colour definitions for its children components, as the process of creating and updating these is the same as we used for both the Bar and Donut component you can have a look at how these is made to get an idea of how the animations work.

--

--