Skip to content

Instantly share code, notes, and snippets.

@d3byex
Created November 25, 2015 03:39
Show Gist options
  • Save d3byex/ba05a6b171c6c77f5909 to your computer and use it in GitHub Desktop.
Save d3byex/ba05a6b171c6c77f5909 to your computer and use it in GitHub Desktop.
D3byEX 8.7: Focus + Context
<html>
<meta name="description" content="D3byEX 8.7" />
<meta charset="utf-8">
<style>
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var width = 960, height = 600;
var margins = { top: 10, left: 50, right: 50, bottom: 50, between: 50 };
var bottomGraphHeight = 50;
var topGraphHeight = height - (margins.top + margins.bottom + margins.between + bottomGraphHeight);
var graphWidths = width - margins.left - margins.right;
var svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height)
.style('font', '10px sans-serif');
svg.append('defs')
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('width', width)
.attr('height', height);
var focus = svg
.append('g')
.attr('transform', 'translate(' + margins.left + ',' + margins.top + ')');
var context = svg.append('g')
.attr('class', 'context')
.attr('transform', 'translate(' + margins.left + ',' +
(margins.top + topGraphHeight + margins.between) + ')');
var xScaleTop = d3.time.scale().range([0, graphWidths]),
xScaleBottom = d3.time.scale().range([0, graphWidths]),
yScaleTop = d3.scale.linear().range([topGraphHeight, 0]),
yScaleBottom = d3.scale.linear().range([bottomGraphHeight, 0]);
var xAxisTop = d3.svg.axis().scale(xScaleTop).orient('bottom'),
xAxisBottom = d3.svg.axis().scale(xScaleBottom).orient('bottom');
var yAxisTop = d3.svg.axis().scale(yScaleTop).orient('left');
var lineTop = d3.svg.line()
.x(function (d) { return xScaleTop(d.date); })
.y(function (d) { return yScaleTop(d.close); });
var lineBottom = d3.svg.line()
.x(function (d) { return xScaleBottom(d.date); })
.y(function (d) { return yScaleBottom(d.close); });
var brush = d3.svg.brush()
.x(xScaleBottom)
.on('brush', function brushed() {
xScaleTop.domain(brush.empty() ? xScaleBottom.domain() : brush.extent());
focus.select('.x.axis').call(xAxisTop);
});
d3.tsv('https://gist.githubusercontent.com/d3byex/b6b753b6ef178fdb06a2/raw/0c13e82b6b59c3ba195d7f47c33e3fe00cc3f56f/aapl.tsv', function (error, data) {
data.forEach(function (d) {
d.date = d3.time.format('%d-%b-%y').parse(d.date);
d.close = +d.close;
});
xScaleTop.domain(d3.extent(data, function (d) { return d.date; }));
yScaleTop.domain(d3.extent(data, function (d) { return d.close; }));
xScaleBottom.domain(d3.extent(data, function (d) { return d.date; }));
yScaleBottom.domain(d3.extent(data, function (d) { return d.close; }));
var topXAxisNodes = focus.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(' + 0 + ',' + (margins.top + topGraphHeight) + ')')
.call(xAxisTop);
styleAxisNodes(topXAxisNodes, 0);
focus.append('path')
.datum(data)
.attr('class', 'line')
.attr('d', lineTop);
var topYAxisNodes = focus.append('g')
.call(yAxisTop);
styleAxisNodes(topYAxisNodes);
context.append('path')
.datum(data)
.attr('class', 'line')
.attr('d', lineBottom);
var bottomXAxisNodes = context.append('g')
.attr('transform', 'translate(0,' + bottomGraphHeight + ')')
.call(xAxisBottom);
styleAxisNodes(bottomXAxisNodes, 0);
context.append('g')
.attr('class', 'x brush')
.call(brush)
.selectAll('rect')
.attr('y', -6)
.attr('height', bottomGraphHeight + 7);
context.selectAll('.extent')
.attr({
stroke: '#000',
'fill-opacity': 0.125,
'shape-rendering': 'crispEdges'
});
styleLines(svg);
});
function styleLines(svg) {
svg.selectAll('path.line')
.attr({
fill: 'none',
'stroke-width': 1.5,
stroke: 'steelblue',
'clip-path': 'url(#clip)'
});
}
function styleAxisNodes(axisNodes, strokeWidth) {
axisNodes.selectAll('.domain')
.attr({
fill: 'none',
'stroke-width': strokeWidth,
stroke: 'black'
});
axisNodes.selectAll('.tick line')
.attr({
fill: 'none',
'stroke-width': 1,
stroke: 'black'
});
}
</script>
</body>
</html>
@m-entrup
Copy link

Two more lines of code are necessary to make the code work. Maybe this is a result of a change in d3, as the latest version of d3 is used.

  1. Add an id to the path that represents lineTop [1]
  2. Update this path at the brush.on() method [2]

@cezar77
Copy link

cezar77 commented Nov 5, 2018

Adding id to the path makes it more obviuos, but just using the class .line can get us there too:

focus.select(".line").attr("d", lineTop);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment