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

Ось Z в двухмерном пространстве

Браузер все рисует в двухмерном пространстве — на плоскости. Но при этому у него есть «слои»: вышележащий слой перекрывает нижележащий. Мы управляем взаимным расположением элементов на слоях в основном с помощью CSS-свойства z-index: можем указать, какой элемент отрисовать выше, а какой ниже.

Что касается трансформаций — тут нам доступны только две оси (X и Y). Как ни крути вышележащий элемент функцией rotate(), он не спрячется за нижележащим, не «пройдет сквозь него». Браузер никак не соотносит трансформации разных элементов по оси Z. Если что-то нарисовано выше, оно и будет выше.

Посмотрим на картинку:

В двухмерном пространстве всегда будет так, как изображено слева

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

Ось Z в трехмерном пространстве

Чтобы получить доступ к оси Z, используем свойство transform-style:

transform-style: preserve-3d;

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

Теперь нам доступны новые трансформации, которые в принципе были доступны и раньше, но особо не имели смысла, так как мы не видели, куда «уходит» трансформируемый элемент.

Возьмем для примера простую разметку:

<div class="stage">
  <div class="element light"></div>
  <div class="element dark"></div>
</div>

Оба дочерних элемента спозиционированы на одном и том же месте. Попробуем повернуть один из них относительно оси X:

.dark {
  transform: rotateX(60deg)
}

В двухмерном пространстве мы даже не поймем, что произошло. Блок просто стал меньше по высоте (если вы не понимаете, о чем речь, чуть ниже будет картинка).

Создадим трехмерное пространство:

.stage {
  transform-style: preserve-3d;
}

Стало лучше: теперь мы видим, что половина нашего темного блока теперь находится за светлым блоком — темный блок прошел сквозь светлый в процессе поворота.

А если добавить немножко перспективы, трансформация станет очевидна:

.dark {
  transform: perspective(700px) rotateX(60deg);
}

Функция perspective задает «глубину» оси Z. За счет этого создается эффект «уменьшения» более отдаленных элементов и «увеличения» более близких. Перспектива обязательно нужна для создания реалистичных трансформаций.

На картинке можно увидеть как выглядит поворот по оси X в двухмерном и трехмерном пространстве:

Эффект от rotateX(60deg) в двухмерном и трехмерном пространстве

See the Pen 3d transformations by FurryCat (@mohnatus-the-lessful) on CodePen.

Перемещение по оси Z

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

Чтобы разделить элементы на оси Z, используем функцию translateZ().

.dark {
  transform: translateZ(-100px); // движение назад (вглубь)
}

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

Чтобы было понятнее, добавим немного перспективы:

.dark {
  transform: perspective(700px) translateZ(-100px);
}

Темный блок стал меньше по размеру, так как для нас он находится «дальше».

Чтобы еще лучше понять, что произошло, повернем немного всю сцену целиком по оси Y:

.stage {
  transform: perspective(700px) rotateY(50deg);
}
Перемещение блока назад по оси Z (без перспективы и с перспективой)

See the Pen 3d transformations by FurryCat (@mohnatus-the-lessful) on CodePen.


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

0 комментариев

Оставить комментарий

*Доступные HTML-теги: a, abbr, blockquote, code, pre, del, i, em, strong, b, strike
*Не будет опубликован