Статьи

Руководство для начинающих по рисованию 2D-графики с Two.js

Two.js API, который позволяет легко создавать 2D фигуры с помощью кода. Следуйте инструкциям, и вы узнаете, как создавать и анимировать фигуры из JavaScript.

Two.js не зависит от рендерера, поэтому вы можете полагаться на один и тот же API для рисования с помощью Canvas, SVG или WebGL. В библиотеке есть много методов, которые можно использовать для управления тем, как различные фигуры появляются на экране или как они анимируются.

Несжатая версия библиотеки имеет размер около 128 КБ, а сжатая версия составляет 50 КБ. Если вы используете последнюю версию, вы можете еще больше уменьшить размер библиотеки, используя пользовательскую сборку.

Вы можете загрузить минимизированную версию библиотеки с GitHub или напрямую связать ее с размещенной на CDN версией . Добавив библиотеку на свою веб-страницу, вы можете начать рисовать и анимировать различные фигуры или объекты.

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

Установите тип рендерера, используя свойство type . Вы можете указать такие значения, как svg , webgl , canvas и т. Д. type по умолчанию установлен на svg . Ширина и высота области рисования могут быть указаны с помощью параметров width и height . Вы также можете установить пространство для рисования на весь доступный экран, используя параметр fullscreen . Если для fullscreen режима задано значение true, значения width и height будут игнорироваться.

Наконец, вы можете указать Two.js автоматически запускать анимацию с помощью логического параметра autostart .

После передачи всех необходимых параметров в конструктор, вы можете начать рисовать линии, прямоугольники, круги и эллипсы.

Вы можете нарисовать линию, используя two.makeLine(x1, y1, x2, y2) . Здесь (x1, y1) — координаты первой конечной точки, а (x2, y2) — координаты второй конечной точки. Эта функция вернет объект Two.Line , который может быть сохранен в переменной для дальнейших манипуляций на более позднем этапе.

Аналогичным образом вы можете нарисовать прямоугольники с нормальными и закругленными углами, используя two.makeRectangle(x, y, width, height) и two.makeRoundedRectangle(x, y, width, height, radius) соответственно. Помните, что x и y определяют центр прямоугольника, а не его верхние левые координаты, как во многих других библиотеках. Параметры width и height будут определять размер прямоугольника. Параметр radius используется для указания значения радиуса для закругленного угла.

Вы также можете визуализировать круги и эллипсы на веб-странице, используя two.makeCircle(x, y, radius) и two.makeEllipse(x, y, width, height) соответственно. Как и прямоугольники, параметры x и y определяют центр круга или эллипса. Установка width и height в одно и то же значение в случае эллипса отобразит его как круг.

Один из полезных методов в Two.js, который вы будете часто использовать, — это two.makeGroup(objects) . Вы можете передать список различных объектов или передать массив объектов, путей или групп в качестве параметра этому методу. Он также вернет объект Two.Group .

После того, как вы создали группу, вы можете управлять всеми ее дочерними элементами одновременно, используя свойства, которые группа делает доступными для вас.

Свойства stroke и fill можно использовать для установки цвета обводки и заливки для всех детей в группе. Они будут принимать все допустимые формы, в которых вы можете представлять цвет в CSS. Это означает, что вы можете использовать RGB, HSL или шестнадцатеричное обозначение. Вы также можете просто использовать название цвета, например, orange , red или blue . Точно так же вы можете установить значения для всех других свойств, таких как linewidth , opacity , miter и cap . Можно удалить заливку и обводку из всех дочерних noFill() в группе, используя noFill() и noStroke() .

Вы также можете применять другие физические преобразования, такие как scale , rotation и translation . Эти преобразования будут применены к отдельным объектам. Добавить новые объекты в группу и удалить их легко с помощью таких методов, как add() и remove() .

Вы можете определить как линейные, так и радиальные градиенты в Two.js. Определение градиента не означает, что он будет автоматически отображаться на экране, но он будет доступен для использования при настройке значений fill или stroke различных объектов.

Вы можете определить линейный градиент, используя two.makeLinearGradient(x1, y1, x2, y2, stops) . Значения x1 и y1 определяют координаты начала градиента. Аналогично, значения x2 и y2 определяют координаты конца градиента. Параметр Two.Stop является массивом экземпляров Two.Stop . Они определяют цвета каждой части массива и то, где каждый цвет переходит в следующий. Они могут быть определены с использованием new Two.Stop(offset, color, opacity) , где offset определяет точку на градиенте, где этот конкретный цвет должен быть полностью отображен. Параметр color определяет цвет градиента в конкретной точке. Вы можете использовать любые допустимые цветовые представления CSS в качестве значения. Наконец, параметр opacity определяет непрозрачность цвета. Непрозрачность является необязательной, и она может иметь любое значение от 0 до 1.

Вы можете определить радиальные градиенты аналогичным образом, используя two.makeRadialGradient(x, y, radius, stops, fx, fy) . В этом случае значения x и y определяют центр градиента. Параметр radius указывает, насколько далеко должен простираться градиент. Вы также можете передать массив остановок этому методу, чтобы установить цветовую композицию градиентов. Параметры fx и fy являются необязательными, и их можно использовать для указания фокусного положения для градиента.

Проверьте некоторые из типов градиента и их код в CodePen ниже.

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

Two.js также позволяет писать текст в области рисования и обновлять его позже в соответствии с вашими потребностями. Это требует использования метода two.makeText(message, x, y, styles) . Из названия параметров может быть видно, что message — это фактический текст, который вы хотите написать. Параметры x и y являются координатами точки, которая будет служить центром для написания текста. Параметр styles — это объект, который можно использовать для установки значений большого набора свойств.

Вы можете использовать стили для установки значений свойств, таких как family шрифтов, size и alignment . Вы также можете указать значение таких свойств, как fill , stroke , opacity , rotation , scale и translation .

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var centerX = window.innerWidth / 2;
var centerY = window.innerHeight / 2;
 
var elem = document.getElementById(«atoms»);
 
var elementNames = [
  «»,
  «Hydrogen»,
  «Helium»,
  «Lithium»,
  «Beryllium»,
  «Boron»,
  «Carbon»,
  «Nitrogen»,
  «Oxygen»,
  «Fluorine»,
  «Neon»
];
 
var styles = {
  alignment: «center»,
  size: 36,
  family: «Lato»
};
 
var nucleusCount = 10;
var nucleusArray = Array();
 
var electronCount = 10;
var electronArray = Array();
 
function intRange(min, max) {
  return Math.random() * (max — min) + min;
}

Приведенный выше код хранит координаты центра нашего окна в переменных centerX и centerY . Они будут использованы позже, чтобы поместить наш атом в центр. Массив elementNames содержит имена первых десяти элементов периодической таблицы. Индекс каждого имени соответствует количеству электронов и протонов этого элемента и начинается с пустой строки. Объект styles содержит свойства для стилизации текстового объекта.

Мы также определили функцию intRange() чтобы получить случайное целочисленное значение в данных экстремумах.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var two = new Two({ fullscreen: true }).appendTo(elem);
 
var protonColor = two.makeRadialGradient(
  0,
  0,
  15,
  new Two.Stop(0, «red», 1),
  new Two.Stop(1, «black», 1)
);
 
var neutronColor = two.makeRadialGradient(
  0,
  0,
  15,
  new Two.Stop(0, «blue», 1),
  new Two.Stop(1, «black», 1)
);
 
for (i = 0; i < nucleusCount; i++) {
  nucleusArray.push(two.makeCircle(intRange(-10, 10), intRange(-10, 10), 8));
}
 
nucleusArray.forEach(function(nucleus, index) {
  if (index % 2 == 0) {
    nucleus.fill = protonColor;
  }
  if (index % 2 == 1) {
    nucleus.fill = neutronColor;
  }
  nucleus.noStroke();
});

Это создает экземпляр Two и определяет два радиальных градиента. Красный / черный радиальные градиенты будут представлять протоны, а синий / черный градиенты будут представлять нейтроны.

Мы использовали intRange() чтобы поместить все эти нейтроны и протоны в пределах 20 пикселей друг от друга. Метод makeCircle() также устанавливает радиус этих протонов и нейтронов в 10 пикселей. После этого мы перебираем nucleusArray и nucleusArray заполняем каждый круг различным градиентом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
for (var i = 0; i < 10; i++) {
  if (i < 2) {
    var shellRadius = 50;
    var angle = i * Math.PI;
    electronArray.push(
      two.makeCircle(
        Math.cos(angle) * shellRadius,
        Math.sin(angle) * shellRadius,
        5
      )
    );
  }
  if (i >= 2 && i < 10) {
    var shellRadius = 80;
    var angle = (i — 2) * Math.PI / 4;
    electronArray.push(
      two.makeCircle(
        Math.cos(angle) * shellRadius,
        Math.sin(angle) * shellRadius,
        5
      )
    );
  }
}

Поместить нейтроны и протоны внутри ядра было легко. Однако правильное размещение электронов на одинаковом расстоянии потребует немного математики. Мы используем переменную shellRadius для указания расстояния различных электронных оболочек от ядра. Целый круг охватывает угол, равный 2 пи радианам. Мы можем размещать разные электроны равномерно, равномерно распределяя 2 пи радиана между ними.

Функции Math.cos() и Math.sin() используются для разделения вертикальной и горизонтальной составляющих вектора положения различных электронов на основе их угла.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
var orbitA = two.makeCircle(centerX, centerY, 50);
orbitA.fill = «transparent»;
orbitA.linewidth = 2;
orbitA.stroke = «rgba(0, 0, 0, 0.1)»;
 
var orbitB = two.makeCircle(centerX, centerY, 80);
orbitB.fill = «transparent»;
orbitB.linewidth = 2;
orbitB.stroke = «rgba(0, 0, 0, 0.1)»;
 
var groupElectronA = two.makeGroup(electronArray.slice(0, 2));
groupElectronA.translation.set(centerX, centerY);
groupElectronA.fill = «orange»;
groupElectronA.linewidth = 1;
 
var groupElectronB = two.makeGroup(electronArray.slice(2, 10));
groupElectronB.translation.set(centerX, centerY);
groupElectronB.fill = «yellow»;
groupElectronB.linewidth = 1;
 
var groupNucleus = two.makeGroup(nucleusArray);
groupNucleus.translation.set(centerX, centerY);

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
two
  .bind(«update», function(frameCount) {
    groupElectronA.rotation += 0.025 * Math.PI;
    groupElectronB.rotation += 0.005 * Math.PI;
    groupNucleus.rotation -= 0.05;
  })
  .play();
 
var text = two.makeText(«», centerX, 100, styles);
 
nucleusArray.forEach(function(nucleus, index) {
  nucleus.opacity = 0;
});
 
electronArray.forEach(function(electron, index) {
  electron.opacity = 0;
});

Эта часть кода устанавливает непрозрачность отдельных электронов и протонов в ноль. Он также говорит Two.js вращать электроны и протоны с определенной скоростью.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
visible = 0;
 
document.addEventListener(«click», function(event) {
  if (visible < nucleusArray.length) {
    nucleusArray[visible].opacity = 1;
    electronArray[visible].opacity = 1;
    visible++;
    text.value = elementNames[visible];
  }
  else {
    nucleusArray.forEach(el => el.opacity=0);
    electronArray.forEach(el => el.opacity=0);
    visible = 0;
    text.value = elementNames[0];
  }
});

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

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

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

Как видите, создавать анимированную 2D-графику очень просто, используя Two.js. Целью этого поста было помочь вам быстро начать работу, поэтому мы рассмотрели только основы. Тем не менее, вы должны прочитать официальную документацию, чтобы узнать больше о библиотеке!