This line chart is constructed from a TSV file storing the daily average temperatures of New York, San Francisco and Austin over the last year. The chart employs conventional margins and a number of D3 features:
forked from mbostock's block: Multi-Series Line Chart
forked from djokicx's block: Multi-Series Line Chart
forked from djokicx's block: Multi-Series Line Chart
forked from djokicx's block: Multi-Series Line Chart
xxxxxxxxxx
<meta charset="utf-8">
<style>
/* change the text color for the lines, move the text and the x to the other side */
body {
font: 10px sans-serif;
fill: #a9a9a9;
}
.city { /* the color of the city label */
fill: gray;
}
svg { /* vector image format for two-dimensional graphics with support for interactivity and animation
A plane in which the data is done
*/
background-color: whitesmoke;
}
.axis path,
.axis line {
fill: none;
stroke: darkgrey;
shape-rendering: crispEdges;
}
.x.axis path {
fill:none;
stroke: darkgrey;
display: inline;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
/* Assign margin variables - top; right; bottom & left */
var margin = {top: 20, right: 80, bottom: 30, left: 40},
/* Width of the visualization area */
width = 960 - margin.left - margin.right,
/* Height of the visualization area */
height = 500 - margin.top - margin.bottom;
/*Javascript doesn't automatically recognize the values in the CSV file as dates, just reading them in as strings. d3's time functions make it pretty easy to convert them to datetime objects */
var parseDate = d3.time.format("%Y%m%d").parse;
/*Constructs a new time scale with the default domain and range; the ticks and tick format are configured for local time.*/
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
/*Constructs a new ordinal scale with a range of ten categorical colors*/
var color = d3.scale.category10();
/*Create a new default axis.
The axis component is designed to work with D3’s quantitative, time and ordinal scales.
*/
/* Every axis needs to be told on what scale to operate*/
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom"); // Specifies where the labels should appear relative to axis itself
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
// TODO FIGURE THIS OUT (?)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.temperature); });
/*D3 selects the body and appends an svg to it */
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right) // the width of an entire svg
.attr("height", height + margin.top + margin.bottom) // the width of an entire svg
.append("g") // changes the selection
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("data.tsv", function(error, data) {
if (error) throw error;
// Returns an array containing the property names of the specified object (an associative array). The order of the returned array is undefined - d3.keys
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
//Create a new array with only the elements for which a predicate is true. .filter
//forEach() executes the provided callback once for each element present in the array in ascending order
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, temperature: +d[name]};
})
};
});
// Returns the minimum and maximum value in the given array using natural order. This is equivalent to calling d3.min and d3.max simultaneously.
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temp (ºF)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text") //appending a different element
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Month");
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
.attr("class", "city");
city.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
city.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
</script>
https://d3js.org/d3.v3.min.js