Демо JavaScript:
<script> var ctx, canvas; var xc1, xc2, xc3; var yc1, yc2, yc3; var iter; //анимирующая функция, реализуемая для всех браузеров window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame })(); //функция, запускающаяся при загрузке станицы window.onload = function() { canvas = document.getElementById('paint'); ctx = canvas.getContext('2d'); w = canvas.width; h = canvas.height; //центры окружностей-траекторий, по которым движутся круги xc1 = 150; xc2 = 300; xc3 = 225; yc1 = 150; yc2 = 150; yc3 = 275; iter = 0; //чёрный фон ctx.beginPath(); ctx.fillStyle = "black"; ctx.fillRect(0, 0, w, h); ctx.closePath(); //вызов функций, которые рисуют 12 кругов синего, красного и зелёного цветов ctx.fillStyle = "blue"; DrawCircles(xc1, yc1, 0); ctx.fillStyle = "red"; DrawCircles(xc2, yc2, Math.PI/3); ctx.fillStyle = "green"; DrawCircles(xc3, yc3, Math.PI/6); //запуск функции, производящей анимацию anim(); } // основная функция, рисующая 12 кругов function DrawCircles(xc, yc, t){ t %= 2*Math.PI; r = 1; //цикл, рисующий круги через каждые 30 градусов с радиусом r for (var al = t; al <= t + 2*Math.PI; al += Math.PI/6){ if (r == 0) r = -1/6 x = Math.cos(al); y = Math.sin(al); x *= 100; y *= 100; x += xc; y += yc; ctx.beginPath(); ctx.arc(x, y, 12 * Math.abs(r), 0, 2*Math.PI); ctx.fill(); ctx.closePath(); r -= 1/6; } } //функция, производящая анимацию function anim(){ //черный фон ctx.beginPath(); ctx.fillStyle = "black"; ctx.fillRect(0, 0, w, h); ctx.closePath(); //смещение кругов на 1.5 градуса iter += Math.PI/120; iter %= Math.PI/6; //вызов функций, которые рисуют 12 кругов синего, красного и зелёного цветов ctx.fillStyle = "blue"; DrawCircles(xc1, yc1, iter + 2*Math.PI/3 + Math.PI/2); ctx.fillStyle = "red"; DrawCircles(xc2, yc2, iter + 4*Math.PI/3 + Math.PI/2); ctx.fillStyle = "green"; DrawCircles(xc3, yc3, iter + 0 + Math.PI/2); requestAnimFrame(anim); } </script>