Contents

How to Make your Chart Dynamic in D3.js?

Contents

Hello! Welcome to this new article about data visualization.

After creating an update function that allow our chart to be updated each time data will change, we will make the chart dynamic.

In this post, I will show you a very simple dynamic way to switch between two datasets.

The idea is to use a flag variable that will switch every period of the update function between True or False. For each situation, we display different data. Let’s do it!

Note: Do to this, you need time series data with two categories. For instance, in my article I use the yearly revenue and yearly profit of a fake company.

First, we want to be sure that our data is integer so we use the method Number() on both revenue and profit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
d3.csv("mydata.csv").then(data => {
	data.forEach(d => {
		d.revenue = Number(d.revenue)
		d.profit = Number(d.profit)
	})
d3.interval( () => {
	update(data)
}, 1000)
update(data)
})

If it seems unusual to you, see the article on How to add external data in D3.js?.

Now, we declare the variable “flag” above the data loading. let flag = true Notice that we use “let” instead of “const” because we will reassign this value every run of the interval function. Then in our interval function, we redefine flag at each second as the opposite of flag:

1
2
3
4
d3.interval( () => {
	flag = !flag
	update(data)
}, 1000)

Now we declare a “value” variable into the update function:

1
2
3
4
function update(data){
    const value = flag ? "profit" : "revenue"
    ...
}

If flag is true, value will be define with “profit” and if flag is false value will be define with “revenue”.

Now that we have done this change, we have to make few edits to make this works.

We replace each of the revenue fields with the name of the value variable. Therefore, these values can switch between “profit” and “revenue” every second.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function update(data){
   const value = flag ? "profit" : "revenue"
    y .domain([0, d3.max(data, d => d[value])])    // input
    x.domain(data.map(d => d.year))    // input

    const xAxisCall = d3.axisBottom(x)
    g.append("g")
        .attr("class", "x axis")
        .attr("transform", `translate(0, 340)`)
        .call(xAxisCall)
        .selectAll("text")
        .attr("y", "10")
        .attr("x", "-5")
        .attr("text-anchor", "end")
        .attr("transform", "rotate(-40)")

    const yAxisCall = d3.axisLeft(y)
    .ticks(3)
    .tickFormat(d => "$"+d)
    g.append("g")
      .attr("class", "y axis")
      .call(yAxisCall)
      
   const rectangles = svg.selectAll("rect").data(data);
   
   rectangles.exit().remove();
   
   rectangles
	.attr("y", d => y(d[value]))
	.attr("x", (d) => x(d.year))
	.attr("width", x.bandwidth)
	.attr("height", d => 340 - y(d[value]))
	
    rectangles.enter().append("rect")
	.attr("y", d => y(d[value]))
	.attr("x", (d) => x(d.year))
	.attr("width", x.bandwidth)
	.attr("height", d => 340 - y(d[value]))
	.attr("fill", "green")
}

Finally, you can see that the visualization is updating every second as expected.

That’s if for this post. I hope you enjoyed it, feel free to ask your questions in DM.

See you!