A-Frame — это фреймворк, который позволяет отображать 3D-контент на веб-сайте всего несколькими строками кода и даже делает его пригодным для использования в VR и AR. Вы можете построить свой 3D-мир из html и готовых компонентов, что очень упрощает начало работы.

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

  • Настройка нашей первой сцены
  • Добавление примитивов, текста, изображений и т. д.
  • Добавление 3D-моделей
  • Анимации
  • Свет и цвет
  • Интерактивность

Финальный глюк-проект

Вы можете посмотреть и сделать ремикс на финальный проект от глюка.

Если вы еще не знакомы с платформой глитч, вам может быть интересна и эта статья: Введение в глитч.

Добавление сценария A-Frame

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

<head>
  ...
  <script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
  ...
</head>

Настройка сцены

Первый элемент A-Frame, который нам нужен, — это ‹a-scene›. Это кронштейн для всех остальных элементов, которые мы добавим. Поэтому всегда следите за тем, чтобы все элементы, относящиеся к нашей 3D-сцене, находились внутри тегов ‹a-scene›.

<a-body>
  <a-scene>
  //everthing you want to see in 3D goes here
  </a-scene>
</a-body>

Мы можем модифицировать нашу сцену многими компонентами и параметрами. Например, для начала мы устанавливаем кремово-белый цвет фона. Вы видите, что параметры, относящиеся к сцене, установлены в пределах ‹›, а те, что нет, как и другие элементы между ‹a-scene› и ‹/a-scene›. В A-Frame все это называется Сущность-Компонент-Система.

<body>
  <a-scene background="color: #FFFAF6"></a-scene>
</body>

Получите больше информации об а-сцене из документации.

примитивы

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

<a-scene background="color: #FFFAF6">
  <a-plane
    position="0 0 -5"
    color="lightgreen"
    rotation="-90 0 0"
    scale="4 4 4"
  ></a-plane>
  <a-sphere
    color="#E75A87"
    radius="0.4"
    position="0.2 0.4 -3.5"
    opacity="0.8"
  ></a-sphere>
</a-scene>

Как видите, мы не только добавили плоскость и сферу, но и указали несколько параметров, таких как цвета и позиции. Вы можете использовать предопределенные цвета, такие как «красный», «синий», «светло-зеленый» и т. д., или шестнадцатеричные коды.

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

Текст

Далее мы добавляем текст в нашу сцену. Как и прежде, для этого есть готовый Элемент A-Frame.

<a-scene>
  ...
  <a-text
    value="INVISIBLE ROOM"
    position="2 4 -5"
    color="#323232"
    align="center"
  ></a-text>
  ...
</a-scene>

Изображения и текстуры

Конечно, вы также можете добавлять изображения в свою сцену. Они могут просто отображаться как поверхности в вашей сцене или как текстуры на ваших 3D-объектах. В любом случае, изображения должны быть загружены в первую очередь. Для этого мы добавляем в нашу сцену новый раздел, где мы можем предварительно загрузить все медиафайлы, которые мы хотим использовать позже в нашей сцене. Этот раздел заключен в ‹a-активы› и ‹/a-активы›. Для лучшего обзора мы вставляем этот раздел в самое начало нашей сцены.

Теперь мы загружаем изображение (например, png или .jpg) внутрь a-ассетов и используем его в качестве источника (src) для нашего a-изображения в сцене. Таким образом, мы можем заменить скучный текст нашим логотипом.

<a-scene>
  <a-assets>
    //here you can preload all media that is needed in the scene
    <img
       id="logo-img"
        src="https://cdn.glitch.global/40b7ed8c-5f85-49dd-afb5-d509594a8ac2/logo_invisibleroom_black%20(4).png?v=1683277762943"
    />
    ...
  </a-assets>
  ...    
  <a-image
     src="#logo-img"
     width="1.24"
     height="0.446"
     position="2 4 -5"
     scale="2 2 2"
   ></a-image>
  ...
</a-scene>

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

Мы загружаем вторую текстуру с радугой и устанавливаем ее как текстуру нашего самолета. Когда вы это сделаете, вы увидите, что текстура получает цвет, который вы ранее установили для плоскости, поэтому обязательно удалите цвет. Установив значение повторения на значение, отличное от «1 1», вы можете масштабировать текстуру вашего самолета.

<a-assets>
  ...
  <img
    id="rainbow-texture"
    src="https://cdn.glitch.global/40b7ed8c-5f85-49dd-afb5-d509594a8ac2/RainbowTexture_seamless.jpg?v=1683275893167"
  />
  ...
</a-assets>
...
<a-plane
  position="0 0 -5"
  rotation="-90 0 0"
  scale="4 4 4"
  repeat="2 2"
  src="#rainbow-texture"
></a-plane>
...

Совет. Если вы хотите придать текстуру 3D-объектам, ищите бесшовные текстуры, чтобы не было видно некрасивых переходов.

Видео/гифки

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

Мы хотим использовать не видео, а гифку в качестве текстуры нашей плоскости, чтобы придать радужной плоскости некоторое движение. Gif изначально не поддерживаются A-Frame, поэтому здесь необходимо выполнить еще несколько шагов. Но, к счастью, несколько лет назад компания mayognaise опубликовала шейдер на Github, который мы можем использовать.

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

<head>
  ...
  <script src="https://rawgit.com/mayognaise/aframe-gif-shader/master/dist/aframe-gif-shader.min.js"></script>
  ...
</head>
<a-plane
  position="0 0 -5"
  rotation="-90 0 0"
  scale="4 4 4"
  material="shader:gif;src:url(https://cdn.glitch.global/40b7ed8c-5f85-49dd-afb5-d509594a8ac2/rainbow.gif?v=1683280007314)"
></a-plane>

Ваш самолет теперь должен иметь движущийся градиент!

3D-модели (gltf/glb)

Чтобы добавить в сцену собственные 3D-модели, мы должны сначала загрузить их в наши a-ассеты. Вы можете использовать файлы glTF с окончанием .gltf или .glb. Мы используем Blender для создания и экспорта 3D-моделей для нашего проекта.

<a-assets>
  ...  
  <a-asset-item
    id="orange_cone"
    src="https://cdn.glitch.global/40b7ed8c-5f85-49dd-afb5-d509594a8ac2/Cone_orange_animated.glb?v=1683214533662"
  ></a-asset-item>
  ...
</a-assets>

Затем создайте элемент ‹a-gltf-model› и задайте ему обычные свойства, такие как положение, вращение и т. д.

<a-gltf-model
  src="#orange_cone"
  scale="0.9 0.9 0.9"
  position="1.5 0 -5"
></a-gltf-model>

Анимации

У нас есть два способа заставить 3D-объекты двигаться в A-Frame.

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

<a-sphere
  color=" #E75A87"
  radius="0.4"
  position="0.2 0.4 -3.5"
  animation="property: scale; to: 2 2 2; dur: 2000; easing:easeInOutQuad; loop: true;dir:alternate"
  opacity="0.8"
></a-sphere>

Добавив еще один параметр анимации и назвав его, например. animation__2 (важны два __), вы можете анимировать другое свойство вашего объекта.

<a-sphere
  color=" #E75A87"
  radius="0.4"
  position="0.2 0.4 -3.5"
  animation="property: scale; to: 2 2 2; dur: 2000; easing:easeInOutQuad; loop: true;dir:alternate"
  opacity="0.8"
></a-sphere>

Нам еще многое предстоит узнать об анимациях A-Frame и о том, как они могут облегчать и ослаблять.

Давайте перейдем ко второму способу заставить вещи двигаться: интегрированным анимациям. Эти анимации должны быть интегрированы в модели gltf. Не все модели gltf имеют встроенную анимацию, но, к счастью, у нашего оранжевого конуса она есть.

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

<head>
  ...
  <script src="https://cdn.jsdelivr.net/gh/c-frame/[email protected]/dist/aframe-extras.min.js"></script>
  ...
</head>

А затем просто добавьте animation-mixer в ‹a-gltf-model›. Вот и все.

<a-gltf-model
  animation-mixer
  src="#orange_cone"
  scale="0.9 0.9 0.9"
  position="1.5 0 -5"
></a-gltf-model>

Свет и цвета

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

<a-gltf-model
  animation-mixer
  src="#blue_cube"
  scale="0.8 0.8 0.8"
  position="-1.2 0.75 -6"
  rotation="0 40 0"
></a-gltf-model>

Затем мы возвращаемся к началу нашей сцены и устанавливаем некоторые значения в нашем рендерере. Для этого мы добавляем в нашу ‹а-сцену› компонент рендерер с соответствующими параметрами.

<a-scene
  background="color: #FFFAF6"
  renderer="antialias: true;
    colorManagement: true;
    physicallyCorrectLights: true;"
>
  ...
</a-scene>

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

<a-entity
  light="type:directional; castShadow:true; intensity:2"
  position="1 1 1"
></a-entity>

<a-light type="ambient" intensity="2"> </a-light>

Теперь вы видите, что сцена стала ярче, но теней по-прежнему нет. Для этого мы должны указать нашим 3D-объектам отбрасывать тени. Здесь мы покажем вам пример того, как вы можете добавить это к конусу.

<a-gltf-model
  shadow="cast: true"
  animation-mixer
  src="#orange_cone"
  scale="0.9 0.9 0.9"
  position="1.5 0 -5"
></a-gltf-model>

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

Интерактивность

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

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

<a-scene
  background="color: #FFFAF6"
  renderer="antialias: true;
                   colorManagement: true;
                   physicallyCorrectLights: true;"
  cursor="rayOrigin: mouse; fuse: true; fuseTimeout: 500"
>
...
</a-scene>

Затем мы добавляем компонент к элементу (розовая сфера), который мы хотим сделать кликабельным, но которого нет в A-Frame, потому что мы хотим сами запрограммировать его поведение. Так что мы можем сами придумать имя для этого компонента. Поскольку мы хотим изменить цвет на желтый, мы просто назовем его желтый при нажатии.

<a-sphere
  shadow="cast: true"
  color=" #E75A87"
  radius="0.4"
  position="0.2 0.4 -3.5"
  animation="property: scale; to: 2 2 2; dur: 2000; easing:easeInOutQuad; loop: true;dir:alternate"
  animation__2="property: position; to: 0.2 0.9 -3.5; dur: 2000; easing:easeInOutQuad; loop: true; dir:alternate"
  opacity="0.8"
  yellow-on-click
></a-sphere>

Теперь нам еще нужно зарегистрировать наш новый компонент и определить, что он должен делать. Для этого мы сначала создаем новый JavaScript-скрипт, т. е. файл, оканчивающийся на .js, и называем его просто script.js. Вы можете создать этот скрипт в глюке с левой стороны.

В этом скрипте мы пишем код для нашего компонента желтый при нажатии.

AFRAME.registerComponent("yellow-on-click", {
  init() {
    var isYellow = false;
    this.el.addEventListener("click", () => {
      if (!isYellow) {
        this.el.setAttribute("color", "#F4D634");
        isYellow = true;
      } else {
        this.el.setAttribute("color", "#E75A87");
        isYellow = false;
      }
    });
  },
});

Давайте пройдемся по коду строка за строкой.

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

Затем мы отмечаем в нашей переменной isYellow, что наша сфера в данный момент не желтая, установив для нее значение «false».

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

Если наш элемент сейчас не желтый (!isYellow), мы устанавливаем желтый цвет элемента (#F4D634) и значение true для нашей переменной isYellow, потому что наш элемент теперь желтый. Если нет, мы устанавливаем розовый цвет (#E75A87) и переменную isYellow в false. Таким образом, каждый щелчок приводит нас к другой ветке нашего блока if-else.

Вернемся к нашей сцене и попробуем!

Чтобы узнать больше о пользовательских компонентах в A-Frame, посмотрите здесь.

Посмотрите документацию!

Есть так много других вещей, которые вы можете делать с A-Frame. Взгляните на звук, например, небо или другие способы изменения материалов ваших 3D-объектов.

Наслаждайтесь обучением и игрой!