Skip to content

Instantly share code, notes, and snippets.

@jisaacks
Last active August 29, 2015 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jisaacks/94d2c7e2e2bd7ed41401 to your computer and use it in GitHub Desktop.
Save jisaacks/94d2c7e2e2bd7ed41401 to your computer and use it in GitHub Desktop.
D3 Brush Mask
var data = [{
date: new Date("Jan 01, 2013"),
data: 12
},{
date: new Date("Jan 02, 2013"),
data: 17
},{
date: new Date("Jan 03, 2013"),
data: 5
},{
date: new Date("Jan 04, 2013"),
data: 18
},{
date: new Date("Jan 05, 2013"),
data: 20
},{
date: new Date("Jan 06, 2013"),
data: 4
},{
date: new Date("Jan 07, 2013"),
data: 9
},{
date: new Date("Jan 08, 2013"),
data: 12
},{
date: new Date("Jan 09, 2013"),
data: 15
},{
date: new Date("Jan 10, 2013"),
data: 2
},{
date: new Date("Jan 11, 2013"),
data: 19
},{
date: new Date("Jan 12, 2013"),
data: 3
},{
date: new Date("Jan 13, 2013"),
data: 7
},{
date: new Date("Jan 14, 2013"),
data: 14
},{
date: new Date("Jan 15, 2013"),
data: 8
},{
date: new Date("Jan 16, 2013"),
data: 17
},{
date: new Date("Jan 17, 2013"),
data: 12
}];
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>D3 Advanced Brush Styling - Part 5</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js"></script>
<script type="text/javascript" src="data.js"></script>
<script type="text/javascript" src="mask.js"></script>
<script type="text/javascript" src="main.js"></script>
<style>
text {
stroke: none;
fill: #84a873;
font: 10px sans-serif;
}
</style>
</head>
<body style="margin:0; padding:0;text-align: center;padding-top: 200px;">
<script>run();</script>
</body>
</html>
function run() {
var w = 700;
var h = 100;
var x = d3.time.scale()
.range([0,w])
.domain([data[0].date, data[data.length-1].date]);
var y = d3.scale.linear()
.range([h,0])
.domain([0,20]);
var svg = d3.select("body").append("svg").style({width: "701px"});
var focus = svg.append("g");
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.style({
fill: "none",
stroke: "#000",
"shape-rendering": "crispEdges"
})
.call(d3.svg.axis().scale(x).orient("bottom"));
var line = d3.svg.line()
.interpolate("basis")
.x(function(d){ return x(d.date);})
.y(function(d){ return y(d.data);});
var area = d3.svg.area()
.interpolate("basis")
.x(function(d){ return x(d.date);})
.y1(function(d){ return y(d.data);})
.y0(function(d){ return y(0);});
var brush = d3.svg.brush().x(x);
focus.append("path")
.attr("class","area")
.style({
"fill": "#C4E8B3",
})
.datum(data)
.attr("d",area);
var mask = new SVGMask(focus)
.x(x)
.y(y)
.style("fill","#fff")
.reveal([data[7].date,data[11].date])
brush.on("brush",function(){
var ext = brush.extent();
mask.reveal(ext);
leftHandle.attr("x",x(ext[0])-5);
rightHandle.attr("x",x(ext[1])-7);
});
focus.append("path")
.attr("class","line")
.style({
"fill": "none",
"stroke": "#000",
"stroke-width": "2"
})
.datum(data)
.attr("d",line);
var leftHandle = focus.append("image")
.attr("width", 15)
.attr("height",100)
.attr("x",x(data[7].date)-5)
.attr("xlink:href",'left-handle.png');
var rightHandle = focus.append("image")
.attr("width", 15)
.attr("height",100)
.attr("x",x(data[11].date)-7)
.attr("xlink:href",'right-handle.png');
focus.append("g")
.attr("class","x brush")
.call(brush.extent([data[7].date,data[11].date]))
.selectAll("rect")
.attr("height",h)
.style({
"fill": "none"
});
}
var SVGMask = (function() {
function SVGMask(focus) {
this.focus = focus;
this.mask = this.focus.append("g").attr("class","mask");
this.left = this.mask.append("polygon");
this.right = this.mask.append("polygon");
this._x = null;
this._y = null;
}
SVGMask.prototype.style = function(prop, val) {
this.left.style(prop, val);
this.right.style(prop, val);
return this;
}
SVGMask.prototype.x = function(f) {
if (f == null) {
return this._x;
}
this._x = f;
return this;
};
SVGMask.prototype.y = function(f) {
if (f == null) {
return this._y;
}
this._y = f;
return this;
};
SVGMask.prototype.redraw = function() {
var lp, maxX, maxY, minX, minY, rp, xDomain, yDomain;
yDomain = this._y.domain();
minY = yDomain[0];
maxY = yDomain[1];
xDomain = this._x.domain();
minX = xDomain[0];
maxX = xDomain[1];
lp = {
l: this._x(minX),
t: this._y(minY),
r: this._x(this.from),
b: this._y(maxY)
};
rp = {
l: this._x(this.to),
t: this._y(minY),
r: this._x(maxX),
b: this._y(maxY)
};
this.left.attr("points", "" + lp.l + "," + lp.t + " " + lp.r + "," + lp.t + " " + lp.r + "," + lp.b + " " + lp.l + "," + lp.b);
this.right.attr("points", "" + rp.l + "," + rp.t + " " + rp.r + "," + rp.t + " " + rp.r + "," + rp.b + " " + rp.l + "," + rp.b);
return this;
};
SVGMask.prototype.reveal = function(extent) {
this.from = extent[0];
this.to = extent[1];
this.redraw();
return this;
};
return SVGMask;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment