This is a derivative of the simple d3.js graph in v4 used as an example in the book D3 Tips and Tricks v4. The stock data was sourced from Mike Bostock's small multiples example.
It is the fourth graph in a series that is building a multi-line graph that incorperates an automatically developed legend and a system that can toggle the lines off and on as desired.
This version is demonstrating the ability to toggle the lines off and on by clicking on the appropriate legend text.
The graph should be taken in context with the text of the book which can be downloaded for free from Leanpub.
forked from d3noob's block: Sucre Crops Linechart
xxxxxxxxxx
<head>
<link href="https://fonts.googleapis.com/css?family=Oxygen" rel="stylesheet">
</head>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: black;
stroke-width: 2;
shape-rendering: crispEdges;
}
.axisLabels
{
font-family: 'Oxygen', sans-serif;
font-size: 15px;
}
.chartTitle
{
font-size: 17px;
font-family: 'Oxygen';
}
</style>
<body>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 20, right: 200, bottom: 50, left: 80},
width = 1024 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
// Set the ranges
var x = d3.scaleLinear().range([0, width]),
y = d3.scaleLinear().range([height, margin.top]);
// Define the line
var priceline = d3.line()
.x(function(d) { return x(d.año); })
.y(function(d) { return y(d.utilidad); });
// Adds the svg canvas
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 + ")");
// Get the data
d3.csv("formatted_data.csv", function(error, data) {
//This is for assuring that the data is correctly interpreted by JavaScript
data.forEach(function(d) {
d.año = parseInt(d.año);
d.utilidad = parseInt(d.utilidad);
d.rentabilidad = parseInt(d.rentabilidad);
});
//Obtaining maximum, minimum values, and number of years
var yMaxScale = d3.max(data, function(d) { return d.utilidad; }),
yMinScale = d3.min(data, function(d) { return d.utilidad; }),
xMinScale = d3.min(data, function(d) { return d.año; }),
xMaxScale = d3.max(data, function(d) { return d.año; }),
uniqueYears = d3.map(data, function(d){return d.año}).keys().length;
// Scale with the range of the data
x.domain([xMinScale, xMaxScale]);
y.domain([yMinScale, yMaxScale]);
// Nest the entries by symbol
var dataNest = d3.nest()
.key(function(d) {return d.cultivo;})
.entries(data);
// set the colour scale
var color = d3.scaleOrdinal(d3.schemeCategory20);
var legendSpace = 20; // spacing for the legend in arbitrary units
// Loop through each symbol / key
dataNest.forEach(function(d,i) {
svg.append("path")
.attr("class", "line")
.style("stroke", "#ddd")
.attr("id", 'tag'+d.key.replace(/\s+/g, '')) // assign an ID
.attr("d", priceline(d.values))
.attr("opacity", 0.2)
.on("click", function(){
// Determine if current line is visible
var active = d.active ? false : true,
newColor = active ? color(d.key) : "#ddd";
newOpacity = active ? 1 : 0.2;
// Hide or show the elements upon clicking the key on the right
d3.select(this)
.transition().duration(300)
.style("stroke", newColor)
.style("opacity", newOpacity);
//Change the behaviour of the text
d3.select(".legend"+d.key.replace(/\s+/g, ''))
.style("fill", newColor);
// Update whether or not the elements are active
d.active = active;
}) ;
// Add the Legend
svg.append("text")
.attr("x", width + (legendSpace) ) // space legend
.attr("y", height - (i*20))
.attr("font-weight", "bold")
.attr("class", 'legend'+d.key.replace(/\s+/g, '')) // style the legend
.style("fill", "#ddd")
.on("click", function(){
// Determine if current line is visible
var active = d.active ? false : true,
newColor = active ? color(d.key) : "#ddd";
newOpacity = active ? 1 : 0.2;
// Hide or show the elements upon clicking the key on the right
d3.select("#tag"+d.key.replace(/\s+/g, ''))
.transition().duration(300)
.style("stroke", newColor)
.style("opacity", newOpacity);
//Change the behaviour of the text
d3.select(this)
.transition().duration(300)
.style("fill", newColor);
// Update whether or not the elements are active
d.active = active;
})
.text(d.key);
});
var axisLabelProperties = {yOffset: -60, yHeight:-(height/1.5), xLength: width/2, xOffset: height + margin.bottom};
// Add the X Axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(uniqueYears).tickFormat(d3.format("d")));
//Add the X axis label
svg.append("text")
.text("Año")
.attr("class", "axisLabels")
.attr("x",axisLabelProperties.xLength)
.attr("y",axisLabelProperties.xOffset);
// Add the Y Axis
svg.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y));
//Add the Y Axis label
svg.append("text")
.text("Utilidad (Millones de pesos)")
.attr("class", "axisLabels")
.attr("transform", "rotate(-90)")
.attr("x", axisLabelProperties.yHeight)
.attr("y", axisLabelProperties.yOffset);
//Add the chart title
svg.append("text")
.text("Rentabilidad de los productos agrícolas de Sucre en el periodo 2011 - 2015")
.attr("x", width/7)
.attr("y", 0)
.attr("class", "chartTitle");
});
</script>
</body>
https://d3js.org/d3.v4.min.js