Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active August 12, 2019 01:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mbostock/3828981 to your computer and use it in GitHub Desktop.
Save mbostock/3828981 to your computer and use it in GitHub Desktop.
van Wijk Smooth Zooming
license: gpl-3.0
redirect: https://observablehq.com/@d3/smooth-zooming
!function(){d3.hexbin=function(){function u(n){var r={};return n.forEach(function(n,t){var a=s.call(u,n,t)/o,e=Math.round(a),c=h.call(u,n,t)/i-(1&e?.5:0),f=Math.round(c),l=a-e;if(3*Math.abs(l)>1){var v=c-f,g=f+(f>c?-1:1)/2,m=e+(e>a?-1:1),M=c-g,d=a-m;v*v+l*l>M*M+d*d&&(f=g+(1&e?1:-1)/2,e=m)}var j=f+"-"+e,p=r[j];p?p.push(n):(p=r[j]=[n],p.i=f,p.j=e,p.x=(f+(1&e?.5:0))*i,p.y=e*o)}),d3.values(r)}function a(r){var t=0,u=0;return n.map(function(n){var a=Math.sin(n)*r,e=-Math.cos(n)*r,i=a-t,o=e-u;return t=a,u=e,[i,o]})}var e,i,o,c=1,f=1,h=r,s=t;return u.x=function(n){return arguments.length?(h=n,u):h},u.y=function(n){return arguments.length?(s=n,u):s},u.hexagon=function(n){return arguments.length<1&&(n=e),"m"+a(n).join("l")+"z"},u.centers=function(){for(var n=[],r=0,t=!1,u=0;f+e>r;r+=o,t=!t,++u)for(var a=t?i/2:0,h=0;c+i/2>a;a+=i,++h){var s=[a,r];s.i=h,s.j=u,n.push(s)}return n},u.mesh=function(){var n=a(e).slice(0,4).join("l");return u.centers().map(function(r){return"M"+r+"m"+n}).join("")},u.size=function(n){return arguments.length?(c=+n[0],f=+n[1],u):[c,f]},u.radius=function(n){return arguments.length?(e=+n,i=2*e*Math.sin(Math.PI/3),o=1.5*e,u):e},u.radius(1)};var n=d3.range(0,2*Math.PI,Math.PI/3),r=function(n){return n[0]},t=function(n){return n[1]}}();
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.mesh {
fill: none;
stroke: #000;
stroke-width: .25px;
}
.start {
fill: none;
stroke: brown;
}
.end {
fill: none;
stroke: steelblue;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="d3.hexbin.min.js"></script>
<script>
var width = 960,
height = 500,
radius = 10;
var p0 = [250, 200, 60],
p1 = [560, 300, 120];
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.call(transition, p0, p1);
svg.append("path")
.attr("class", "mesh")
.attr("d", d3.hexbin()
.size([width, height])
.radius(radius)
.mesh);
svg.selectAll("circle")
.data([p0, p1])
.enter().append("circle")
.attr("class", function(d, i) { return i ? "end" : "start"; })
.attr("cx", function(d) { return d[0]; })
.attr("cy", function(d) { return d[1]; })
.attr("r", function(d) { return d[2] / 2 - .5; });
function transition(svg, start, end) {
var center = [width / 2, height / 2],
i = d3.interpolateZoom(start, end);
svg
.attr("transform", transform(start))
.transition()
.delay(250)
.duration(i.duration * 2)
.attrTween("transform", function() { return function(t) { return transform(i(t)); }; })
.each("end", function() { d3.select(this).call(transition, end, start); });
function transform(p) {
var k = height / p[2];
return "translate(" + (center[0] - p[0] * k) + "," + (center[1] - p[1] * k) + ")scale(" + k + ")";
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment