Move the mouse to change the focal point of the fisheye. The left side of the grid shows fisheye with smoothing which is implemented in this plugin https://github.com/duaneatat/d3-fisheye and described here https://observablehq.com/@duaneatat/smoothed-fisheye - The right side is the sarkar-brown fisheye effect which has the abrupt discontinuity at the edge of the fisheye effect.
xxxxxxxxxx
<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="fisheye-deprecated.js"></script>
<script src="d3-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 + 4, 4),
yStepsSmall = d3.range(0, height + 4, 4);
const points = [];
for (var i = 0; i < 100; i++) {
points.push({ x: Math.random() * width, y: Math.random() * height });
}
var fisheye = d3Fisheye
.radial()
.radius(120)
.distortion(5)
.smoothingRatio(0.5);
var fisheyeDeprecated = d3fisheyeDeprecated
.circular()
.radius(100)
.distortion(5);
var line = d3.svg.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);
const pointsSelection = svg
.selectAll('dot')
.data(points)
.enter()
.append('circle')
.attr('r', 5)
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
});
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() {
const mouse = d3.mouse(this);
fisheye.focus(mouse);
fisheyeDeprecated.focus(mouse);
pointsSelection
.each(d => {
if (mouse[0] > 500) {
d.fisheye = fisheyeDeprecated(d);
} else {
d.fisheye = fisheye([d.x, d.y]);
}
})
.attr('cx', function(d) {
if (mouse[0] > 500) {
return d.fisheye.x;
} else {
return d.fisheye[0];
}
})
.attr('cy', function(d) {
if (mouse[0] > 500) {
return d.fisheye.y;
} else {
return d.fisheye[1];
}
});
path.attr('d', function(d) {
return line(
d.map(tuple => {
if (mouse[0] > 500) {
const point = fisheyeDeprecated({ x: tuple[0], y: tuple[1] });
return [point.x, point.y];
} else {
return fisheye(tuple);
}
})
);
});
});
</script>
</body>
https://d3js.org/d3.v3.min.js