2014-01-24 8 views
1

У меня есть простая анимация на холсте: два прямоугольника перемещаются в двух разных направлениях. Однако я чувствую, что это может быть упрощено.Просто анимация холста

http://jsfiddle.net/tmyie/R5wx8/6/

var canvas = document.getElementById('canvas'), 
    c = canvas.getContext('2d'), 
    x = 10, 
    y = 15, 

    a = 20, 
    b = 50; 

function move() { 
    c.clearRect(0, 0, 500, 300); 

    c.fillRect(0, y, 5, 5), 
    c.fillRect(b, 5, 15, 15); 


    x++; 
    y++; 
    b++ 

    if (y > canvas.height || x > canvas.width) { 
     y = 0; 
     x = 0; 
    } 
} 

setInterval(move, 100); 

Например, что произойдет, если я хотел создать еще три фигуры? На данный момент, я должен был бы создать больше переменных для каждой координаты:

x++; 
    y++; 
    b++ 

Есть ли способ, которым я мог бы превратить каждый прямоугольник в свой собственный объект?

+2

Вы должны рассмотреть возможность использования [requestAnimationFrame()] (https://developer.mozilla.org/en/docs/Web/API/window.requestAnimationFrame) вместо setInterval() при анимации. Лучше для производительности, и цикл останавливается, когда вкладка браузера не активна. Чтобы создать непрерывный цикл, замените строку setInterval на 'window.requestAnimationFrame (move);' и добавьте ту же строку снова в начале функции перемещения. – Strille

ответ

4

Вы можете, конечно, превратить их в объекты, например:

function Rect(x, y, w, h, dltX, dltY, color) { 

    var me = this; 

    this.x = x; 
    this.y = y; 
    this.width = w; 
    this.height = h; 

    this.deltaX = dltX || 0;  /// and deltas can be optional 
    this.deltaY = dltY || 0; 
    this.color = color || '#000'; /// color is optional 

    this.update = function(ctx) { 
     me.x += me.deltaX; 
     me.y += me.deltaY; 

     ctx.fillStyle = me.color; 
     ctx.fillRect(me.x, me.y, me.width, me.height); 
    }  
} 

deltaX и deltaY насколько вы хотите переместить прямоугольник для каждого обновления. Если вы установите их, например, 1, то x и y будут увеличены с 1 при каждом вызове update().

Использование deltas позволяет легко создавать отскоки (см. Демонстрацию ниже), просто изменяя значение дельта (то есть delta = -delta), а также такие вещи, как ускорение, скорость изменения, вы можете кормить их через тригонометрические функции, чтобы иметь объект двигаться под определенным углом и т. д.

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

Online demo here

Теперь, когда мы определили объект, мы можем просто создать его экземпляры и хранить их в массиве:

var rects = [ 
    new Rect(10, 10, 100, 100, 1, -2), 
    new Rect(100, 1, 50, 50, 2, 1, '#f00'), 
    ... 
] 

Отсюда это просто вопрос переборе массива обновить каждый объект:

function move() { 
    ctx.clearRect(0, 0, width, height); 

    for(var i = 0, r; r = rects[i]; i++) { 
     /// check any conditions here 
     r.update(ctx); 
    } 
    requestAnimationFrame(move); 
} 

requestAnimationFrame(move); /// start loop 
+1

Я никогда раньше не видел этого для синтаксиса цикла, и это потрясающе. Использование задания как проверки границ массива, блестящее. – Tesserex

+0

Не могли бы вы объяснить deltaX, deltaY? Я этого раньше не видел. –

+1

@tmyie, конечно, см. Обновленный ответ. – K3N

1

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

var canvas = document.getElementById('canvas'), 
    c = canvas.getContext('2d'), 
    rects = [{x:0, y:15, w:5, h:5, vx:0, vy:1}, 
      {x:50, y:5, w:15, h:15, vx:1, vy:0}]; 

function move() { 
    c.clearRect(0, 0, 500, 300); 

    for (var i=0; i < rects.length; i++) { 
     var rect = rects[i]; 
     c.fillRect(rect.x, rect.y, rect.w, rect.h), 
     rect.x += rect.vx; 
     rect.y += rect.vy; 
    } 
} 

setInterval(move, 100); 
Смежные вопросы