Here is a source code for static part of the project. It renders the orbit inside browser. I didn't catch a time to finish dynamic rotation stuff, but if anyone wants to build up upon the static part, they are very welcome.

orbital.html:

`<!DOCTYPE html>`

<!--?xml version="1.0"?-->

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Orbital</title>

<style type="text/css" media="screen">

html, body, div, svg

{

overflow: hidden;

height: 100%;

width: 100%;

margin-top:0px;

margin-left:0px;

}

</style>

<body>

<div id="intro">

<svg><!-- viewBox="0 0 400 400" transform='scale(1, 1)'-->

</svg>

</div>

<script src="orbital.js"></script>

<script>

orbital(document.getElementsByTagName('svg')[0]);

</script>

</body>

</html>

orbital.js:

`function orbital (svg) {`

"use strict";

var ratio = 0.5;//575;

var minRadius = 0.5;

var branchCount = 42;

var pixelPrecision = 1 / 32;

var fill1 = "rgb(255, 255, 150)";//"lightgray";

var stroke1 = "gray";

var fill2 = stroke1;

var stroke2 = fill1;

var svgns = "http://www.w3.org/2000/svg";

function insertGroup () {

var g;

g = document.createElementNS(svgns, "g");

g.setAttribute('id', 'group');

g.setAttribute('shape-rendering', 'inherit');

g.setAttribute('pointer-events', 'all');

return g;

}

function insertCircle (x, y, r, fill, stroke) {

var el = document.createElementNS(svgns, 'ellipse');

el.setAttribute('cx', x * squashX);

el.setAttribute('cy', y * squashY);

el.setAttribute('rx', r * squashX);

el.setAttribute('ry', r * squashY);

el.setAttribute('fill', fill);

el.setAttribute('stroke-width', 1);

el.setAttribute('stroke', stroke);

return el;

}

function insertRect (x, y, width, height, fill, stroke) {

var rect = document.createElementNS(svgns, 'rect');

rect.setAttribute('x', x);

rect.setAttribute('y', y);

rect.setAttribute('height', height);

rect.setAttribute('width', width);

rect.setAttribute('fill', fill);

rect.setAttribute('stroke-width', 1);

rect.setAttribute('stroke', stroke);

return rect;

}

function node() {

var children = (function () {

return {

alphaOffset: Math.PI,

itemOffset: 0,

items: (function (itemCount) {

var i, items;

items = [];

for (i = 0; i < itemCount; i++)

items.push (i);

return items;

})(branchCount),

getX: function (index) {

return (rLarge + rSmall) * Math.cos (-Math.PI / 2 - index * alpha);

},

getY: function (index) {

return (rLarge + rSmall) * Math.sin (-Math.PI / 2 - index * alpha);

}

};

})();

var render = function (minRadius, x1, y1, r1, alpha0, rec) {

function getCircle (alpha) {

var beta = alpha0 + alpha - Math.PI / 2;

var ra = 0;

var xa = x0 + r0 * Math.cos (beta);

var ya = y0 + r0 * Math.sin (beta);

var rb = 2 * r1;

var xb = x0 + (r0 + rb) * Math.cos (beta);

var yb = y0 + (r0 + rb) * Math.sin (beta);

var dr = (rb - ra) / 2;

var dx = (xb - xa) / 2;

var dy = (yb - ya) / 2;

ra += dr;

xa += dx;

ya += dy;

var j;

do {

dx /= 2;

dy /= 2;

dr /= 2;

var d = Math.sqrt (Math.pow ((xa - x1), 2) + Math.pow ((ya - y1), 2));

if (Math.abs (ra - r1) <= d) {

xa -= dx;

ya -= dy;

ra -= dr;

} else {

xa += dx;

ya += dy;

ra += dr;

}

} while (dr > pixelPrecision);

return {

x: (r0 + ra) * Math.cos (beta),

y: (r0 + ra) * Math.sin (beta),

r: ra,

alpha: alpha

};

}

function getNeighbor (c1) {

var alpha = c1.alpha / 2;

var dalpha = alpha;

var j;

var datmp = 2 * Math.pow (2 * r1, 2);

var da = Math.acos ((datmp - Math.pow (pixelPrecision, 2)) / datmp);

do {

var c2 = getCircle (alpha);

dalpha /= 2;

var d = Math.sqrt (Math.pow ((c1.x - c2.x), 2) + Math.pow ((c1.y - c2.y), 2));

if ((c1.r + c2.r) >= d) {

alpha -= dalpha;

} else {

alpha += dalpha;

}

} while (dalpha > da);

return c2;

}

var r0 = r1 * ratio;

var x0 = x1 + (r1 - r0) * Math.cos (alpha0 - Math.PI / 2);

var y0 = y1 + (r1 - r0) * Math.sin (alpha0 - Math.PI / 2);

if (r0 > minRadius) {

var g = svg;

g.appendChild (insertCircle (x0, y0, r0, fill1, stroke1));

var i;

var alpha = 4 * Math.PI / 2 - 0.3941;

var c1 = getCircle (alpha);

for (i = 0; i < branchCount; i++) {

if (c1.r > minRadius)

render (minRadius, x0 + c1.x, y0 + c1.y, c1.r, alpha0 + alpha - Math.PI, rec);

c1 = getNeighbor (c1);

alpha = c1.alpha;

}

}

};

return {

children: children,

render: render

};

}

var ww = window.innerWidth;

var hh = window.innerHeight;

var rr, squashX, squashY;

if (ww > hh) {

rr = hh / 2;

squashX = ww / hh;

squashY = 1;

} else {

rr = ww / 2;

squashX = 1;

squashY = hh / ww;

}

var r1 = rr;

var x1 = ww / squashX - rr;

var y1 = hh / squashY - rr;

var n = node();

var i = 8;

var repeat = function () {

if (i >= minRadius) {

var s = svg.cloneNode(false);

svg.parentNode.replaceChild(s, svg);

svg = s;

svg.appendChild(insertRect (0, 0, ww, hh, fill2, stroke2));

n.render (i, x1, y1, r1, 0, 1);

setTimeout (repeat, 0);

}

i/=2;

};

repeat();

}