Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
D3 lets us add graphics to a front-end web app easily.
Vue is a popular front end web framework.
They work great together. In this article, we’ll look at how to add graphics to a Vue app with D3.
Create a Bar Chart
We can create a bar chart with D3 in our React app by reading in the data, creating the axes, and adding the bars.
For example, we can write:
public/data.csv
year,population
2006,20
2008,25
2010,38
2012,61
2014,43
2016,26
2017,62
src/App.js
import React, { useEffect } from "react";
import * as d3 from "d3";
const createBarChart = async () => {
const svg = d3.select("svg"),
margin = 200,
width = svg.attr("width") - margin,
height = svg.attr("height") - margin;
svg
.append("text")
.attr("transform", "translate(100,0)")
.attr("x", 50)
.attr("y", 50)
.attr("font-size", "20px")
.attr("class", "title")
.text("Population bar chart");
const x = d3.scaleBand().range([0, width]).padding(0.4),
y = d3.scaleLinear().range([height, 0]);
const g = svg.append("g").attr("transform", "translate(100, 100)");
const data = await d3.csv("data.csv");
x.domain(
data.map(function (d) {
return d.year;
})
);
y.domain([
0,
d3.max(data, function (d) {
return d.population;
})
]);
g.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("y", height - 250)
.attr("x", width - 100)
.attr("text-anchor", "end")
.attr("font-size", "18px")
.attr("stroke", "blue")
.text("year");
g.append("g")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "-5.1em")
.attr("text-anchor", "end")
.attr("font-size", "18px")
.attr("stroke", "blue")
.text("population");
g.append("g").attr("transform", "translate(0, 0)").call(d3.axisLeft(y));
g.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.style("fill", "lightgreen")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("x", function (d) {
return x(d.year);
})
.attr("y", function (d) {
return y(d.population);
})
.attr("width", x.bandwidth())
.transition()
.ease(d3.easeLinear)
.duration(200)
.delay(function (d, i) {
return i * 25;
})
.attr("height", function (d) {
return height - y(d.population);
});
function onMouseOver(d, i) {
d3.select(this).attr("class", "highlight");
d3.select(this)
.transition()
.duration(200)
.attr("width", x.bandwidth() + 5)
.attr("y", function (d) {
return y(d.population) - 10;
})
.attr("height", function (d) {
return height - y(d.population) + 10;
});
g.append("text")
.attr("class", "val")
.attr("x", function () {
return x(d.year);
})
.attr("y", function () {
return y(d.value) - 10;
});
}
function onMouseOut(d, i) {
d3.select(this).attr("class", "bar");
d3.select(this)
.transition()
.duration(200)
.attr("width", x.bandwidth())
.attr("y", function (d) {
return y(d.population);
})
.attr("height", function (d) {
return height - y(d.population);
});
d3.selectAll(".val").remove();
}
};
export default function App() {
useEffect(() => {
createBarChart();
}, []);
return (
<div className="App">
<svg width="500" height="500"></svg>
</div>
);
}
We add the svg
element in our template.
Then we create the title by writing:
svg
.append("text")
.attr("transform", "translate(100,0)")
.attr("x", 50)
.attr("y", 50)
.attr("font-size", "20px")
.attr("class", "title")
.text("Population bar chart");
x
and y
are the x and y coordinates of the top left corner of the text.
transform
transforms the text by translating it.
The font-size
has the font size for the title.
Then we create the x
and y
ranges we use for the axes:
const x = d3.scaleBand().range([0, width]).padding(0.4),
y = d3.scaleLinear().range([height, 0]);
const g = svg.append("g").attr("transform", "translate(100, 100)");
const data = await d3.csv("data.csv");
x.domain(
data.map(function(d) {
return d.year;
})
);
y.domain([
0,
d3.max(data, function(d) {
return d.population;
}),
]);
We set the domain of x
and y
with the domain
method.
Then we create the x-axis with the axisBottom
method:
g.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))
.append("text")
.attr("y", height - 250)
.attr("x", width - 100)
.attr("text-anchor", "end")
.attr("font-size", "18px")
.attr("stroke", "blue")
.text("year");
The attr
method sets all the CSS styles.
Then we add the label for the y-axis by writing:
g.append("g")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "-5.1em")
.attr("text-anchor", "end")
.attr("font-size", "18px")
.attr("stroke", "blue")
.text("population");
Then we add the y-axis itself by writing:
g.append("g").attr("transform", "translate(0, 0)").call(d3.axisLeft(y));
And we add the bars by writing:
g.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.style("fill", "lightgreen")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("x", function(d) {
return x(d.year);
})
.attr("y", function(d) {
return y(d.population);
})
.attr("width", x.bandwidth())
.transition()
.ease(d3.easeLinear)
.duration(200)
.delay(function(d, i) {
return i * 25;
})
.attr("height", function(d) {
return height - y(d.population);
});
We add a mouseover
event listener that expands the bar when we hover our mouse over it.
Also, we add the mouseout
event listener to restore the bar to its original size when we move our mouse away from the bar.
We set the x
and y
attributes so that we can position it on the x-axis.
Then, we add some transition to it when it’s loading with the transition
, ease
, and duration
calls.
And finally, we set the height of the bar to by setting the height
attribute in the last attr
call.
Conclusion
We can create a bar chart from CSV data with D3.
The post Adding Graphics to a React App with D3 — Bar Chart appeared first on The Web Dev.