an ES2015 fork of the bl.ock Fisheye Grid from @mbostock
The above grid shows the effect of fisheye distortion. Move the mouse to change the focal point.
license: gpl-3.0 | |
border: none |
an ES2015 fork of the bl.ock Fisheye Grid from @mbostock
The above grid shows the effect of fisheye distortion. Move the mouse to change the focal point.
(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="//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> |