Демо JavaScript:
var f=0; //переключатель состояний var a=150,b=150; // параметры сжатия по оси Х и У var c=100; // координата У центра мячика, а координата Х не изменяется var ctx; //наш конвас var ImgData //тут храним слепок фона)для быстрой отрисовки. ctx = document.getElementById('paintbox').getContext('2d'); function bg(){ //рисуем фон ctx.fillStyle="#008000"; for(var i=0;i<500;i+=20){ for(var j=0;j<500;j+=20){ ctx.beginPath(); ctx.fillRect(i,j,15,15); ctx.closePath(); ctx.fill(); ctx.stroke(); } } } function drawEllipse(c, q, p){ //рисуем сам мячик ctx.putImageData(ImgData,0,0); //перед тем как рисовать нам нужно отрисовать фон ctx.save(); //на всякий случай сохранил параметры канваса и стилей ctx.beginPath(); ctx.scale(q/p,1); //изменил масштабы по х и у ctx.arc(0,c,p,0,Math.PI*2); ctx.closePath(); ctx.fill(); ctx.stroke(); ctx.restore(); // ну раз уж сохранил то давай и восстанови гыгы } function animate(){//анимация мячика ctx.clearRect(0, 0, 500, 500); if(f==0&&c<150){ //сжатие a+=2; b-=2; c+=2; } if(c==150&&f==0){f=1;} //переключили if(f==1&&c>100){ //растягивание a-=2; b+=2; c-=2; } if(c==100&&f==1){f=2;} //переключили if(c>-150&&f==2){ //прыжок c-=5; } if(c==-130&&f==2){f=3;} //переключили if(f==3&&c<100){ //падение c+=5; } if(c==100&&f==3){f=0;} //переключили на сжатие drawEllipse(c,a,b); window.requestAnimationFrame(animate); } function start(){ bg(); //рисуем фон с помощью скрипта ImgData = ctx.getImageData(0,0,500,500); //сохраняем фон ctx.translate(250,250); //перенесли начало координат в центр канваса ctx.strokeStyle="blue"; //задаем цвет самого мячика ctx.fillStyle="red"; //и его контура animate(); }