Статьи

Как использовать функции 2D-преобразования в CSS

Ниже приведен небольшой отрывок из новой книги Тиффани « Мастер CSS», 2-е издание .

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

Существует четыре основных функции двумерного преобразования: rotate , scale , skew и translate . Шесть других функций позволяют преобразовать элемент в одном измерении: scaleX и scaleY ; skewX и skewY ; и translateX и translateY .

rotate()

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

Фиолетовая коробка была повернута на 55 градусов от начальной позиции, показанной пунктирной линией

Функция rotate() принимает значения в угловых единицах. Угловые единицы определяются модулем «Значения и единицы измерения CSS» уровня 3 . Это могут быть градусы (градусы), rad (радианы), градусы (градианы) или единицы turn . Один полный оборот равен 360deg 6.28rad , 400grad 6.28rad , 400grad или 1 1turn .

Значения поворота, которые превышают одно вращение (скажем, 540deg или 1.5turn ), отображаются в соответствии с их 1.5turn значением, если они не анимированы или не переведены. Другими словами, 540 градусов отображается так же, как 180deg градусов (540 градусов минус 360 градусов), а 1.5turn — так же, как .5turn (1,5 — 1). Но переход или анимация от 0 0deg до 540deg или от 1turn до 1.5turn будет вращать элемент в полтора раза.

Функции 2D масштабирования: scale , scale scaleY и scaleY

С помощью функций масштабирования мы можем увеличить или уменьшить визуализированный размер элемента в X-измерении ( scaleX ), Y-измерении ( scaleY ) или в обоих ( scale ). Масштабирование показано ниже, где граница иллюстрирует исходные границы прямоугольника, а знак + обозначает его центральную точку.

Поле (слева) масштабируется в 2 раза (справа)

Каждая функция масштаба принимает множитель или коэффициент в качестве аргумента. Этот множитель может быть примерно любым положительным или отрицательным числом. Значения в процентах не поддерживаются. Положительные множители больше 1 увеличивают размер элемента. Например, scale(1.5) увеличивает размер элемента в направлениях X и Y в 1,5 раза. Положительные множители от 0 до 1 уменьшат размер элемента.

Значения меньше 0 также приведут к увеличению или уменьшению размера элемента и созданию преобразования отражения (отражения).

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

Использование scale(1) создает преобразование идентичности , что означает, что оно отображается на экране, как будто преобразование масштабирования не применялось. Использование scale(-1) не изменит нарисованный размер элемента, но отрицательное значение приведет к отражению элемента. Даже если элемент не выглядит преобразованным, он все равно запускает новый контекст стека и содержит блок.

Можно масштабировать размеры X и Y отдельно, используя функцию scale . Просто передайте ему два аргумента: scale(1.5, 2) . Первый аргумент масштабирует X-измерение; второй масштабирует Y-размерность. Мы могли бы, например, отразить объект вдоль оси X, используя scale(-1, 1) . Передача одного аргумента масштабирует оба измерения одним и тем же фактором.

Функции 2D-перевода: translateX , translateY и translate

Перевод элемента смещает его закрашенное положение от положения макета на указанное расстояние. Как и в случае с другими преобразованиями, трансляция элемента не меняет его offsetLeft или offsetTop . Это, однако, влияет на то, где оно визуально расположено на экране.

Каждая функция 2D-перевода — translateX , translateY и translate принимает длины или проценты для аргументов. Единицы длины включают пиксели ( px ), em , rem и единицы просмотра ( vw и vh ).

Функция translateX изменяет горизонтальную позицию рендеринга элемента. Если элемент расположен на нулевом transform: transitionX(50px) слева, transform: transitionX(50px) смещает свою визуализированную позицию на 50 пикселей вправо от своей начальной позиции. Точно так же translateY изменяет вертикальную позицию рендеринга элемента. Transform of transform: transitionY(50px) смещает элемент по вертикали на 50 пикселей.

С translate() мы можем сместить элемент по вертикали и горизонтали, используя одну функцию. Он принимает до двух аргументов: значение перевода X и значение перевода Y. На рисунке ниже показано влияние элемента со значением transform translate(120%, -50px) , где левый зеленый квадрат находится в исходном положении, а правый зеленый квадрат переводится на 120% по горизонтали и -50px по вертикали от его содержащий элемент (пунктирная граница).

Эффект наличия элемента со значением преобразования translate (120%, -50px)

Передача одного аргумента для translate является эквивалентом использования translateX ; значение перевода Y будет установлено на 0 . Использование translate() является более кратким вариантом. Применение translate(100px, 200px) эквивалентно translateX(100px) translateY(200px) .

Положительные значения перевода перемещают элемент вправо (для translateX ) или вниз (для translateY ). Отрицательные значения перемещают элемент влево ( translateX ) или вверх ( translateY ).

Переводы особенно хороши для перемещения предметов влево, вправо, вверх или вниз. Обновление значений свойств left , right , top и bottom заставляет браузер пересчитывать информацию макета для всего документа. Но преобразования рассчитываются после расчета макета. Они влияют на то, где элементы появляются на экране, но не на их фактические размеры. Да, странно думать о макете и рендеринге документа как об отдельных концепциях, но с точки зрения браузеров это так.

Свойства преобразования могут появиться в браузере рядом с вами

Последняя версия спецификации CSS Transforms добавляет свойства translate , rotate и scale в CSS. Свойства преобразования работают так же, как и соответствующие им функции преобразования, но значения разделяются пробелами, а не запятыми. Мы могли бы, например, выразить transform: rotate3d(1, 1, 1, 45deg) используя свойство rotate: 1 1 1 45deg . Аналогично, translate: 15% 10% 300px визуально совпадает с transform: translate3d(15%, 10%, 300px) и scale: 1.5 1.5 3 аналогично transform: scale3d(1.5, 1.5, 3) . С помощью этих свойств мы можем управлять преобразованиями вращения, перемещения или масштабирования отдельно от других преобразований.

На момент написания, поддержка браузером свойств преобразования все еще довольно скудна. Chrome и Samsung Интернет поддерживают их из коробки. В Firefox версии 60 и выше поддержка скрыта за флагом; посетите about: config и установите для layout.css.individual-transform.enabled значение true .

skew , skewX и skewY

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

Прямоугольник перекошен на 45 градусов вдоль его X-измерения

Функции перекоса — skew , skewX и skewY принимают большинство угловых единиц в качестве аргументов. Градусы, градианы и радианы являются действительными угловыми единицами для функций перекоса, в то время как единицы поворота, возможно, очевидно, не являются.

Функция skewX элемент в X или горизонтальном направлении (см. Изображение ниже). Он принимает один параметр, который снова должен быть угловой единицей. Положительные значения смещают элемент влево, а отрицательные значения смещают его вправо.

Левое изображение не преобразуется, а правое показывает эффект преобразования: skewX (30 градусов)

Точно так же, skewY сдвигает элемент в Y или вертикальном направлении. На изображении ниже показан эффект transform: skewY(30deg) . Точки справа от начала координат смещены вниз с положительными значениями. Отрицательные значения сдвигают эти точки вверх.

Опять же, левое изображение остается без преобразования, а правое изображение перекошено по вертикали на 30 градусов

Это подводит нас к функции skew . Функция skew требует один аргумент, но принимает до двух. Первый аргумент наклоняет элемент в направлении X, а второй — в направлении Y. Если указан только один аргумент, предполагается, что второе значение равно нулю, что делает его эквивалентным искажению только в направлении X. Другими словами, skew(45deg) отображает то же самое, что skewX(45deg) .

Матрица преобразования тока

До сих пор мы обсуждали функции преобразования отдельно, но их также можно комбинировать. Хотите масштабировать и вращать объект? Нет проблем: используйте список преобразования . Например:

 .rotatescale { transform: rotate(45deg) scale(2); } 

Это дает результаты, которые вы видите ниже.

Исходный элемент (слева) и после комбинированного преобразования вращения и масштабирования (справа)

Порядок имеет значение при использовании функций преобразования. Этот момент лучше показать, чем обсуждать, поэтому давайте рассмотрим пример для иллюстрации. Следующий CSS наклоняет и поворачивает элемент:

 .transformEl { transform: skew(10deg, 15deg) rotate(45deg); } 

Это дает нам результат, который вы видите ниже.

Элемент после преобразования перекоса (10 градусов, 15 градусов) rotate (45 градусов)

Что произойдет, если сначала повернуть элемент, а затем наклонить его?

 .transformEl { transform: rotate(45deg) skew(10deg, 15deg); } 

Эффект, показанный ниже, совершенно другой.

Элемент после того, как он был повернут, а затем перекошен

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

Умножение матриц и функции матриц

Матрица — это массив чисел или выражений, расположенных в прямоугольнике строк и столбцов. Все преобразования могут быть выражены с использованием матрицы 4 × 4, как показано ниже.

Матрица 4 × 4 для 3D преобразований

Эта матрица соответствует функции matrix3d , которая принимает 16 аргументов, по одному для каждого значения матрицы 4 × 4. Двумерные преобразования также могут быть выражены с использованием матрицы 3 × 3, как показано ниже.

Эта матрица 3 × 3 соответствует функции преобразования matrix . Функция matrix() принимает шесть параметров, по одному для значений от a до f .

Каждая функция преобразования может быть описана с использованием матрицы и функций matrix или matrix3d . На рисунке ниже показана матрица 4 × 4 для функции scale3d , где sx , sy и sz — коэффициенты масштабирования для размеров X, Y и Z соответственно.

Матрица масштабного преобразования 4 × 4

Когда мы объединяем преобразования — такие как transform: scale(2) translate(30px, 50px) — браузер умножает матрицы для каждой функции, чтобы создать новую матрицу. Эта новая матрица — это то, что применяется к элементу.

Но вот в чем заключается умножение матриц: оно не коммутативно. При простых значениях произведение 3 × 2 совпадает с 2 × 3. Однако в случае матриц произведение A × B не обязательно совпадает с произведением B × A. Давайте посмотрим на пример. Мы рассчитаем матричный продукт transform: scale(2) translate(30px, 50px) .

Наш элемент был масштабирован в два раза, а затем переведен на 60 пикселей по горизонтали и 100 пикселей по вертикали. Мы также можем выразить этот продукт, используя matrix функцию: transform: matrix(2, 0, 0, 2, 60, 100) . Теперь давайте переключим порядок этих преобразований, то есть transform: translate(30px, 50px) scale(2) . Результаты показаны ниже.

Произведение матриц для перевода (30px, 50px) и масштаба (2)

Обратите внимание, что наш объект все еще масштабируется в два раза, но здесь он переводится на 30 пикселей по горизонтали и 50 пикселей по вертикали. Выражается с помощью функции matrix , это transform: matrix(2, 0, 0, 2, 30, 50) .

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

 <div style="transform: skewX(25deg)"> <p style="transform: rotate(-15deg)"></p> </div> 

Это отображается так же:

 <div> <p style="transform: skewX(25deg) rotate(-15deg)"></p> </div> 

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