Skip to content

Instantly share code, notes, and snippets.

@walkerjeffd
Last active May 20, 2017 12:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walkerjeffd/804dedb5214ca11a04931d74fe5ca1c1 to your computer and use it in GitHub Desktop.
Save walkerjeffd/804dedb5214ca11a04931d74fe5ca1c1 to your computer and use it in GitHub Desktop.
Spinning Ovals III
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.5/dat.gui.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.stop-left {
stop-color: rgba(0, 192, 191, 1); /* Indigo */
}
.stop-right {
stop-color: rgba(44, 161, 252, 1); /* Teal */
}
.outlined {
fill: none;
stroke: url(#mainGradient);
}
ellipse { mix-blend-mode: normal; }
.isolate { isolation: isolate; }
</style>
</head>
<body>
<script>
var gui = new dat.GUI();
var ellipseFactor = 0.92352 ,
speed = 10000,
omega = 180,
scale = 1,
strokeWidth = 38,
blur = 0,
n = 2,
minRadius = 100,
radiusFactor = 1.04,
pulseFactor = 4;
var opacity = 0.4;
// var opacity = 1/n;
gui.add(window, "n", 1, 20).step(1).onChange(restart);
gui.add(window, "speed", 100, 20000).step(100);
gui.add(window, "strokeWidth", 0, 100).step(10);
gui.add(window, "ellipseFactor", 0.1, 2).step(0.01);
gui.add(window, "opacity", 0, 1).step(0.01);
gui.add(window, "blur", 0, 10).step(0.1);
gui.add(window, "pulseFactor", 0, 100);
gui.add(window, "radiusFactor", 1, 2).step(0.01);
gui.add(window, "omega", 0, 360).step(1);
var width = 960,
height = 500;
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('class', 'isolate')
.attr('transform', 'scale(' + scale + ')')
var defs = svg.append('defs');
// Color gradient
var mainGradient = defs.append('linearGradient')
.attr('id', 'mainGradient');
mainGradient.append('stop')
.attr('class', 'stop-left')
.attr('offset', '0');
mainGradient.append('stop')
.attr('class', 'stop-right')
.attr('offset', '1');
// Filter for the outside glow
var filter = defs.append('filter')
.attr('id', 'glow');
var feGaussianBlur = filter.append('feGaussianBlur')
.attr('stdDeviation', blur)
.attr('result','coloredBlur');
var feMerge = filter.append('feMerge');
feMerge.append('feMergeNode')
.attr('in', 'coloredBlur');
feMerge.append('feMergeNode')
.attr('in', 'SourceGraphic');
// Shapes
var ellipse;
function restart() {
console.log("restart", n);
var data = d3.range(n);
svg.selectAll('ellipse').remove();
var ellipseSel = svg.selectAll('ellipse')
.data(data);
ellipse = ellipseSel
.enter()
.append('ellipse')
.classed('outlined', true)
.style('filter', 'url(#glow)')
.style('opacity', opacity)
.style('stroke-width', strokeWidth)
.attr('cx', width / 2)
.attr('cy', height / 2)
.attr('rx', 100 * ellipseFactor)
.attr('ry', 100)
ellipseSel.exit().remove();
ellipse.each(function (d) {
var theta = d / n * omega;
d3.select(this)
.attr('transform', 'rotate(' + theta + ',' + width/2 + ',' + height/2 + ')');
});
}
restart();
d3.timer(function (elapsed) {
feGaussianBlur.attr('stdDeviation', blur);
ellipse
.style('opacity', opacity)
.style('stroke-width', strokeWidth)
.attr('rx', 100 * ellipseFactor);
ellipse.each(function (d) {
var theta = elapsed % speed / speed * 360 + d / n * omega,
r = minRadius + (minRadius * radiusFactor - minRadius) * (Math.sin(((elapsed % speed * pulseFactor) / speed) * 2 * Math.PI) / 2 + 0.5);
d3.select(this)
.attr('transform', 'rotate(' + theta + ',' + (width/2) + ',' + (height/2) + ')')
.attr('rx', r * ellipseFactor)
.attr('ry', r);
})
})
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment