Анимация в p5.js

p5.js отлично подходит для создания и запуска простой анимации в браузере, по сравнению, скажем, с d3.js, для которого требуется немного больше шаблонов.

Но одна вещь, которой нет в p5.js, - это простой способ управления переходами между состояниями, который есть в d3.js. Мы могли бы легко создать функцию замедления с нуля для переходов между состояниями или для промежуточного перехода между состояниями, но зачем это делать, если есть библиотеки, которые могут сделать это за нас.

Библиотека TweenLite от GSAP (или GreenSock Animation Platform) отлично подходит для этого. Это очень просто в использовании. Единственная сложность - понять, как заставить его работать с циклом отрисовки библиотеки p5.js.

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

var pos = {x:0, y:0};

function setup(){
	...
    ellipse(pos.x,pos.y,40,40);
    TweenLite.to(pos, 5, {x:width});
	...
}

Функция TweenLite принимает 3 параметра. Первый - это исходный объект (с начальными значениями), второй - продолжительность анимации движения, а третий - значения в конечном состоянии.

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

var currentPos = [];
var newPos = [];
var colorsPalette;
var numpoints = 80;

function setup() {

    c = createCanvas(600,600);
    c.parent('p5canvas');
    
    colorsPalette = [color(146, 167, 202,25),
            color(186, 196, 219,50),
            color(118, 135, 172,250),
            color(76, 41, 81,250),
            color(144, 62, 92,50),
            color(178, 93, 119,250),
            color(215, 118, 136,250),
            color(246, 156, 164,250),];
    background(colorsPalette[0]);

    frameRate(30);

    for (var i=0;i<numpoints;i++){        
        currentPos.push({
          x: random(width),
          y: random(height),
          c: colorsPalette[6]
        })    
    }
    for (var i=0;i<numpoints;i++){        
        newPos.push({
          x: random(width)+random(),
          y: random(height)+random(),
          c: colorsPalette[6]
        })    
    }

}

Мы создали массивы currentPos и ​​newPos для хранения текущего и нового состояний, некоторых цветов и инициализировали массивы currentPos и ​​newPos.

Далее, мясо этого поста.

function draw() {
    
    background(colorsPalette[0]);

    if (frameCount%300==0){
        for (var i=0;i<numpoints;i++){      
            newPos[i].x = random(width)+random();
            newPos[i].y = random(height)+random();
        }

    }


    for (var i=0;i<numpoints;i++){
        TweenLite.to(currentPos[i], 10, newPos[i]);
        noStroke();
        fill(currentPos[i].c);
        ellipse(currentPos[i].x,currentPos[i].y,3,3);
        noStroke();
        fill(255,150);
        ellipse(currentPos[i].x+2,currentPos[i].y,1,1); 
        ellipse(currentPos[i].x-2,currentPos[i].y,1,1);   
    }

}

Что мы здесь сделали, так это обновили объект newPos с новыми позициями x и y. Затем мы перебираем каждую точку, чтобы применить анимацию движения и нарисовать эллипсы. Следует отметить всего две вещи:

  • Нет необходимости устанавливать для currentPos значение newPos отдельно. Это было то, что я делал изначально, и это просто испортило всю анимацию. Что здесь происходит, так это то, что TweenLite уже обновляет currentPos по мере того, как подготавливает его к newPos.
  • TweenLite может обрабатывать только одну точку данных за раз. Это не сработало, когда я передал все currentPos и ​​newPos в
  • Не критично синхронизировать время между вычислением newPos и ​​длительностью промежуточного кадра, но это действительно делает вещи более плавными. Что я здесь сделал, так это вычислить новое значение newPos каждые 300 кадров. Поскольку частота кадров составляет 30 кадров в секунду, это означает, что мы обновляем newPos каждые 10 секунд, что также является продолжительностью, которую я установил для анимации движения в TweenLite.

И это все. Вы можете найти полный код здесь. А здесь вы можете увидеть демонстрацию стилизованных рыб, плавающих в пруду.

Playgrd.com || Facebook.com/playgrdstar || Instagram.com/playgrdstar/