Skip to content

Instantly share code, notes, and snippets.

@lancegliser
Created March 12, 2020 13:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lancegliser/906df57db229fe9c9a9fad59b9c2ae92 to your computer and use it in GitHub Desktop.
Save lancegliser/906df57db229fe9c9a9fad59b9c2ae92 to your computer and use it in GitHub Desktop.
A dirt simple example of a D3 chart using multiple lines, dots, and text elements on version 5.
const render = (data) => {
console.log(data);
var height = 900;
var width = 1000;
var margin = { top: 20, right: 15, bottom: 25, left: 25 };
width = width - margin.left - margin.right;
height = height - margin.top - margin.bottom;
// Create the svg to draw into
var svg = d3.select('body').append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// set the ranges
const xDomain = d3.extent(data.years.map(d => parseInt(d)));
console.log('xDomain', xDomain);
var x = d3.
scaleLinear()
.domain(xDomain)
.range([0, width]);
const yDomain = [0, d3.max(data.series.map(d => d.deaths))]; // TODO remove
console.log('yDomain', yDomain);
var y = d3
.scaleLinear()
.domain(yDomain)
.range([height, 0]);
var valueline = d3.line()
.x(function (d) { return x(d.year); })
.y(function (d) { return y(d.deaths); })
.curve(d3.curveMonotoneX);
// var xAxis_woy = d3.axisBottom(x).tickFormat(d3.timeFormat("Week %V"));
var xAxis_woy = d3.axisBottom(x)
// .ticks(11)
// .tickFormat(d3.timeFormat("%y-%b-%d"))
// .tickValues(() => data.map(d => d.year))
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis_woy);
// Add the Y Axis
svg.append("g").call(d3.axisLeft(y));
Object.keys(data.lines).forEach(key => {
const lineData = data.lines[key];
svg.append("path")
.data([lineData]) // Why the double array? no idea, no care
.attr("class", "line")
.attr("d", valueline);
svg.selectAll(".dot")
.data(lineData)
.enter()
.append("circle") // Uses the enter().append() method
.attr("class", "dot") // Assign a class for styling
.attr("cx", d => x(d.year))
.attr("cy", d => y(d.deaths))
.attr("r", 5);
svg.selectAll(".text")
.data(lineData)
.enter()
.append("text") // Uses the enter().append() method
.attr("class", "label") // Assign a class for styling
.attr("x", d => x(d.year))
.attr("y", d => y(d.deaths))
.attr("dy", "-5")
.text(function (d) {
return `${d.country} -${d.year} - ${d.deaths}`;
});
});
svg.append('text')
.attr('x', 10)
.attr('y', -5)
.text('Deaths');
}
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
const getData = async () => {
const data = await d3.csv("https://raw.githubusercontent.com/creilly8/projects/master/hiv_death_data0_27.csv");
console.log(data.slice(0, 1));
const lines = data.reduce((lines, d) => {
const country = d.Country;
if (!lines[country]) {
lines[country] = [];
}
lines[country].push({
country: d.Country,
year: d.Year,
deaths: parseInt(d.Deaths),
});
return lines;
}, {});
return {
lines,
series: data.map(d => ({
country: d.Country,
year: d.Year,
deaths: parseInt(d.Deaths),
})),
years: data.map(item => item.Year).filter(onlyUnique),
countries: Object.keys(lines),
};
}
getData()
.then(render);
<html>
<head>
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
body {
font-family: sans-serif;
color: #444;
}
.line {
fill: none;
stroke: #ffab00;
stroke-width: 3;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font-size: 10px;
}
</style>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment