Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.hidden {
opacity: 0.1
}
.latest {
opacity: 1;
}
.shown {
opacity: 1;
}
</style>
</head>
<body>
<script>
const width = 500;
const height = width;
const margin = {"top": 50,"bottom": 50,"left": 50,"right": 50};
let xScale = d3.scaleLinear()
.range([0,width])
.domain([0,100]);
let yScale = d3.scaleLinear()
.range([height,0])
.domain([0,100])
let line = d3.line()
.x(function(d) { return xScale(d.provision); })
.y(function(d) { return yScale(d.girls); });
const radius = 5;
let svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
let g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top +")" );
d3.csv("data.csv", convertTextToNumbers, function (error, data) {
if (error) { throw error; };
let nestedData = d3.nest()
.key(function(d){ return d.state; })
.entries(data);
nestedData.forEach(function(d, i){
let stateName = d.key;
let stateData = d.values;
let dataLength = stateData.length;
let stateG = g.append("g")
.attr("id", stateName);
stateG.append("path")
.datum(stateData)
.attr("d", line)
.style("stroke", "black")
.style("fill", "none")
.style("opacity", 0.1)
stateG.selectAll("circle")
.data(stateData)
.enter()
.append("circle")
.attr("cx", function(d){ return xScale(d.provision); })
.attr("cy", function(d){ return yScale(d.girls); })
.attr("r", radius)
.style("fill", "red")
.attr("class", function(d, i){
return i == (dataLength-1) ? "latest" : "hidden";
})
});
})
function convertTextToNumbers(d) {
d.year = +d.year;
d.girls = +d.girls;
d.provision = +d.provision;
return d;
};
</script>
</body>
https://d3js.org/d3.v4.min.js