The above grid shows the effect of fisheye distortion. Move the mouse to change the focal point.
forked from mbostock's block: Fisheye Grid
| license: gpl-3.0 |
The above grid shows the effect of fisheye distortion. Move the mouse to change the focal point.
forked from mbostock's block: Fisheye Grid
| (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(); | |
| }; | |
| })(); |
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| .background { | |
| fill: none; | |
| pointer-events: all; | |
| } | |
| path { | |
| fill: none; | |
| stroke: #333; | |
| } | |
| </style> | |
| <body> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script src="fisheye.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 500, | |
| xStepsBig = d3.range(10, width, 20), | |
| yStepsBig = d3.range(10, height, 20), | |
| xStepsSmall = d3.range(0, width + 6, 6), | |
| yStepsSmall = d3.range(0, height + 6, 6); | |
| var fisheye = d3.fisheye(); | |
| var line = d3.line(); | |
| var 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(function(x) { return yStepsSmall.map(function(y) { return [x, y]; }); }); | |
| svg.selectAll(".y") | |
| .data(yStepsBig) | |
| .enter().append("path") | |
| .attr("class", "y") | |
| .datum(function(y) { return xStepsSmall.map(function(x) { return [x, y]; }); }); | |
| var path = svg.selectAll("path") | |
| .attr("d", line); | |
| svg.on("mousemove", function() { | |
| fisheye.center(d3.mouse(this)); | |
| path.attr("d", function(d) { return line(d.map(fisheye)); }); | |
| }); | |
| </script> |