block by wboykinm 10146562

10146562

Full Screen

index.html

<!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="//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>
  </head>
  <body style="margin:0; padding:0;">
  <script>run();</script>
  </body>
</html>

data.js

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
}];

main.js

function run() {
    var w = 750;
    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");
    var focus = svg.append("g");
    
    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": "#ccc",
        })
        .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"
        });
}

mask.js

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;
    
})();