Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active January 3, 2024 15:40
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mbostock/1020902 to your computer and use it in GitHub Desktop.
Save mbostock/1020902 to your computer and use it in GitHub Desktop.
Superformula Tweening
license: gpl-3.0

Christophe Viau implemented a new shape type as a D3 plugin based on superformulas. One nice property of these shapes is that you can easily tween between two shapes by simply interpolating the control points. Click on the blue shapes to try it!

(function(){function n(n,a,r){for(var e,s,o,m=-1,u=2*Math.PI/a,b=0,h=[];++m<a;)e=n.m*(m*u-Math.PI)/4,e=Math.pow(Math.abs(Math.pow(Math.abs(Math.cos(e)/n.a),n.n2)+Math.pow(Math.abs(Math.sin(e)/n.b),n.n3)),-1/n.n1),e>b&&(b=e),h.push(e);for(b=r*Math.SQRT1_2/b,m=-1;++m<a;)s=(e=h[m]*b)*Math.cos(m*u),o=e*Math.sin(m*u),h[m]=[Math.abs(s)<1e-6?0:s,Math.abs(o)<1e-6?0:o];return t(h)+"Z"}var a=d3.svg.symbol(),t=d3.svg.line();d3.superformula=function(){function t(a,t){var u,b=r[e.call(this,a,t)];for(u in m)b[u]=m[u].call(this,a,t);return n(b,o.call(this,a,t),Math.sqrt(s.call(this,a,t)))}var e=a.type(),s=a.size(),o=s,m={};return t.type=function(n){return arguments.length?(e=d3.functor(n),t):e},t.param=function(n,a){return arguments.length<2?m[n]:(m[n]=d3.functor(a),t)},t.size=function(n){return arguments.length?(s=d3.functor(n),t):s},t.segments=function(n){return arguments.length?(o=d3.functor(n),t):o},t};var r={asterisk:{m:12,n1:.3,n2:0,n3:10,a:1,b:1},bean:{m:2,n1:1,n2:4,n3:8,a:1,b:1},butterfly:{m:3,n1:1,n2:6,n3:2,a:.6,b:1},circle:{m:4,n1:2,n2:2,n3:2,a:1,b:1},clover:{m:6,n1:.3,n2:0,n3:10,a:1,b:1},cloverFour:{m:8,n1:10,n2:-1,n3:-8,a:1,b:1},cross:{m:8,n1:1.3,n2:.01,n3:8,a:1,b:1},diamond:{m:4,n1:1,n2:1,n3:1,a:1,b:1},drop:{m:1,n1:.5,n2:.5,n3:.5,a:1,b:1},ellipse:{m:4,n1:2,n2:2,n3:2,a:9,b:6},gear:{m:19,n1:100,n2:50,n3:50,a:1,b:1},heart:{m:1,n1:.8,n2:1,n3:-8,a:1,b:.18},heptagon:{m:7,n1:1e3,n2:400,n3:400,a:1,b:1},hexagon:{m:6,n1:1e3,n2:400,n3:400,a:1,b:1},malteseCross:{m:8,n1:.9,n2:.1,n3:100,a:1,b:1},pentagon:{m:5,n1:1e3,n2:600,n3:600,a:1,b:1},rectangle:{m:4,n1:100,n2:100,n3:100,a:2,b:1},roundedStar:{m:5,n1:2,n2:7,n3:7,a:1,b:1},square:{m:4,n1:100,n2:100,n3:100,a:1,b:1},star:{m:5,n1:30,n2:100,n3:100,a:1,b:1},triangle:{m:3,n1:100,n2:200,n3:200,a:1,b:1}};d3.superformulaTypes=d3.keys(r)})();
<!DOCTYPE html>
<meta charset="utf-8">
<title>Superformula</title>
<style>
path {
stroke-width: 1.5px;
}
.small {
fill: steelblue;
}
.big {
stroke: #666;
fill: #ddd;
}
.small:hover {
stroke: steelblue;
fill: lightsteelblue;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="d3.superformula.min.js"></script>
<script>
var size = 1000;
var x = d3.scale.ordinal()
.domain(d3.superformulaTypes)
.rangePoints([0, 960], 1);
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
var small = d3.superformula()
.type(function(d) { return d; })
.size(size);
var big = d3.superformula()
.type("square")
.size(size * 50)
.segments(360);
svg.selectAll("a")
.data(d3.superformulaTypes)
.enter().append("a")
.attr("xlink:title", String)
.attr("transform", function(d, i) { return "translate("+ x(d) + ",40)"; })
.append("path")
.attr("class", "small")
.attr("d", small)
.on("mousedown", function() { d3.select(this).style("fill", "aliceblue"); })
.on("mouseup", function() { d3.select(this).style("fill", null); })
.on("click", function(d) { d3.select(".big").transition().duration(500).attr("d", big.type(d)); });
svg.append("path")
.attr("class", "big")
.attr("transform", "translate(450,250)")
.attr("d", big);
</script>
@uttamg911
Copy link

Hi I have observed a really strange thing in the the tooltips of the shapes.
If you click on the small blue shape thrice or more times ( click before the big one completely redraws )and move the pointer to adjacent shape ( before the big one completely redraws ), it is showing "Monday/ Tuesday ..." as the tooltip. Is that a bug? I am really curious to know the reason behind the behavior.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment