Created for d3 viSFest unconf 2017
generates elliptical paths, moves 'stars' along those paths with path.getPointAtLength();
function for elliptical paths adapted from this stackverflow question
Created using blockbuilder
license: gpl-3.0 | |
height: 960 |
Created for d3 viSFest unconf 2017
generates elliptical paths, moves 'stars' along those paths with path.getPointAtLength();
function for elliptical paths adapted from this stackverflow question
Created using blockbuilder
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>unconf 2017 viz</title> | |
<style> | |
body {margin:0;} | |
svg { background: #000; } | |
</style> | |
</head> | |
<body> | |
<svg width="960px" height="960px" viewBox="0 0 960 960" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | |
<defs> | |
<path class="star" d="M32,64 C32,46.326888 46.326888,32 64,32 C46.326888,32 32,17.673112 32,0 C32,17.673112 17.673112,32 0,32 C17.673112,32 32,46.326888 32,64 Z"></path> | |
</defs> | |
<style> | |
.star { | |
fill: #fff; | |
stroke: none; | |
} | |
.color-orbit { | |
fill: none; | |
stroke-width: 8px; | |
} | |
.star-orbit { | |
fill: none; | |
stroke: none; | |
} | |
</style> | |
<g id="orbital-grp"></g> | |
<g id="stars-grp"></g> | |
</svg> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script> | |
<script> | |
var svg = d3.select('svg'); | |
var svgDims = svg.node().getBoundingClientRect(); | |
var ctrX = svgDims.width * 0.5; | |
var ctrY = svgDims.height * 0.5; | |
var orbitRx = (svgDims.width - 128) * 0.5; | |
var orbitalGrp = d3.select('#orbital-grp'); | |
var starDef = document.querySelector('svg defs .star'); | |
var starDims = starDef.getBoundingClientRect(); | |
var starsGrp = d3.select('#stars-grp'); | |
var colors = ['hsl(0, 100%, 50%)','hsl(28, 100%, 50%)','hsl(60, 100%, 50%)','hsl(90, 100%, 50%)','hsl(120, 100%, 50%)','hsl(216, 100%, 50%)','hsl(252, 100%, 50%)','hsl(272, 100%, 50%)','hsl(288, 100%, 50%)','hsl(314, 100%, 50%)']; | |
var clx = 0; | |
var cLen = colors.length; | |
function ellipticalPath (cx, cy, rx, ry) { | |
return 'M' + (cx - rx) + ',' + cy | |
+ ' a' + rx + ',' + ry | |
+ ' 0 1,0 ' + (rx * 2) + ',0' | |
+ ' a' + rx + ',' + ry | |
+ ' 0 1,0 -' + (rx * 2) + ',0 Z' | |
} | |
function setOrbitTransform (idx) { | |
return 'translate(' + ctrX + ', ' + ctrY + ')' | |
+ ' rotate(' + (idx * 18) + ') ' // 10 colors, 180 / 10 | |
+ ' translate( -' + ctrX + ', -' + ctrY + ' )'; | |
} | |
function cycle () { | |
var orbits = orbitalGrp.selectAll('.color-orbit'); | |
orbits.each(function () { | |
var orbit = d3.select(this); | |
var nextColor = orbit.datum().color - 1 < 0 ? cLen - 1 : orbit.datum().color - 1; | |
orbit | |
.attr('stroke', colors[nextColor]) | |
.datum({'color': nextColor}); | |
}); | |
var starGrps = d3.selectAll('.star-grp'); | |
starGrps.each(function () { | |
var starGrp = d3.select(this); | |
var starOrbit = starGrp.select('.star-orbit'); | |
var len = starOrbit.node().getTotalLength(); | |
var stars = starGrp.selectAll('.star') | |
stars.each(function () { | |
var star = d3.select(this); | |
var step = star.datum().step + 1 < 10 ? star.datum().step + 1 : 0; | |
var pt = starOrbit.node().getPointAtLength(step * len * .1) | |
star | |
.attr('transform', 'translate(' + (pt.x - 32) + ',' + (pt.y - 32) + ')') | |
.datum({ 'step': step}); | |
}); | |
}); | |
setTimeout(cycle, 100); | |
} | |
function draw () { | |
var colorOrbit, starGrp, starOrbit, star0, star1, len, cp5, pt0, pt1; | |
for (clx; clx < cLen; clx += 1) { | |
colorOrbit = orbitalGrp.append('path') | |
.attr('id', 'orbit-' + clx) | |
.attr('class', 'color-orbit') | |
.attr('stroke', colors[clx]) | |
.attr('d', ellipticalPath(ctrX, ctrY, orbitRx, 192)) | |
.datum({'color': clx}); | |
starGrp = starsGrp.append('g') | |
.attr('class', 'star-grp'); | |
starOrbit = starGrp.append('path') | |
.attr('id', 'star-orbit-' + clx) | |
.attr('class', 'star-orbit') | |
.attr('d', ellipticalPath(ctrX, ctrY, orbitRx, 192)); | |
cp5 = clx + 5 < 10 ? clx + 5 : clx + 5 - 10; | |
len = starOrbit.node().getTotalLength(); | |
pt0 = starOrbit.node().getPointAtLength(len * clx * .1) | |
pt1 = starOrbit.node().getPointAtLength(len * cp5 * .1) | |
star0 = d3.select(starGrp.node().appendChild(starDef.cloneNode(true))) | |
.attr('id', 'star-' + clx + '-0' ) | |
.attr('transform', 'translate(' + (pt0.x - 32) + ',' + (pt0.y - 32) + ')') | |
.datum({ 'step': clx}); | |
star1 = d3.select(starGrp.node().appendChild(starDef.cloneNode(true))) | |
.attr('id', 'star-' + clx + '-1') | |
.attr('transform', 'translate(' + (pt1.x - 32) + ',' + (pt1.y - 32) + ')') | |
.datum({ 'step': cp5}); | |
colorOrbit.attr('transform', setOrbitTransform(clx)) | |
starGrp.attr('transform', setOrbitTransform(clx)) | |
} | |
} | |
draw(); | |
setTimeout(cycle, 100); | |
</script> | |
</body> | |
</html> |