Here’s a scatterplot of some randomly made up fireworks display datapoint compared to the reported enjoyment of said fireworks display by an equally made up respondent.
What’s cool about this is that the patterns that make up the fireworks are created using the superformula, a parameterized shape with tremendous flexibility.
<html>
<head>
<title>Superformula Fireworks</title>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="superformula.js" type="text/JavaScript"></script>
</head>
<style>
svg {
height: 850px;
width: 900px;
border: 1px solid gray;
background: black;
}
g.am-axis text {
font-size: 8px;
}
.domain {
fill: none;
}
.tick > line {
stroke: white;
stroke-width: 1px;
stroke-opacity: .25;
}
.tick > text {
fill: white;
}
</style>
<body>
<div id="viz">
<svg>
</svg>
</body>
<footer>
<script>
var xAxisName = ["time of day", "number of children", "crowd", "distance from fireworks", "number of drinks", "patriotism"];
var xAxisDomain = [[2,12], [0,6], [2, 1000], [0.1,10], [0,12], [1,100]];
var yAxisName = "Enjoyment";
randomDomain = parseInt(Math.random() * 6);
d3.select("svg").append("text").text("Enjoyment").style("fill", "white").attr("transform", "translate(830,350) rotate(90)")
d3.select("svg").append("text").text(xAxisName[randomDomain]).style("fill", "white").attr("transform", "translate(20,510)")
xAxis = d3.svg.axis().scale(d3.scale.linear().domain(xAxisDomain[randomDomain]).range([0,800])).orient("bottom").tickSize(425).ticks(4);
d3.select("svg").append("g").attr("transform", "translate(0,50)").attr("id", "xAxisG").call(xAxis);
yAxis = d3.svg.axis().scale(d3.scale.linear().domain([0,10]).range([450,50])).orient("right").ticks(10).tickSize(800);
d3.select("svg").append("g").attr("id", "yAxisG").call(yAxis);
var randomData = d3.range(100).map(function (d,i) {
var randY = (Math.random() * 400) + 50;
var randX = (Math.random() * 700) + 50;
return {x: randX, y: randY}
});
var superCircle = d3.superformula()
.type("circle")
.size(25);
d3.select("svg").selectAll("path.fireworks")
.data(randomData)
.enter()
.append("path")
.attr("transform", function (d) {return "translate(400,800)"})
.attr("d", superCircle)
.style("fill", "darkgray")
.each(function (d) {
randomShape = d3.superformulaTypes[parseInt(Math.random() * 21)];
d3.select(this)
.transition()
.delay(function () {return Math.random() * 5000})
.transition()
.duration(function () {return (Math.random() * 500) + 100})
.attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")"})
.transition()
.duration(function () {return (Math.random() * 100) + 50})
.attr("d", function() {
var randomSize = parseInt((Math.random() * 1000) + 100);
var fireworkPattern = d3.superformula().type(randomShape).size(randomSize);
return fireworkPattern();
})
.style("fill", function () {
var randomColor = parseInt(Math.random() * 12)
return ["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"][randomColor];
})
.transition()
.duration(500)
.attr("d", function() {
var randomSize = parseInt((Math.random() * 1000) + 100);
var fireworkPattern = d3.superformula().type(randomShape).size(35);
return fireworkPattern();
})
.style("fill-opacity", .75)
.style("stroke-width", 1)
.style("stroke-opacity", .25)
.style("stroke", "white")
})
</script>
</footer>
</html>
(function() {
var _symbol = d3.svg.symbol(),
_line = d3.svg.line();
d3.superformula = function() {
var type = _symbol.type(),
size = _symbol.size(),
segments = size,
params = {};
function superformula(d, i) {
var n, p = _superformulaTypes[type.call(this, d, i)];
for (n in params) p[n] = params[n].call(this, d, i);
return _superformulaPath(p, segments.call(this, d, i), Math.sqrt(size.call(this, d, i)));
}
superformula.type = function(x) {
if (!arguments.length) return type;
type = d3.functor(x);
return superformula;
};
superformula.param = function(name, value) {
if (arguments.length < 2) return params[name];
params[name] = d3.functor(value);
return superformula;
};
// size of superformula in square pixels
superformula.size = function(x) {
if (!arguments.length) return size;
size = d3.functor(x);
return superformula;
};
// number of discrete line segments
superformula.segments = function(x) {
if (!arguments.length) return segments;
segments = d3.functor(x);
return superformula;
};
return superformula;
};
function _superformulaPath(params, n, diameter) {
var i = -1,
dt = 2 * Math.PI / n,
t,
r = 0,
x,
y,
points = [];
while (++i < n) {
t = params.m * (i * dt - Math.PI) / 4;
t = Math.pow(Math.abs(Math.pow(Math.abs(Math.cos(t) / params.a), params.n2)
+ Math.pow(Math.abs(Math.sin(t) / params.b), params.n3)), -1 / params.n1);
if (t > r) r = t;
points.push(t);
}
r = diameter * Math.SQRT1_2 / r;
i = -1; while (++i < n) {
x = (t = points[i] * r) * Math.cos(i * dt);
y = t * Math.sin(i * dt);
points[i] = [Math.abs(x) < 1e-6 ? 0 : x, Math.abs(y) < 1e-6 ? 0 : y];
}
return _line(points) + "Z";
}
var _superformulaTypes = {
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: 1000, n2: 400, n3: 400, a: 1, b: 1},
hexagon: {m: 6, n1: 1000, 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: 1000, 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(_superformulaTypes);
})();