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> |