This serves as an example of how to add a zoomable feature to a plot using a "brush". By selecting a window width in the bottom graph, the top graph is redrawn with that window extent. For this data this may not be all that interesting, but in principle it is an interesting technique.
forked from natemiller's block: Multiple Line Climate Plot with Zoom
forked from cse4qf's block: Multiple Line Climate Plot with Zoom
xxxxxxxxxx
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.y.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.line {
fill: none;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
//setting up margin space around
var margin = {top: 10, right: 10, bottom: 100, left: 40},
margin2 = {top: 430, right: 10, bottom: 20, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var color = d3.scale.category10(); //default color range
var parseDate = d3.time.format("%Y%m%d").parse;
//setting up actual size of graph within the margins
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
//referring to division of x axis
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
//thickness of graph lines x2
var brush = d3.svg.brush()
.x(x2)
.on("brush", brush);
var line = d3.svg.line()
.defined(function(d) { return !isNaN(d.bande); }) // valid temp value
.interpolate("cubic") //makes graph slightly smoother
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.bande); }); // x and y var for line
//must refer to graph underneath
var line2 = d3.svg.line()
.defined(function(d) { return !isNaN(d.bande); })
.interpolate("cubic")
.x(function(d) {return x2(d.date); })
.y(function(d) {return y2(d.bande); });
//appending body to svg element to apply transformations
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
//tooltips
const tooltip = d3.select('#tooltip')
const tooltipLine = svg.append('line')
//t tipBox;
let tipBox = svg.append('rect')
.attr('width', width)
.attr('height', height)
.attr('opacity', 0)
.on('mousemove', drawTooltip)
.on('mouseout', removeTooltip);
function removeTooltip() {
if (tooltip) tooltip.style('display', 'none');
if (tooltipLine) tooltipLine.attr('stroke', 'none');
}
function drawTooltip() {
const year = Math.floor((x.invert(d3.mouse(tipBox.node())[0]) + 5) / 10) * 10;
//}
/*parsing csv with javascript*/
// states.sort((a, b) => {
// return b.history.find(h => h.year == year).population - a.history.find(h => h.year == year).population;
//})
tooltipLine.attr('stroke', 'black')
.attr('x1', x(year)) //
//.attr('x2', x(d.date))
.attr('y1', 0)
.attr('y2', height);
/*
tooltip.html(date)
.style('display', 'block')
.style('left', d3.event.pageX + 20)
.style('top', d3.event.pageY - 20)
.selectAll()
//.data(states).enter()
.append('div')
.style('color', d => d.color)
.html(d => d.name + ': ' + d.history.find(h => h.year == year).population);
*/
//focus
var focus = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.csv("bandes - Sheet1.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var sources = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, bande: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([d3.min(sources, function(c) { return d3.min(c.values, function(v) { return v.bande; }); }),
d3.max(sources, function(c) { return d3.max(c.values, function(v) { return v.bande; }); }) ]);
x2.domain(x.domain());
y2.domain(y.domain());
var focuslineGroups = focus.selectAll("g")
.data(sources)
.enter().append("g");
var focuslines = focuslineGroups.append("path")
.attr("class","line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) {return color(d.name);})
.attr("clip-path", "url(#clip)");
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
var contextlineGroups = context.selectAll("g")
.data(sources)
.enter().append("g");
var contextLines = contextlineGroups.append("path")
.attr("class", "line")
.attr("d", function(d) { return line2(d.values); })
.style("stroke", function(d) {return color(d.name);})
.attr("clip-path", "url(#clip)");
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 6);
});
function brush() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.selectAll("path.line").attr("d", function(d) {return line(d.values)});
focus.select(".x.axis").call(xAxis);
focus.select(".y.axis").call(yAxis);
}
var body = d3.select('body')
body.append('input')
.attr('type','text')
.attr('name','textInput')
.attr('value','input text here')
//tooltip logic
/*
var tooltip = d3.select("body")
.append("div")
.style("postion", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background", "#000")
.text("simple tooltip")
d3.select("body")
.selectAll("div")
.data(data)
.enter().append("div")
.style("width", function(d) { return x(d) + "px"; })
*/
}
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js