Главная » Статьи » Как работает CSS perspective

Как работает CSS perspective

Как работает CSS perspective

От автора: как человек, который любит создавать CSS-анимацию, я использую один из наиболее мощных инструментов perspective. Хотя свойство perspective не поддерживает 3D-эффекты само по себе (поскольку базовые фигуры не могут иметь глубины), вы можете использовать свойство transform для перемещения и поворота объектов в 3D-пространстве (с осями X, Y и Z), а затем используйте perspective для контроля глубины.

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

Основы

Мы начнем с простого зеленого квадрата и переместим его по всем трем осям.

Хотя перемещение объекта по осям X и Y довольно просто, если мы переместим его по оси Z, это будет выглядеть так, как будто квадрат остается в точности таким же, и это потому, что когда объект движется по оси Z, анимация перемещает его ближе к нам, а затем дальше от нас, но размер (и расположение) квадрата остается прежним. Вот где в игру вступает свойство CSS perspective.

Хотя perspective не влияет на объект, когда он движется по осям X или Y, когда объект движется по оси Z, квадрат выглядит больше, когда он приближается к нам, и меньше, когда он отдаляется. Да, прямо как в «реальной» жизни. Тот же эффект возникает, когда мы вращаем объект:

Вращение квадрата по оси Z выглядит как обычное вращение, которое мы все знаем и любим, но когда мы вращаем квадрат по осям X или Y (без использования перспективы), это только выглядит так, будто квадрат становится меньше (или уже). Но когда мы добавляем perspective, мы видим, что когда квадрат вращается, более близкая сторона квадрата кажется больше, а дальнейшая сторона кажется меньше, и вращение выглядит так, как ожидалось.

Обратите внимание, что когда объект вращается по осям X или Y на 90 ° (или 270 °, 450 °, 630 ° и т. д.), он «исчезнет» из поля зрения. Опять же, это происходит потому, что мы не можем добавить глубину к объекту, и в этом положении ширина (или высота) квадрата фактически будет равна 0.

Значение perspective

Нам нужно установить свойство perspective со значением. Это значение устанавливает расстояние от плоскости объекта или, другими словами, силу перспективы. Чем больше значение, тем дальше вы от объекта; чем меньше значение, тем заметнее будет перспектива.

perspective-origin

Свойство perspective-origin определяет позицию, с которой вы «смотрите» на объект. Если исходная точка находится по центру (по умолчанию), а объект перемещается вправо, будет казаться, что вы смотрите на него слева (и наоборот).

Как вариант, вы можете оставить объект по центру и переместить perspective-origin. Когда исходная точка установлена сбоку, это как будто вы «смотрите» на объект с этой стороны. Чем больше значение, тем дальше он будет казаться.

transform

Хотя perspective и perspective-origin устанавливаются для родительского контейнера элемента и определяют положение точки схода (т.е. расстояние от плоскости объекта с позиции, с которой вы «смотрите» на объекте), положение объекта и вращение устанавливаются с помощью свойства transform, которое объявляется для самого объекта.

Если вы посмотрите на код предыдущего примера, где я переместил квадрат с одной стороны на другую, вы увидите, что я использовал функцию translateX() — что имеет смысл, поскольку я хотел, чтобы он двигался по оси X. Но обратите внимание на то, что он присваивается свойству transform. Функция — это тип преобразования, который применяется непосредственно к элементу, который мы хотим преобразовать, но ведет себя в соответствии с правилами перспективы, назначенными родительскому элементу.

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

При вращении объекта его система координат трансформируется вместе с объектом.

При перемещении объекта он перемещается относительно своей собственной системы координат (а не координат своего родителя).

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

Чтобы получить эффект, который я хотел достичь в предыдущей демонстрации, мне сначала нужно было переместить квадрат по оси X. Только тогда я мог его повернуть. Если бы это было сделано наоборот (сначала повернуть, а затем переместить), то результат был бы совершенно другим.

Чтобы подчеркнуть, насколько важен порядок значений для свойства transform, давайте рассмотрим пару простых примеров. Во-первых, простое двумерное (2D) преобразование двух квадратов, которые имеют одинаковые значения transform, но они объявлены в другом порядке:

То же самое, даже если мы вращаем квадраты по оси Y:

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

transform: translateX(100px) rotateY(90deg);

… будет иметь такой же эффект, как:

transform: rotateY(90deg) translate<strong>Z(100px);

Это потому, что в первой строке мы перемещали объект по оси X перед его вращением, но во второй строке мы повернули объект, изменили его координаты, а затем переместили его по оси Z. Тот же результат, разные значения.

Давайте рассмотрим что-нибудь поинтереснее

Конечно, квадраты — хороший способ объяснить общую концепцию перспективы, но мы действительно начинаем понимать, как работает перспектива, когда переходим на трехмерные (3D) фигуры. Давайте воспользуемся всем, что мы рассмотрели до сих пор, чтобы построить трехмерный куб.

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

<div class="container"> <div class="cube"> <div class="side front"></div> <div class="side back"></div> <div class="side left"></div> <div class="side right"></div> <div class="side top"></div> <div class="side bottom"></div> </div>
</div>

Сначала мы добавим перспективу родительскому элементу .container. Затем мы убедимся, что элемент .cube имеет стороны 200 пикселей и учитывает трехмерные преобразования. Я добавляю здесь несколько презентационных стилей, но ключевые свойства выделены.

/* The parent container, with perspective */
.container { width: 400px; height: 400px; border: 2px solid white; border-radius: 4px; display: flex; justify-content: center; align-items: center; perspective: 800px; perspective-origin: top right;
} /* The child element, with 3D tranforms preserved */
.cube { position: relative; width: 200px; height: 200px; transform-style: preserve-3d;
} /* The sides of the cube, absolutely positioned */
.side { position: absolute; width: 100%; height: 100%; opacity: 0.9; border: 2px solid white;
} /* Background colors for the cube's sides to help visualize the work */
.front { background-color: #d50000; }
.back { background-color: #aa00ff; } .left { background-color: #304ffe; }
.right { background-color: #0091ea; } .top { background-color: #00bfa5; }
.bottom { background-color: #64dd17; }

Преобразование сторон

С лицевой стороной проще всего. Сдвинем ее вперед на 100 пикселей:

.front { background-color: #d50000; transform: translateZ(100px);
}

Мы можем переместить обратную сторону куба назад, добавив translateZ(-100px). Другой способ сделать это — повернуть сторону на 180 градусов, а затем переместить ее вперед:

.back { background-color: #aa00ff; transform: translateZ(-100px);

 /* or */ /* transform: rotateY(180deg) translateZ(100px); */
}

Как и для задней стороны, есть несколько способов трансформировать левую и правую стороны:

.left { background-color: #304ffe; transform: rotateY(90deg) translateZ(100px);

 /* or */ /* transform: translateX(100px) rotateY(90deg); */
} .right { background-color: #0091ea; transform: rotateY(-90deg) translateZ(100px);

 /* or */ /* transform: translateX(-100px) rotateY(90deg); */
}

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

.top { background-color: #00Bfa5; transform: rotateX(90deg) translateZ(100px);

 /* or */ /* transform: translateY(-100px) rotateX(90deg); */
} .bottom { background-color: #64dd17; transform: rotateX(-90deg) translateZ(100px);

 /* or */ /* transform: translateY(100px) rotateX(90deg); */
}

Это дает нам трехмерный куб!

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

Давайте поговорим о transform-style

Мы собираемся добавить необычную анимацию к нашему кубу, но сначала поговорим о свойстве transform-style. Я добавил его ранее в общий CSS, но толком не объяснил, что это такое и для чего оно нужно. Свойство transform-style имеет два значения:

flat (по умолчанию)

preserve-3d

Когда мы устанавливаем значение preserve-3d, оно выполняет две важные вещи:

Оно сообщает, что стороны куба (дочерние элементы) должны располагаться в том же трехмерном пространстве, что и куб. Если не задано значение preserve-3d, устанавливается значение по умолчанию flat, и стороны выравниваются в плоскости куба. preserve-3d «копирует» перспективу куба на его дочерние элементы (стороны) и позволяет вращать только куб, поэтому нам не нужно анимировать каждую сторону отдельно.

Оно отображает дочерние элементы в соответствии с их положением в трехмерном пространстве, независимо от их места в DOM.

В этом примере три квадрата — зеленый, красный и синий. Зеленый квадрат имеет значение translateZ 100 пикселей, что означает, что он находится перед другими квадратами. Синий квадрат имеет значение translateZ -100 пикселей, что означает, что он находится позади других квадратов.

Но в DOM порядок квадратов следующий: зеленый, красный, синий. Следовательно, когда для transform-style установлено значение Flat (или не установлено вообще), синий квадрат появится спереди, а зеленый квадрат будет сзади, потому что это порядок DOM. Но если мы установим для transform-style значение preserve-3d, он будет отображаться в соответствии со своим положением в трехмерном пространстве. В результате зеленый квадрат будет спереди, а синий — сзади.

Анимация

Теперь давайте анимируем куб! А чтобы было интереснее, мы добавим анимацию по всем трем осям. Сначала мы добавим свойство animation для .cube. Оно пока ничего не сделает, так как мы не определили ключевые кадры анимации, но оно заработает, когда мы это сделаем.

animation: cubeRotate 10s linear infinite;

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

@keyframes cubeRotate { from { transform: rotateY(0deg) rotateX(720deg) rotateZ(0deg); } to { transform: rotateY(360deg) rotateX(0deg) rotateZ(360deg); }
}

Именно свойство perspective действительно придает анимации такую глубину, как будто мы видим, как куб катится влево и вправо, а также вперед и назад.

Но до этого значение свойства perspective было постоянным, как и значение perspective-origin. Посмотрим, как изменение этих значений влияет на внешний вид куба.

Я добавил в этот пример три ползунка, чтобы увидеть, как разные значения влияют на перспективу куба:

Левый ползунок устанавливает значение свойства perspective. Помните, что это значение устанавливает расстояние от плоскости объекта, поэтому чем меньше значение, тем заметнее будет эффект перспективы.

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

Обратите внимание, что во время анимации эти изменения могут быть менее заметными, поскольку сам куб вращается, но вы можете легко отключить анимацию, нажав кнопку «Запустить анимацию».

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

Что дальше?

Теперь, когда вы освоили основы свойства perspective, вы можете использовать свое воображение и креативность для создания 3D-объектов в своих собственных проектах, добавляя глубину кнопкам, меню, полям ввода и всему остальному, что вы хотите «оживить».

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

Автор: Amit Sheen

Источник: https://css-tricks.com

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