block by syntagmatic 748b02519c942c5291f302e060315ad6

Hexbins

Full Screen

A demonstration of the d3-hexbin plugin for D3 4.0.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>
html, body {
  background: #111;
}

.hexagons {
  fill: none;
  stroke: #000;
}

</style>
<body>
<script src="//d3js.org/d3.v4.js"></script>
<script src="d3-hexbin.js"></script>
<script>

var margin = {top: 12, right: 12, bottom: 12, left: 12},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var randomX = d3.randomBates(2),
    randomY = d3.randomBates(2),
    points = d3.range(2000).map(function() { return [width * randomX(), height * randomY()]; });

var hexbin = d3.hexbin()
    .extent([[-margin.left, -margin.top], [width + margin.right, height + margin.bottom]])
    .radius(10);

var bins = hexbin(points);

var color = d3.scaleSequential(d3.interpolatePlasma)
    .domain([0, 10]);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("g")
    .attr("class", "hexagons")
  .selectAll("path")
    .data(bins)
  .enter().append("path")
    .attr("d", hexbin.hexagon())
    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
    .style("fill", function(d) { return color(d.length); });


/* Messing with bl.ocks.org styles */
if(window.parent && window.parent.document) {
  window.parent.document.body.style.backgroundColor = "#111"
  window.parent.document.body.style.color = "#fff"
  d3.selectAll(window.parent.document.getElementsByTagName("a")).style("color", "rgb(244, 136, 73)");
}
</script>

d3-hexbin.js

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (factory((global.d3 = global.d3 || {})));
}(this, function (exports) { 'use strict';

  var version = "0.2.1";

  var thirdPi = Math.PI / 3;
  var angles = [0, thirdPi, 2 * thirdPi, 3 * thirdPi, 4 * thirdPi, 5 * thirdPi];
  function pointX(d) {
    return d[0];
  }

  function pointY(d) {
    return d[1];
  }

  function hexbin() {
    var x0 = 0,
        y0 = 0,
        x1 = 1,
        y1 = 1,
        x = pointX,
        y = pointY,
        r,
        dx,
        dy;

    function hexbin(points) {
      var binsById = {}, bins = [], i, n = points.length;

      for (i = 0; i < n; ++i) {
        if (isNaN(px = +x.call(null, point = points[i], i, points))
            || isNaN(py = +y.call(null, point, i, points))) continue;

        var point,
            px,
            py,
            pj = Math.round(py = py / dy),
            pi = Math.round(px = px / dx - (pj & 1) / 2),
            py1 = py - pj;

        if (Math.abs(py1) * 3 > 1) {
          var px1 = px - pi,
              pi2 = pi + (px < pi ? -1 : 1) / 2,
              pj2 = pj + (py < pj ? -1 : 1),
              px2 = px - pi2,
              py2 = py - pj2;
          if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) pi = pi2 + (pj & 1 ? 1 : -1) / 2, pj = pj2;
        }

        var id = pi + "-" + pj, bin = binsById[id];
        if (bin) bin.push(point);
        else {
          bins.push(bin = binsById[id] = [point]);
          bin.x = (pi + (pj & 1) / 2) * dx;
          bin.y = pj * dy;
        }
      }

      return bins;
    }

    function hexagon(radius) {
      var x0 = 0, y0 = 0;
      return angles.map(function(angle) {
        var x1 = Math.sin(angle) * radius,
            y1 = -Math.cos(angle) * radius,
            dx = x1 - x0,
            dy = y1 - y0;
        x0 = x1, y0 = y1;
        return [dx, dy];
      });
    }

    hexbin.hexagon = function(radius) {
      return "m" + hexagon(radius == null ? r : +radius).join("l") + "z";
    };

    hexbin.centers = function() {
      var centers = [],
          j = Math.round(y0 / dy),
          i = Math.round(x0 / dx);
      for (var y = j * dy; y < y1 + r; y += dy, ++j) {
        for (var x = i * dx + (j & 1) * dx / 2; x < x1 + dx / 2; x += dx) {
          centers.push([x, y]);
        }
      }
      return centers;
    };

    hexbin.mesh = function() {
      var fragment = hexagon(r).slice(0, 4).join("l");
      return hexbin.centers().map(function(p) { return "M" + p + "m" + fragment; }).join("");
    };

    hexbin.x = function(_) {
      return arguments.length ? (x = _, hexbin) : x;
    };

    hexbin.y = function(_) {
      return arguments.length ? (y = _, hexbin) : y;
    };

    hexbin.radius = function(_) {
      return arguments.length ? (r = +_, dx = r * 2 * Math.sin(thirdPi), dy = r * 1.5, hexbin) : r;
    };

    hexbin.extent = function(_) {
      return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], hexbin) : [[x0, y0], [x1, y1]];
    };

    return hexbin.radius(1);
  }

  exports.version = version;
  exports.hexbin = hexbin;

  Object.defineProperty(exports, '__esModule', { value: true });

}));