2013-06-22 7 views
2

Я начал с кодом по следующему адресу:Как сгладить анимацию JavaScript?

http://demos.sixrevisions.com/2010/09/11/demo.html

Я обновил его использовать requestAnimFrame следующим образом:

window.requestAnimFrame = (function(){ 
    return window.requestAnimationFrame  || 
     window.webkitRequestAnimationFrame || 
     window.mozRequestAnimationFrame || 
     function(callback){ 
      window.setTimeout(callback, 1000/60); 
     }; 
})(); 

Демо можно посмотреть здесь:

http://jsfiddle.net/XBssp/1/

В моих глазах, работающих под Chrome, анимация все еще кажется немного размытым при более высоких скоростях. Какие дальнейшие оптимизации я могу сделать?

+0

Это выглядит хорошо для меня в Chrome и Firefox.Можете ли вы объяснить, что вы подразумеваете под «размытым»? – Dai

+1

Вы можете снизить скорость @ Дай. Он имеет в виду, что вы видите, как он двигается, как 3 шара подряд (иллюзия глаз) – copypaste

+0

Чтобы быть более конкретным, я имею в виду эффект ореола. @yotam, так что это всегда будет присутствовать на более высоких скоростях? – deltanovember

ответ

2

jsFiddle Demo

Хорошая анимация, вы очень близко :)

Немного вещей. Во-первых, когда вы живете, вы, как правило, хотите иметь небольшие шаги, чтобы элемент, который вы анимируете, не прерывистый. Во-вторых, убедитесь, что при анимации небольшими шагами вы делаете это на высокой частоте (вы получили эту часть). В-третьих, когда анимация объекта и обнаружение конфликтов являются проблемой, убедитесь, что вы смещаете границу по размерам вашего объекта.

Мое демо изменило первое и третье примечание.

var dx=4; 
var dy=4; 

и

if(x < 20 || x > 280) 
dx=-dx; 
if(y < 20 || y > 280) 

Я также сделал ограничивающий прямоугольник более понятным для примера.

2

Я не знаю, что вы подразумеваете под размытым, но шаги в 20 пикселях сделают анимацию довольно грубой (опустите их, чтобы сделать мяч менее размытым/«skippy»).

В любом случае, если вы хотите, чтобы оптимизировать этот код вы можете настроить следующие вещи:

//put this outside the loop, no need to get it everytime 
context= myCanvas.getContext('2d'); 

//record previous position and size and only clear that area 
//instead of the complete canvas for each time 
context.clearRect(0,0,300,300); 

//pre-render this object to an off-screen canvas and use 
//drawImage(osCanvas, x, y) instead 
context.beginPath(); 
context.fillStyle="#0000ff"; 
context.arc(x,y,20,0,Math.PI*2,true); 
context.closePath(); 
context.fill(); 

и, конечно, использовать requestAnimationFrame при наличии сохранить анимацию в синхронизации с монитором vblank (устраняет рывки).

Но положите его в свою основную петлю.

Вот результат этих оптимизаций:
http://jsfiddle.net/AbdiasSoftware/XBssp/6/

Без многих элементов DOM и IFRAME:
http://jsfiddle.net/AbdiasSoftware/XBssp/6/embedded/result/

Вы не можете сделать что-нибудь о DOM обновляет так, чтобы уменьшить влияние перерисовки и другой событий в очереди событий, желательно иметь как можно меньше других элементов в одном окне. Используйте фиксированные или абсолютные позиции для элементов, если это возможно, избегайте отбрасывания теней и закругленных границ.

Источник выход optmized подхода:

function draw() { 
    //here we only clear last draw and draw the cached ball 
    context.clearRect(oldX - 2, oldY -2 ,dia +4,dia +4); 
    context.drawImage(canvas,x, y); 

    oldX = x; //store the current x/y as old x/y for next loop 
    oldY = y; 

    if(x<0 || x>300) dx=-dx; 
    if(y<0 || y>300) dy=-dy; 

    x+=dx; 
    y+=dy; 
    requestAnimationFrame(draw); 
} 

//function to create cached ball 
function createBall() { 
    canvas = document.createElement('canvas'); 
    canvas.width = dia; 
    canvas.height = dia; 
    var ctx = canvas.getContext('2d'); 

    ctx.beginPath(); 
    ctx.fillStyle="#0000ff"; 
    ctx.arc(rad,rad,rad,0,Math.PI*2,true); 
    ctx.fill(); 
} 

createBall(); //create ball 
draw();  //start anim