CSS переходы, трансформации и анимации — Перспектива

CSS переходы, трансформации и анимации - Перспектива

От автора: В этой статье из серии статей, посвященных CSS переходам, трансформациям и анимациям, мы рассмотрим на примерах (включая 3D куб) CSS3 свойство perspective.

скачать исходники

Это вторая часть из серии обучающих статей, посвященных практическому применению CSS переходов, трансформаций и анимаций. В данной обучающей статье мы подробно разберем перспективу в CSS3 и случаи ее применения для улучшения пользовательского опыта взаимодействия.

Что такое перспектива?

В контексте двумерного мира перспектива дает пользователям иллюзию глубины объекта, ширины, высоты и позиции относительно другого объекта, если смотреть на объект с определенной точки зрения. Перспектива позволяет художникам создавать пейзажи, глядя на которые создается впечатление, что они уходят «внутрь» холста, или рисовать на улице здания разных размеров, которые «уходят» от нашего взгляда. На двумерной плоскости у объектов также есть точка схода, в которой «растворяется» глубина объекта. Давайте проиллюстрируем это на простой диаграмме:

На данной диаграмме показаны три объекта (прямоугольники) на двумерной плоскости. Когда прямоугольники перемещаются по плоскости, то линии перспективы (лучи) могут быть проведены к точке схода, и тогда мы получим трехмерные объекты. А поскольку Веб отображается на двумерных поверхностях (т.е. экранах устройств), то перспектива может помочь нам создать похожую глубину. В мире Веба и CSS3 трансформаций, перспектива может быть определена следующим образом (определение с сайта MDN):

CSS свойство perspective определяет расстояние между плоскостью z = 0 и пользователем, чтобы дать 3D-позиционированному элементу некоторую перспективу. Каждый 3D-элемент с z > 0, становится больше, а каждый 3D-элемент с z < 0 — меньше. Сила эффекта определяется значением данного свойства.

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

Демо-пример № 1 – Базовая перспектива

Давайте возьмем очень простую фигуру – квадрат – и используем свойства перспективы, чтобы придать ей немного глубины. Для первых демо-примеров я буду использовать некоторые вспомогательные классы, чтобы отразить следующие диапазоны:

свойство perspective не задано

свойство perspective со значением 100px

свойство perspective со значением 200px

свойство perspective-origin в значении [0, 0]

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

<div class="perspective-container perspective--none">
  <span class="surface square">
    square
  </span>
</div>

<div class="perspective-container perspective--200">
  <span class="surface square">
    square
  </span>
</div>

<div class="perspective-container perspective--100 perspective-origin--00">
  <span class="surface square">
    square
  </span>
</div>

Давайте теперь применим необходимые CSS свойства перспективы:

.perspective-container {
  background-color: #eee;
}

.perspective--none {
  /**/
}

.perspective--100 {
  perspective: 100px;
}

.perspective--200 {
  perspective: 200px;
}

.perspective-origin--00 {
  perspective-origin: 0 0;
}

.surface {
  display: block;
  text-align: center;
  width: 100%;
  height: 100%;
  color: #fff;
  background-color: rgb(55,124,255);
  font-size: 18px;
  line-height: 200px;
}

Если мы обновим нашу страницу в браузере, то увидим три одинаковых квадрата. Почему? Потому что ни один из наших трех объектов не был в действительности перемещен на плоскости. Чтобы увидеть, как свойства перспективы влияют на наши объекты, давайте переместим их на плоскости по оси Z, используя свойство transform. Мы добавим следующий CSS к нашему классу .surface, который управляет представлением наших объектов:

.surface {
  transform: translateZ(-50px);
}

Теперь мы можем увидеть три разных результата:

Первый объект остался неизменным, потому что без указания каких-либо правил для перспективы перемещение по оси Z (т.е. в и из экрана) не даст никаких изменений в плане глубины.

Второй объект немного переместился внутрь экрана, поскольку мы указали свойство perspective равное 200px. Помните, что, по определению, свойства перспективы устанавливают расстояние между плоскостью z=0 и пользователем.

Третий объект кажется еще меньше. Он переместился в верхний левый угол родительского контейнера. Это произошло потому, что мы установили свойство perspective-origin именно для родительского контейнера.

Демо-пример № 2 – Вращение фигур в перспективе

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

На этот раз у нас есть те же три квадрата, но мы будем вращать их по оси Y, чтобы они поворачивались «внутрь» экрана. Мы будем использовать CSS эффект перехода вместе с псевдо-классом :hover, чтобы анимировать то, как свойства перспективы влияют на вращение. Вот разметка:

<div class="perspective-container perspective--none">
  <span class="surface-2">
    square
  </span>
</div>

<div class="perspective-container perspective--400">
  <span class="surface-2">
    square
  </span>
</div>

<div class="perspective-container perspective--400 perspective-origin--00">
  <span class="surface-2">
    square
  </span>
</div>

На этот раз я добавил вспомогательный класс со значением 400px:

.perspective--400 {
  perspective: 400px;
}

Наконец, давайте посмотрим на CSS для нашей новой фигуры, который прописан в классе surface-2:

.surface-2 {
  display: block;
  text-align: center;
  width: 100%;
  height: 100%;
  color: #fff;
  background-color: rgb(55,124,255);
  font-size: 24px;
  line-height: 200px;
  transition: transform 1s;
}

.surface-2:hover {
  transform: rotateY(180deg);
}

При наведении мы получаем три разных результата:

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

Когда мы устанавливаем перспективу со значением 400px, мы уже видим, что второй объект вращается, «заглядывая» и «выглядывая» из экрана. А все благодаря перспективе.

А установив для третьего объекта перспективу со значением 400px и исходное положение со значением [0,0] мы достигаем похожего эффекта (как и со вторым объектом), но только уже отталкиваясь от исходного положения.

Демо-пример № 3 – 3D куб в различных исходных положениях

А теперь мы будем создавать нечто клевое. Мы собираемся создать куб (с шестью сторонами), используя CSS3 трансформации, и зададим для данного куба глубину с помощью перспективы. Мы также настроим систему управления, чтобы мы могли «на лету» изменять свойства перспективы, чтобы по-настоящему прочувствовать, насколько сильное влияние оказывает использование перспективы на конечный результат.

Мы будем строить наш куб, используя 6 элементов span внутри родительского элемента div с классом cube. Каждый элемент span будет представлять отдельную сторону куба. А сам куб будет находиться внутри блока-обертки, для которого мы будем задавать свойства перспективы. Вот такая разметка у нас получилась:

<div id="wrap" class="wrap">
  <div class="cube">
    <span class="face front">front</span>
    <span class="face back">back</span>
    <span class="face top">top</span>
    <span class="face bottom">bottom</span>
    <span class="face left">left</span>
    <span class="face right">right</span>
  </div>
</div>

Мы зададим некоторые начальные настройки для блока-обертки. Контейнер для куба будет иметь относительное позиционирование, чтобы каждая из сторон куба могла быть абсолютно спозиционирована внутри контейнера и соответствующим образом изменена. Если нам нужно получить куб, у которого длина каждой стороны будет 200px, наш CSS будет следующим:

.wrap {
  perspective: 500px;
  perspective-origin: 50% 50%;
}

.cube {
  position: relative;
  margin: 100px auto;
  width: 200px;
  height: 200px;
  transform-style: preserve-3d;
}

Обратите внимание на то, что я изначально задал для свойства perspective значение 500px, а для свойства perspective-origin — 50% 50%. Это изначально создаст нам некоторую глубину для работы, чтобы мы могли увидеть перемещение трансформированных элементов на плоскости. Запомните, что без перспективы трансформированные объекты не получат той трехмерной глубины, к которой мы стремимся. Свойство perspective-origin является необязательным, т.к. я уже указал значение по умолчанию (это центр контейнера), но я включил его здесь просто для повторения.

Давайте теперь изучим стороны куба. Прежде всего каждая сторона должна быть абсолютно спозиционирована, и иметь ширину и высоту в 200px. В целях визуализации я также добавлю немного внутренних теней для каждой стороны. Вот как выглядит базовый CSS для сторон куба:

.face {
  display: block;
  position: absolute;
  top: 0; left: 0;
  width: 200px;
  height: 200px;
  color: #666;
  font-size: 18px;
  text-align: center;
  line-height: 200px;
  box-shadow: inset 0 0 4px rgba(0,0,0,0.5);
}

А теперь давайте посмотрим на каждую сторону в отдельности. Мы установили следующие размеры для нашего куба: 200 x 200 x 200. Но в целом нам нужно добавить немного глубины. Поэтому давайте пододвинем к нам лицевую сторону куба на 100px, а обратную сторону, наоборот, отодвинем. И теперь мы получим идеальный квадрат размером 200px в центре плоскости. Обратная сторона куба также должна быть повернута на 180 градусов, чтобы она была отображена наружу. Вот наш CSS:

.front {
  transform: translateZ(100px);
}

.back {
  transform: translateZ(-100px) rotateY(-180deg);
}

Теперь давайте посмотрим на левую и правую стороны. Левую сторону нужно переместить влево на 100px, затем повернуть на –90 градусов по оси Y. С правой стороной нужно проделать обратные действия. Следующие правила расставят их по местам:

.left {
  transform: translateX(-100px) rotateY(-90deg);
}

.right {
  transform: translateX(100px) rotateY(90deg);
}

И теперь давайте посмотрим на верхнюю и нижнюю стороны. Верхнюю сторону нужно поднять на 100px и повернуть по оси X на 90 градусов, а с нижней стороной все наоборот. Следующие правила помогут расположить их нужным образом:

.top {
  transform: translateY(-100px) rotateX(90deg);
}

.bottom {
  transform: translateY(100px) rotateX(-90deg);
}

И вот мы получили наш CSS куб, используя трансформации и перспективу! А сейчас давайте добавим некоторые элементы управления, которые позволят нам изменять «на лету» свойства перспективы. Я буду использовать элемент range и размещу три таких элемента, чтобы управлять настройками. Вот наша разметка:

<h3 class="sub-title">Perspective</h3>
0 <input id="p" type="range" min="0" max="1000" value="500" step="1"> 1000px
        
<h3 class="sub-title">Perspective Origin X</h3>
-1000px <input id="pX" type="range" min="-1000" max="1000" value="100" step="1"> 1000px

<h3 class="sub-title">Perspective Origin Y</h3>
-1000px <input id="pY" type="range" min="-1000" max="1000" value="100" step="1"> 1000px

А вот и немного JavaScript, который позволит нам создать небольшой интересный демо-пример:

(function() {

  "use strict";

  var wrap = document.getElementById("wrap");
  var p = document.getElementById("p");
  var pX = document.getElementById("pX");
  var pY = document.getElementById("pY");
  var pVal;
  var xVal;
  var yVal;

  p.addEventListener( "input", function() {
    pVal = p.value + "px";
    wrap.style.perspective = pVal;
  });

  pX.addEventListener( "input", function() {
    xVal = pX.value + "px";
    yVal = pY.value + "px";
    wrap.style.perspectiveOrigin = xVal + " " + yVal;
  });

  pY.addEventListener( "input", function() {
    xVal = pX.value + "px";
    yVal = pY.value + "px";
    wrap.style.perspectiveOrigin = xVal + " " + yVal;
  });

})();

Вот теперь у нас есть интерактивный демо-пример с 3D кубом, который создан благодаря CSS3 трансформациям и перспективе.

Демо-пример № 4 – Вращающиеся кубы

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

.rotate-x {
  animation: spinX 4s infinite linear;
}

.rotate-y {
  animation: spinY 4s infinite linear;
}

@keyframes spinX {
  from { transform: rotateX(0); }
  to { transform: rotateX(360deg); }
}

@keyframes spinY {
  from { transform: rotateY(0); }
  to { transform: rotateY(360deg); }
}

И мы можем добавить следующие классы для наших кубов:

<div id="cube" class="cube rotate-x">
  ...
</div>

<div id="cube" class="cube rotate-y">
  ...
</div>

Также обратите внимание на важность использования для куба свойства transform-style: preserve-3d. Это гарантирует нам то, что стороны куба будут оставаться в трехмерном пространстве, а не становиться плоскими при трансформациях.

Браузерная поддержка

Перспектива, переходы и анимации поддерживаются в браузере IE10 и выше, в то время как трансформации поддерживаются в IE9 и выше. В связи с этим очень легко будет использовать запасные решения. Я протестировал весь приведенный код в новых версиях браузеров Chrome, Safari и Firefox. В них можно спокойно реализовывать данные эффекты. Однако, убедитесь в том, что вы добавили все необходимые вендорные префиксы! Если вы будете скачивать zip-архив с исходниками по приведенным ссылкам, то там префиксы уже будут добавлены.

В заключение

Вот и подошла к концу данная обучающая статья! В ней мы подробно рассмотрели понятие перспективы в CSS3, а также некоторые другие возможности комбинирования перспективы с трансформациями, переходами и анимациями. Не забудьте посмотреть демо-примеры и скачать исходники по приведенным ссылкам. Если у вас есть какие-либо вопросы, замечания или отзывы, поделитесь ими в комментариях.

Автор: Nick Salloum

Источник: http://callmenick.com/

Редакция: Команда webformyself.

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки: , ,

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (1)

  1. Сергей

    А нельзя ли изменить вращение куба на обратное? Чтоб вращался в противоположную сторону.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree