block by micahstubbs 4fc5b8bdb27bde8a321ba410152a31ae

ES2015 Fisheye Grid

Full Screen

an ES2015 fork of the bl.ock Fisheye Grid from @mbostock


Original README.md

The above grid shows the effect of fisheye distortion. Move the mouse to change the focal point.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.background {
  fill: none;
  pointer-events: all;
}

path {
  fill: none;
  stroke: #333;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="https://npmcdn.com/babel-core@5.8.34/browser.min.js"></script>
<script src="fisheye.js"></script>
<script lang='babel' type='text/babel'>

  const width = 960;
  const height = 500;
  const xStepsBig = d3.range(10, width, 20);
  const yStepsBig = d3.range(10, height, 20);
  const xStepsSmall = d3.range(0, width + 6, 6);
  const yStepsSmall = d3.range(0, height + 6, 6);

  const fisheye = d3.fisheye();

  const line = d3.svg.line();

  const svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height)
    .append('g')
      .attr('transform', 'translate(-.5,-.5)');

  svg.append('rect')
    .attr('class', 'background')
    .attr('width', width)
    .attr('height', height);

  svg.selectAll('.x')
    .data(xStepsBig)
    .enter().append('path')
      .attr('class', 'x')
      .datum(x => yStepsSmall.map(y => [x, y]));

  svg.selectAll('.y')
    .data(yStepsBig)
    .enter().append('path')
      .attr('class', 'y')
      .datum(y => xStepsSmall.map(x => [x, y]));

  const path = svg.selectAll('path')
    .attr('d', line);

  svg.on('mousemove', function () {
    fisheye.center(d3.mouse(this));
    path.attr('d', d => line(d.map(fisheye)));
  });

</script>

fisheye.js

(function() {
  d3.fisheye = function() {
    var radius = 200,
        power = 2,
        k0,
        k1,
        center = [0, 0];

    function fisheye(d) {
      var dx = d[0] - center[0],
          dy = d[1] - center[1],
          dd = Math.sqrt(dx * dx + dy * dy);
      if (dd >= radius) return d;
      var k = k0 * (1 - Math.exp(-dd * k1)) / dd * .75 + .25;
      return [center[0] + dx * k, center[1] + dy * k];
    }

    function rescale() {
      k0 = Math.exp(power);
      k0 = k0 / (k0 - 1) * radius;
      k1 = power / radius;
      return fisheye;
    }

    fisheye.radius = function(_) {
      if (!arguments.length) return radius;
      radius = +_;
      return rescale();
    };

    fisheye.power = function(_) {
      if (!arguments.length) return power;
      power = +_;
      return rescale();
    };

    fisheye.center = function(_) {
      if (!arguments.length) return center;
      center = _;
      return fisheye;
    };

    return rescale();
  };
})();