This variation of a line chart demonstrates a sequence of chained transitions. Clicking on the radio buttons changes the displayed metric. First, the line transitions to the new values. Then, the axes rescale to fit the new data.
forked from mbostock's block: Chained Transitions
forked from SpaceActuary's block: Chained Transitions
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: auto;
position: relative;
width: 960px;
}
text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
</style>
<form>
<label><input type="radio" name="city" value="New York" checked> New York</label>
<label><input type="radio" name="city" value="San Francisco"> San Francisco</label>
</form>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var city = "New York",
parseDate = d3.timeParse("%Y%m%d");
var x = d3.scaleTime()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom()
.scale(x);
var yAxis = d3.axisLeft()
.scale(y);
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d[city]); });
var color = d3.scaleOrdinal(d3.schemeCategory10 )
.domain(["New York", "San Francisco"])
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 + ")");
d3.tsv("data.tsv", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.date = parseDate(d.date);
d["New York"] = +d["New York"];
d["San Francisco"] = +d["San Francisco"];
});
x.domain([data[0].date, data[data.length - 1].date]);
y.domain(d3.extent(data, function(d) { return d[city]; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperature (ºF)");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
svg.append("text")
.datum(data[data.length - 1])
.attr("class", "label")
.attr("transform", transform)
.attr("x", 3)
.attr("dy", ".35em")
.text(city);
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"San Francisco\"]").property("checked", true).each(change);
}, 2000);
console.clear()
function change() {
clearTimeout(timeout);
var oldCity = city,
newCity = this.value;
// First transition the y-axis to the combined extent
y.domain(d3.extent(d3.merge([
d3.extent(data, function(d) { return d[oldCity]; }),
d3.extent(data, function(d) { return d[newCity]; })
])));
console.log(city + " -(0)-> " + newCity, y.domain())
var t0 = svg.transition().duration(750);
t0.selectAll(".line").attr("d", line);
t0.selectAll(".label").attr("transform", transform);
t0.selectAll(".y.axis").call(yAxis);
city = this.value;
console.log(oldCity + " -(1)-> " + newCity, y.domain())
// Then transition the line & label to the new city.
var t1 = t0.transition();
t1.selectAll(".line").attr("d", line).style("stroke", color(newCity));
t1.selectAll(".label").attr("transform", transform).text(newCity);
// Then transition the y-axis to the new city's range.
y.domain(d3.extent(data, function(d) { return d[newCity]; }));
console.log(oldCity + " -(2)-> " + newCity, y.domain())
var t2 = t1.transition();
t2.selectAll(".line").attr("d", line);
t2.selectAll(".label").attr("transform", transform);
t2.selectAll(".y.axis").call(yAxis);
}
function transform(d) {
return "translate(" + x(d.date) + "," + y(d[city]) + ")";
}
});
</script>
https://d3js.org/d3.v4.min.js