Froked from mbostock's block: Brush Handles (now in d3v4).
See issue #14 and crossfilter.
| license: gpl-3.0 |
Froked from mbostock's block: Brush Handles (now in d3v4).
See issue #14 and crossfilter.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| circle { | |
| fill-opacity: 0.2; | |
| transition: fill-opacity 250ms linear; | |
| } | |
| circle.active { | |
| stroke: #f00; | |
| } | |
| </style> | |
| <svg width="960" height="500"></svg> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script> | |
| var data = d3.range(800).map(Math.random); | |
| var svg = d3.select("svg"), | |
| margin = {top: 194, right: 50, bottom: 214, left: 50}, | |
| width = +svg.attr("width") - margin.left - margin.right, | |
| height = +svg.attr("height") - margin.top - margin.bottom, | |
| g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
| var x = d3.scaleLinear().range([0, width]), | |
| y = d3.randomNormal(height / 2, height / 8); | |
| var brush = d3.brushX() | |
| .extent([[0, 0], [width, height]]) | |
| .on("start brush end", brushmoved); | |
| g.append("g") | |
| .attr("class", "axis axis--x") | |
| .attr("transform", "translate(0," + height + ")") | |
| .call(d3.axisBottom(x)); | |
| var circle = g.append("g") | |
| .attr("class", "circle") | |
| .selectAll("circle") | |
| .data(data) | |
| .enter().append("circle") | |
| .attr("transform", function(d) { return "translate(" + x(d) + "," + y() + ")"; }) | |
| .attr("r", 3.5); | |
| var gBrush = g.append("g") | |
| .attr("class", "brush") | |
| .call(brush); | |
| // style brush resize handle | |
| // https://github.com/crossfilter/crossfilter/blob/gh-pages/index.html#L466 | |
| var brushResizePath = function(d) { | |
| var e = +(d.type == "e"), | |
| x = e ? 1 : -1, | |
| y = height / 2; | |
| return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8); | |
| } | |
| var handle = gBrush.selectAll(".handle--custom") | |
| .data([{type: "w"}, {type: "e"}]) | |
| .enter().append("path") | |
| .attr("class", "handle--custom") | |
| .attr("stroke", "#000") | |
| .attr("cursor", "ew-resize") | |
| .attr("d", brushResizePath); | |
| gBrush.call(brush.move, [0.3, 0.5].map(x)); | |
| function brushmoved() { | |
| var s = d3.event.selection; | |
| if (s == null) { | |
| handle.attr("display", "none"); | |
| circle.classed("active", false); | |
| } else { | |
| var sx = s.map(x.invert); | |
| circle.classed("active", function(d) { return sx[0] <= d && d <= sx[1]; }); | |
| handle.attr("display", null).attr("transform", function(d, i) { return "translate(" + [ s[i], - height / 4] + ")"; }); | |
| } | |
| } | |
| </script> |