JSFiddle - React, Tailwind, and code Playground

HTML

<input id="go" type="button" value="Go!" />
<div id="canvas"></div>

JavaScript

/*
Ellipse: (x/a)^2 + (y/b)^2 = 1
     or: y = +/- b * (1 - (x/a)^2)^0.5
Focus = Center(x) +/- (a^2 - b^2) ^ 0.5
http://en.wikipedia.org/wiki/Ellipse#Focus
*/

var paper = Raphael("canvas", 500, 500);adadasd

var center = {x: 100, y: 200 };
var a = 100;
var b = 80;

//see http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
var ellipse = "M" + (center.x - a) + "," + center.y + " a " + a + "," + b + " 0 1,1 0,0.1";

var orbit = paper.path(ellipse);
               
var focus = Math.pow(a*a - b*b, 0.5);

var palebluedot = paper.circle(center.x - focus, center.y, 25)
    .attr({
        stroke: 0,
        fill: "blue"    
    });

var moon = paper.circle(center.x - a, center.y, 10)
.attr({
    stroke: 0,
    fill: "#CCC"
});

document.getElementById("go").addEventListener('click', function() {
    console.log("moon");
    moon.animateAlong(orbit, 2000);
});
    
//Adapted from https://github.com/brianblakely/raphael-animate-along/blob/master/raphael-animate-along.js
Raphael.el.animateAlong = function(path, duration, easing, callback) {
    var element = this;
    element.path = path;
    element.pathLen = element.path.getTotalLength();    
    duration = (typeof duration === "undefined") ? 5000 : duration;
    easing = (typeof easing === "undefined") ? "linear" : duration;

    //create an "along" function to take a variable from zero to 1 and return coordinates. Note we're using cx and cy specifically for a circle    
paper.customAttributes.along = function(v) {
		var point = this.path.getPointAtLength(v * this.pathLen),
			attrs = {
				cx: point.x,
				cy: point.y 
			};
 		this.rotateWith && (attrs.transform = 'r'+point.alpha);
		return attrs;
	};    
    
    element.attr({along: 0 }).animate({along: 1}, duration, easing, function() {
		callback && callback.call(element);
	});    
};