Статьи

Начало работы с Paper.js: анимация и изображения

До сих пор в этой серии я рассмотрел проекты и элементы , пути и геометрию , а также взаимодействие с пользователем в Paper.js. Библиотека также позволяет анимировать различные элементы в ваших проектах. Если вы комбинируете это с возможностью действовать на основе пользовательского ввода, вы можете создать действительно классные эффекты. Этот туториал покажет, как анимировать элементы в Paper.js.

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

Все анимации в Paper.js обрабатываются обработчиком события onFrame . Код внутри обработчика выполняется до 60 раз в секунду. Представление перерисовывается автоматически после каждого выполнения. Постепенное изменение некоторых свойств внутри функции может создать действительно хорошие эффекты.

Функция-обработчик onFrame также получает объект event . У объекта есть три свойства, которые предоставляют нам информацию, относящуюся к анимации.

Первый — это event.count , который сообщает нам, сколько раз выполнялся обработчик. Вторым является event.delta , который дает нам общее количество времени, прошедшее с момента последнего выполнения нашего обработчика. Третий — event.time , который дает нам время, прошедшее с первого события кадра.

Вы можете анимировать множество свойств внутри обработчика. В нашем примере я поверну три прямоугольника и изменим оттенок центрального прямоугольника. Рассмотрим код ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
var rectA = new Path.Rectangle({
  point: [300, 100],
  size: [200, 150],
  strokeColor: ‘yellow’,
  strokeWidth: 10
});
 
var rectB = rectA.clone();
rectB.strokeColor = ‘orange’;
rectB.scale(0.8);
var rectC = rectA.clone();
rectC.strokeColor = ‘black’;
rectC.scale(1.2);
 
function onFrame(event) {
  rectA.strokeColor.hue += 10 * event.delta;
  rectA.rotate(2);
  rectB.rotate(2);
  rectC.rotate(2);
}

Как видно из приведенного выше фрагмента, фактический код, необходимый для анимации наших прямоугольников, довольно минимален. Для прямоугольника A мы увеличиваем оттенок в 10 раз event.delta при каждом выполнении обработчика onFrame . Значение event.delta обычно будет близко к 0,01. Если бы я не умножил его значение на 10, потребовалось бы много времени, чтобы заметить изменение цвета.

Я также поворачиваю каждый прямоугольник на 2 градуса каждый раз, когда выполняется код. Если бы мы использовали значение event.time для поворота прямоугольников, через некоторое время повороты стали бы очень быстрыми.

Вместо того, чтобы анимировать весь путь или элемент сразу, вы также можете анимировать отдельные сегменты. Сам процесс довольно прост. Вы можете использовать path.segments чтобы вернуть массив всех сегментов, составляющих путь. Доступ к отдельным сегментам можно получить, указав значение index . Прежде чем идти дальше, я хотел бы, чтобы вы ознакомились с кодом ниже.

01
02
03
04
05
06
07
08
09
10
11
12
var aSquare = new Path.RegularPolygon(new Point(550, 200), 4, 100);
aSquare.fillColor = ‘pink’;
aSquare.fullySelected = true;
 
function onFrame(event) {
  for (var i = 0; i <= 3; i++) {
    var sinValue = Math.sin(event.time * 4 + i);
     
    aSquare.segments[i].point.x = sinValue * 100 + 350;
  }
  aSquare.segments[1].point.y = sinValue * 50 + 100;
}

Здесь мы начнем с создания квадрата с помощью конструктора Path.RegularPolygon(center, sides, radius) . Параметр sides определяет количество сторон нашего многоугольника. Параметр radius определяет размер нашего многоугольника. Я также установил для свойства fullySelected значение true чтобы вы могли видеть отдельные точки.

Внутри обработчика onFrame я перебираю все сегменты, используя цикл for, и устанавливаю их координату x равной значению, рассчитанному на основе их индекса. Использование event.time внутри функции Math.sin() не создает проблем, связанных с экстремальными значениями, поскольку значение функции Math.sin() всегда будет лежать в диапазоне от -1 до 1.

Следующая демонстрация показывает наш анимированный квадрат, который, кстати, больше не квадрат, благодаря коду внутри нашего обработчика onFrame . Я хотел бы предложить вам попробовать разные значения для параметров нашего конструктора полигонов, а также функцию sin чтобы увидеть, как они влияют на финальную анимацию в демоверсии .

Изображения в Paper.js называются растрами. Вы можете трансформировать и перемещать их, как любой другой предмет. Чтобы использовать изображение в своем проекте, вам сначала нужно добавить его в разметку вашей веб-страницы с помощью обычного тега img и присвоить ему id . Этот id позже передается new Raster(id) .

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

Образец изображения роботов и заката

Чтобы получить доступ к цветам отдельных пикселей на изображении выше, вы можете использовать raster.getPixel(x, y) , где x и y — координаты нашего пикселя. Код ниже генерирует квадраты размером 7 * 7 пикселей, заполненные цветом пикселей, расположенных в их верхнем левом углу:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
var raster = new Raster(‘landscape’);
var gridSize = 8;
var rectSize = 7;
 
raster.on(‘load’, function() {
  raster.size = new Size(80, 40);
 
  for (var y = 0; y < raster.height; y++) {
    for (var x = 0; x < raster.width; x++) {
       
      var color = raster.getPixel(x, y);
      var path = new Path.Rectangle( new Point(x, y) * gridSize, new Size(rectSize, rectSize));
 
      path.fillColor = color;
    }
  }
 
  project.activeLayer.position = view.center;
});

После загрузки растра мы изменяем его размер до 80 * 40. пиксели. Внутри вложенных циклов мы проходим отдельные пиксели этого растра и создаем 7 * 7 квадратов. Увеличение размера нашего растра даст нам лучшие результаты, но выполнение будет медленнее. Вот окончательный результат с растром с измененным размером, видимым в верхнем левом углу:

Если вы хотите скрыть растр с raster.visible , вы можете установить для свойства raster.visible значение false . Вы также можете манипулировать цветом сгенерированных квадратов. Например, чтобы увеличить красный компонент во всех квадратах, вы можете использовать следующую строку:

1
path.fillColor = color + new Color(0.4,0,0);

Окончательный результат, в этом случае, будет:

Хотя Paper.js — это библиотека векторной графики, она также позволяет создавать растры из существующих элементов. Для этого вам нужно будет использовать метод item.rasterize() . Сам исходный элемент не удаляется из проекта после растеризации. Вы также можете при желании указать разрешение вашего растра в пикселях на дюйм. Код ниже создает два растра из многоугольника с разным разрешением:

01
02
03
04
05
06
07
08
09
10
11
12
var aDodecagon = new Path.RegularPolygon(new Point(150, 180), 12, 30);
aDodecagon.fillColor = ‘#CCAAFC’;
   
var dodecRasterA = aDodecagon.rasterize();
dodecRasterA.position.x += 250;
   
var dodecRasterB = aDodecagon.rasterize(150);
dodecRasterB.position.x += 500;
   
aDodecagon.scale(3);
dodecRasterA.scale(3);
dodecRasterB.scale(3);

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

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

JavaScript стал одним из де-факто языков работы в сети. Это не без кривых обучения, и есть множество фреймворков и библиотек, которые также могут вас занять. Если вы ищете дополнительные ресурсы для обучения или использования в своей работе, посмотрите, что у нас есть на рынке Envato .

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