<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg.js"></script>
</head>
<body>
<svg id="svg" width="600px" height="600px"></svg>
<script src="script.js"></script>
</body>
</html>
var s = Snap("#svg");
var padding = 10; // left/top padding
var r = 280; // radius of big circle
var rotation = 0; // current rotation (radiants)
var step = 100;
var animSpeed = 20;
// big circle
var bigCircle = s.circle(padding + r, padding + r, r);
bigCircle.attr({
fill: 'white',
stroke: 'black',
strokeWidth: 3
});
// bounding circle for smooth animation
var smallCircleBounding = s.circle(padding + r, padding + r/2, r/2 + 8);
smallCircleBounding.attr({ fill: 'none', stroke: 'none' });
// small, rotating circle with radius = r/2
var smallCircle = s.circle(padding + r, padding + r/2, r/2);
smallCircle.attr({
fill: 'white',
stroke: 'gray',
strokeWidth: 1,
});
// dot rotating with small circle
var dot = s.circle(padding + r, padding, 4);
dot.attr({
fill: 'red'
});
// group rotating circles
var group = s.group(smallCircleBounding, smallCircle, dot);
// line on which the dot moves
var line = s.line(padding + r, padding, padding + r, padding + 2 * r);
line.attr({
stroke: 'lightgray',
strokeWidth: 1,
'stroke-dasharray': '5,5'
});
// timer function
var timerFunc = function() {
// increment rotation
rotation += Math.PI / step;
if (rotation >= 2 * Math.PI) {
rotation -= 2 * Math.PI;
}
// calculate translation of small circle
var x = Math.cos(Math.PI / 2 - rotation) * r/2;
var y = r/2 - Math.sin(Math.PI / 2 - rotation) * r/2;
// transform circle and dot
group.animate(
{ transform: 'T' + Math.round(x) +',' + Math.round(y) + 'R' + (-1) * rotation / Math.PI / 2 * 360 },
animSpeed,
timerFunc);
};
// schedule first animation step
timerFunc();