block by fil 2d43867ba1f36a05459c7113c7f6f98a

Brush Handles d3v4 II

Full Screen

Froked from mbostock‘s block: Brush Handles (now in d3v4).

See issue #14 and crossfilter.

index.html

<!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>