Перейти к содержимому

Как наложить svg друг на друга

  • автор:

Как наложить два SVG друг на друга, но без CSS или HTML?

У меня есть две SVG картинки и я хочу, чтобы одна располагалась в другой. Я выяснил, что можно добавить один в другой через , как здесь. Но сложность в том, что, когда я так делаю, один SVG располагается на фоне, другой как надо на переднем плане, но первый вместо того, чтобы быть фоном для всего переднего плана, он остаётся маленьким в левом верхнем углу. Первый SVG выглядит так:

Второй выглядит так:

Второй должен служить фоном первому, но почему-то, если их объединить под получается вот так:

введите сюда описание изображения

Живое превью можно увидеть, если вставить код здесь. Я мало понимаю в векторных изображениях, просто хочу использовать итоговую картинку как favicon для сайта. Должно получиться что-то такое: Я пытался добавлять атрибуты ширины и высоты для , которые, видимо, неприменимы для этого, пробовал задать идентичный viewBox для каждого из SVG и добавить в , но тоже не получилось. Как можно объединить два SVG, чтобы получилось как на картинке выше, не используя HTML, CSS, JS и т.д. — используя только SVG?

Как с помощью CSS наложить элементы друг на друга

При разработке веб-дизайна часто нужно сделать так, чтобы два элемента перекрывались или полностью накладывались друг на друга. В CSS это можно реализовать с помощью свойства position и Grid.

Способ 1. Использование свойства Position

Свойство position со значением absolute разместит абсолютно позиционированный элемент на странице. В этом случае указывается позиция элемента относительно левого верхнего угла веб-страницы.

.child

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

.child < /* . */ position: absolute; top: 0; left: 0; >.parent

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

Parent

Child 1

Child 2

.child < position: absolute; top: 0; >.child-1 < left: 0; >.child-2 < left: 150px; >.parent

Способ 2. Использование CSS Grid

Еще одним способом наложения элементов друг на друга является использование CSS Grid. Но эта технология поддерживается не всеми старыми браузерами.

С помощью Grid мы можем разместить элемент внутри контейнера следующим образом:

.parent < display: grid; grid-template-columns: 250px 1fr; grid-template-rows: 150px 1fr; >.child < grid-area: 1 / 1 / 2 / 2; >

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

.parent < display: grid; grid-template-columns: 250px 1fr; grid-template-rows: 150px 1fr; >.child < grid-area: 1 / 1 / 2 / 2; >.child-2

Для облегчения позиционирования я создал CSS Grid Generator, который поможет вам визуально сконструировать необходимый макет.

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

Как в html css наложить две svg картинки одна на другую как на примере ?

Мы постоянно добавляем новый функционал в основной интерфейс проекта. К сожалению, старые браузеры не в состоянии качественно работать с современными программными продуктами. Для корректной работы используйте последние версии браузеров Chrome, Mozilla Firefox, Opera, Microsoft Edge или установите браузер Atom.

Трансформации для SVG-элементов

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

Как и HTML-элементами, SVG-элементами можно управлять при помощи функций для трансформации. Однако, далеко не всё работает с SVG-элементами так, как с HTML-элементами

Для начала, CSS-трансформации для SVG-элементов не работают в IE. Конечно, есть вариант с использованием SVG-атрибутов трансформации для IE, в случае, если нам нужно применять для наших элементов только 2D-трансформации.

Однако, в этом случае, все параметры для функций трансформаций представлены в виде чисел, что означает, что мы не можем управлять единицами измерения и комбинировать их. Например, мы не можем использовать значения в % для функций сдвига (хотя значения % всё равно бы не стали работать для CSS-трансформаций в Firefox, и не важно, говорим ли мы о значениях transform-origin или параметрах translate()), и все значения для поворота или угла наклона высчитываются в градусах, поэтому мы не можем применять другие единицы измерения, которые доступны в CSS.

Еще одна проблема — тот факт, что определение возможностей скриптом не справляется (чтение значения CSS-трансформации при помощи JS вернёт матрицу, эквивалентную трансформации, которую мы установили в нашей таблице стилей), поэтому нам нужен либо другой способ проверки для IE, либо нам надо повсеместно использовать атрибуты трансформации (что в каком-то смысле кажется более легким путем вообще)

Главная разница в работе между HTML- и SVG-элементами — локальная система координат элемента. У каждого элемента, будь то HTML- или SVG-элемент, есть такая система. Для HTML-элементов эта система координат начинается в точке 50% 50% элемента. Для SVG-элементов (если мы не применяли трансформации к элементу или его предкам в пределах элемента ) исходная точка находится в 0 0 SVG-холста. Это приведёт к разным результатам с трансформациями rotate , scale или skew , если точка 50% 50% SVG-элемента не совпадает с точкой 0 0 SVG-холста.

Чтобы лучше это понимать, давайте посмотрим, как работают функции трансформации.

Как работают функции трансформации

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

Сдвиг

Сдвиг перемещает все точки элемента в том же направлении и на ту же величину. Сдвиг сохраняет параллельность, углы и расстояния. Это можно интерпретировать, как сдвиг начальной точки системы координат элемента — когда это происходит, любой элемент, положение которого описывается относительно этой начальной точки (сам элемент и любые его потомки), тоже сдвигается. Его результат не зависит от положения системы координат.

svg-transforms-fig1

Рисунок 1: трансформация сдвига: HTML-элементы (слева) напротив SVG-элементов (справа)

На рисунке выше представлено сравнение примеров с HTML (слева) и SVG (справа). Полупрозрачные рисунки элементов — это их исходное положение (до применения сдвига). Трансформация сдвига перемещает элементы вместе с их системами координат, и это же произойдет с любыми потомками наших элементов, если таковые будут.

Как вы уже знаете, различие между двумя случаями — положение системы координат. В случае с HTML, начало координат находится в точке 50% 50% элемента. В случае с SVG начало координат располагается в точке 0 0 холста (если мы не применяли трансформации ни к каким возможным предкам элемента в пределах элемента ). Тем не менее, при сдвиге положение системы координат относительно элемента не влияет на конечное положение элемента.

Как для HTML-, так и для SVG-элементов, при использовании CSS-трансформации у нас есть три функции для сдвига, доступные для 2D: translateX(tx) , translateY(ty) и translate(tx[, ty]) . Первые две влияют только на направления x и y (как указано системой координат элемента), соответственно. Заметьте, что если другая трансформация применена до сдвига, то направления x и y , возможно, больше не будут горизонтальным и вертикальным, соответственно. Третья функция сдвига перемещает элемент на tx вдоль оси x и на ty вдоль оси y . Параметр ty необязательный, и если он не указан, по умолчанию он равен нулю.

SVG-элементы могут также перемещаться при помощи атрибутов для трансформации. В этом случае, у нас есть только функция translate(tx[ ty]) . Здесь значения могут разделяться пробелами, а не только запятыми, как в аналогичной функции CSS-трансформации. Поэтому в очень простом случае, когда 1 в пользовательской системе координат SVG равно 1px , это равнозначно 1px , следующие два способа сдвига SVG-элемента равнозначны:

rect < /* не работает в IE */ transform: translate(295px,115px); >

• применение атрибутов для SVG-атрибута для трансформации:

Заметьте: SVG-атрибут для трансформации и CSS-свойство для трансформации будут объединены.

Последовательные трансформации translate() можно складывать, это значит, что цепочки вида translate(tx1, ty1) translate(tx2, ty2) можно записывать как translate(tx1 + tx2, ty1 + ty2) . Заметьте, что это верно, если в цепочке трансформаций между ними не стоит трансформации другого типа. Обратный сдвиг translate(tx, ty) делается при помощи другого сдвига translate(-tx, -ty) .

Поворот

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

svg-transforms-fig2

Рисунок 2: базовая трансформация поворота: HTML-элементы (слева) напротив SVG-элементов (справа)

На рисунке выше представлено сравнение примеров с HTML (слева) и SVG (справа). Полупрозрачные рисунки элементов — это их исходное положение (до применения поворота). Поворот перемещает элементы и их системы координат вокруг фиксированного начала координат, и это же произойдет с любыми потомками наших элементов, если таковые будут.

В случае с HTML, начальная точка системы координат элемента находится в 50% 50% элемента, поэтому все поворачивается вокруг этой точки. Однако, в случае с SVG, исходная точка находится в 0 0 SVG-холста (если мы не применяли трансформации ни к каким возможным предкам элемента в пределах элемента ), в результате чего всё будет перемещаться вокруг этой точки.

Для CSS-трансформаций функция 2D-поворота довольно простая: только rotate(angle) . Значение angle может быть представлено в градусах ( deg ), радианах ( rad ), оборотах ( turn ) или градах ( grad ). Также мы можем использовать значение calc() (например, что-нибудь типа calc(.25turn — 30deg) ), но на данный момент это работает только в Chrome 38+/ Opera. Если вы используете положительное значение угла, тогда поворот будет идти по часовой стрелке (и наоборот, при отрицательном значении угла, поворот будет идти против часовой стрелки).

В случае с атрибутами для SVG-трансформации, функция поворота немного отличается — rotate(angle[ x y]) . Значение angle работает аналогичным с функцией CSS-трансформации способом (положительное значение означает поворот по часовой стрелке, отрицательное значение — против часовой), но значение градусов должно быть безрамерным. Необязательные безразмерные параметры x и y указывают координаты фиксированной точки, вокруг которой мы поворачиваем элемент (и его систему координат). Если они опущены, тогда фиксированной точкой будет начальная точка системы координат. Если указать только параметры angle и x , значение будет невалидным и трансформация не применится.

Как и в функции translate() , параметры могут разделяться пробелами или запятыми.

Заметьте, что наличие параметров x и y не означает, что начальная точка системы координат переместится в эту точку. Система координат, как и сам элемент (и любые потомки, если они есть) просто будут вращаться вокруг точки x y .

Это означает, что у нас есть два равнозначных способа поворота SVG-элемента (результат можно увидеть справа на предыдущем рисунке):

rect < /* не работает в IE */ transform: rotate(45deg); >

• применение атрибута для SVG-трансформации:

Также в CSS мы можем указать значение transform-origin , чтобы сымитировать применение параметров x и y . Значения длины указываются относительно системы координат элемента, а процентные значения — относительно самого элемента, поэтому они, кажется, идеальны для того, что мы хотели получить. Однако, нам надо учитывать две вещи.

Во-первых, CSS transform-origin и фиксированная точка, указанная в функции rotate() — не одно и тоже. В качестве очень простого примера, скажем, возьмем всего лишь поворот вокруг точки 50% 50% в SVG, не столь важно. Рассмотрим два случая:

rect < transform: rotate(45deg); transform-origin: 50% 50%; >

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

svg-transforms-fig3

Рисунок 3: вращение SVG-элемента вокруг установленной точки: применение CSS (слева) и атрибута для SVG-трансформации (справа)

Это показывает разницу между ними. При использовании CSS, система координат элемента сначала перемещается от точки 0 0 SVG-холста в точку 50% 50% элемента. Затем элемент поворачивается. При использовании атрибута для SVG-трансформации, элемент и его система координат просто поворачивается вокруг точки, указанной во втором и третьем аргументе функции rotate() , точки, координаты которой мы вычислили так, чтобы она находилась в точке 50% 50% элемента. Начальная точка системы координат элемента по-прежнему находится снаружи элемента, и эта начальная точка будет влиять на любые последующие трансформации, зависящие от неё.

Чтобы лучше это понять, давайте укажем другой поворот (сразу после первого), который поворачивает элемент на 45° в противоположном направлении:

rect < transform: rotate(45deg) rotate(-45deg); transform-origin: 50% 50%; >

svg-transforms-fig4

Рисунок 4: цепочка поворотов для SVG-элемента: CSS-трансформации (слева) и атрибут для SVG-трансформации (справа)

Как показано на рисунке выше, при использовании CSS-трансформации и установке transform-origin в 50% 50% , два поворота компенсируют друг друга, но при использовании SVG-атрибута transform , фиксированная точка, вокруг которой мы поворачиваем элемент, различается между двумя поворотами — она является точкой 50% 50% элемента для первого поворота и начальной точкой системы координат элемента для второго. В этой ситуации поворот в обратную сторону делается легко; просто используйте rotate(-45 140 105) вместо rotate(-45) .

Однако, это не отменяет того факта, что у нас есть только один transform-origin (поскольку у системы координат элемента есть только одна начальная точка), но при использовании SVG-атрибута transform , мы можем применять множественные повороты, каждый из которых поворачивает элемент вокруг разной точки. Поэтому, если мы хотим сначала повернуть наш прямоугольник на 90° вокруг его нижнего правого угла, а затем ещё на 90° вокруг его верхнего правого угла, то это легко сделать при помощи атрибута для SVG-трансформации — мы просто указываем разные фиксированные точки для каждого поворота.

svg-transforms-fig5

Рисунок 5: цепочка поворотов вокруг разных фиксированных точек (атрибут для SVG-трансформации)

Но как нам получить тот же самый эффект при помощи CSS-трансформаций? Это легко сделать для первого поворота, поскольку можно установить transform-origin в right bottom , но как быть со вторым поворотом? Если дописать его в CSS-правиле после первого, то он просто повернёт элемент ещё на 90° вокруг той же самой точки ( right bottom ).

Нам нужно три сцепленных трансформации, для того, чтобы поворот элемента вокруг фиксированной точки не зависел от того, где находится его transform-origin . Во-первых, это трансформация translate(x, y) , которая переместит начальную точку системы координат элемента таким образом, чтобы она совпадала с фиксированной точкой, вокруг которой мы хотим всё поворачивать. Во-вторых, это сам поворот. И наконец, в-третьих, это translate(-x, -y) — противоположность первому сдвигу.

В этом случае наш код мог бы быть таким:

rect < transform-origin:right bottom; /* или 100% 100%, что одно и тоже */ transform: rotate(90deg) translate(0, -100%) /* идём от нижнего правого до верхнего правого края */ rotate(90deg) translate(0, 100%); >

На нижнем рисунке показано, как это работает, шаг за шагом:

Рисунок 6: иллюстрация того, как работает цепочка CSS-трансформаций

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

Масштабирование

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

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

Результат трансформации масштаба зависит от положения начальной точки системы координат. Две трансформации масштабирования с одним и тем же коэффициентом на одном и том же элементе дадут разный результат при разном положении начала координат.

svg-transforms-fig7

Рисунок 7: трансформация масштабирования: HTML-элементы (слева) и SVG-элементы (справа)

На рисунке выше представлено сравнение примеров с HTML (слева) и SVG (справа). В обоих случаях мы масштабируем элемент, используя коэффициент масштабирования sx вдоль оси x и sy вдоль оси y . Разница в положении начальной точки системы координат элемента, которая в случае с HTML находится в точке 50% 50% элемента, а в случае с SVG в точке 0 0 SVG-холста (если мы не применяли трансформации ни к каким возможным предкам элемента в пределах элемента ).

При использовании CSS-трансформаций у нас есть три функции масштабирования, которые доступны для 2D-трансформаций: scale(sx[, sy]) , scaleX(sx) и scaleY(sy) . Первая функция масштабирует элемент на sx вдоль оси x и на sy вдоль оси y . Параметр sy необязательный, и если он не указан, то предполагается, что он равен sx , делая таким образом масштабирование одинаковым во всех направлениях. sx и sy всегда являются безразмерными значениями. Другие две функции действуют только в направлениях x и y (как указано системой координат элемента), соответственно. scaleX(sx) равнозначно scale(sx, 1) или просто scale(sx) , а scaleY(sy) равнозначно scale(1, sy) . Если другая трансформация применяется до масштабирования, направления x и y могут уже не быть горизонтальным и вертикальным, соответственно.

В случае с атрибутами для SVG-трансформации у нас есть только функция scale(sx[ sy]) . Снова, значения здесь могут разделяться пробелами, а не только запятыми, как в аналогичной функции CSS-трансформации.

Поэтому для SVG-элементов следующие два метода масштабирования равнозначны:

rect < /* не работает в IE */ transform: scale(2, 1.5); >

• применение атрибута для SVG-трансформации

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

С CSS-трансформациями у нас есть выбор: либо задать нашему SVG-элементу правильный transform-origin , либо добавить в цепочку трансформаций сдвиги до и после масштабирования — сначала мы сдвигаем систему координат так, что ее начало оказывается в точке 50% 50% нашего SVG-элемента, затем масштабируем, а затем обращаем первый сдвиг. С SVG-атрибутом transform у нас есть только вариант с цепочкой трансформаций. Так что код для вышеописанного случая был бы таким:

• Применение CSS-трансформации при помощи transform-origin

rect < /* не работает в IE */ transform: scale(2, 1.5); /* не работает в Firefox, если мы только не заменим значения % на значения с абсолютной длиной */ transform-origin: 50% 50%; >

• Применение цепочки CSS-трансформаций

rect < /* не работает в IE */ transform: translate(140px, 105px) scale(2 1.5) translate(-140px, -105px); >

• Применение функций цепочки трансформаций в виде значения для атрибута SVG-трансформации

Следующий демо-пример иллюстрирует, как работает метод с цепочкой трансформаций (нажмите кнопку «воспроизведение» (►) для старта):

Что ещё нужно помнить о масштабировании — это что две последовательные трансформации scale() ( scale(sx1, sy1) scale(sx2, sy2) ) могут быть записаны как scale(sx1*sx2, sy1*sy2) , а обратная трансформация делается при помощи scale(1/sx1, 1/sy1) . Если все коэффициенты масштаба по модулю равны 1 , то такое масштабирование — само себе обратная трансформация.

Наклон

Наклон элемента вдоль оси смещает каждую из его точек (кроме тех, которые находятся точно на оси наклона) в этом направлении на ту величину, которая зависит от угла наклона и расстояния между этой точкой и осью наклона. Это значит, что изменяется только координата вдоль оси наклона, а координата вдоль другой оси остаётся неизменной. В отличие от поворота, наклон деформирует элемент, превращая квадраты в неравносторонние параллелограммы, а круги в эллипсы. Наклон не сохраняет углы (при наклоне на угол α 90-градусные углы прямоугольного элемента становятся 90° ± α ) или длина любого сегмента не параллельна оси наклона. Однако, площадь элемента сохраняется.

В отличие от сдвига или поворота, наклоны не складываются. Наклон элемента вдоль оси на угол α1 , а затем наклон снова вдоль той же оси на другой угол α2 — не то же самое, что наклон элемента вдоль этой оси на угол α1 + α2 .

Демо-пример ниже показывает, как работает наклон — изменяйте угол и/или ось, чтобы увидеть, как это влияет на исходный квадрат.

Угол наклона — это угол между конечным и исходным положением оси, которая изменяется после применения трансформации (а не оси, вдоль которой мы наклоняем элемент). Положительный угол наклона в интервале [0°, 90°] добавляет значение того же знака, что у неизменной координаты, к исходному значению меняющейся координаты, которая изменилась (координата вдоль угла наклона), а отрицательное значение в интервале [-90°, 0°] добавляет значение, знак которого является противоположным этой фиксированной координаты.

Если мы делаем наклон вдоль оси x , то для любой точки нашего элемента координата y этой точки остаётся такой же, а координата x изменяется на величину d в зависимости от угла наклона и от фиксированной координаты y (где-то на 15-й минуте этого доклада поясняется, как величина d может быть вычислена). Верхняя и нижняя стороны (и любой другой сегмент, параллельный оси x ) остаются той же длины, а левая и правая стороны становятся длиннее по мере увеличения угла наклона, уходя в бесконечность в случае угла ±90° . Как только это значение превышается, они начитают становиться короче, пока мы не получим угол в ±180° .

Заметьте, что результат наклона на угол в интервале (90°, 180°] равнозначен результату наклона на угол α — 180° > (который в конечном итоге оказался бы в интервале (-90°, 0°] ). Также результат наклона на угол в интервале (-180°, -90°] равнозначен результату наклона на угол — α + 180° (который в конечном итоге оказался бы в интервале [0°, 90°))

Если мы делаем наклон вдоль оси y , то координата x остаётся такой же для любой точки нашего элемента, а координата y изменяется на величину d в зависимости от угла наклона и от фиксированной координаты x . Правая и левая стороны (и любой другой сегмент, параллельный оси y ) остаются той же длины, а верхняя и нижняя стороны становятся длиннее по мере увеличения угла наклона, уходя в бесконечность в случае угла ±90° . Как только это значение превышается, они начитают становиться короче, пока мы не получим угол в ±180° .

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

svg-transforms-fig8

Рисунок 8: трансформация наклона: HTML-элементы (слева) и SVG-элементы (справа)

На рисунке выше представлено сравнение примеров с HTML (слева) и SVG (справа). В обоих случаях, мы наклоняем наши элементы вдоль оси x на тот же угол наклона. Разница в положении начальной точки системы координат элемента, которая в случае с HTML находится в точке 50% 50% элемента, а в случае с SVG в точке 0 0 SVG-холста (если мы не применяли трансформации ни к каким возможным предкам элемента в пределах элемента в случае с SVG).

Для простоты, давайте сосредоточимся на том, что случается только с одной точкой наших элементов: верхний правый угол. В обоих случаях координата y сохраняет своё положение — точка не двигается по вертикали, только по горизонтали. Однако, в случае HTML мы видим, что по горизонтали этот угол двигается влево (в отрицательном направлении оси x ), а в случае с SVG вправо. А нижний правый угол двигается вправо, по мере наклона, как в HTML, так и в случае с SVG. Итак, как это работает?

Ну, как упоминалось выше, при наклоне вдоль оси x , координата y любой точки остаётся такой же, хотя к исходной точке координаты x той же точки мы добавляем величину d , которая зависит от угла наклона и от фиксированной координаты y . Эта величина d совпадает по знаку с фиксированной координатой y , если угол наклона находится в интервале [0°, 90°] , и противоположна ей по знаку, если угол наклона находится в интервале [-90°, 0°] .

В обоих случаях наш угол 60° , поэтому дело решает знак координаты y верхнего правого угла. В случае с HTML начальная точка системы координат элемента находится в точке 50% 50% элемента, координата y верхнего правого угла элемента является отрицательной, поскольку ось y направлена вниз. Однако, в случае с SVG, где начальная точка системы координат элемента находится в точке 0 0 SVG-холста, координата y верхнего правого угла элемента положительна. Это означает, что в случае с HTML мы добавляем отрицательную величину к исходной точке координаты x верхнего правого угла, заставляя его двигаться влево, а в случае с SVG мы добавляем положительную величину к исходной координате x верхнего правого угла, заставляя его двигаться вправо.

Независимо от того, наклоняем ли мы SVG-элемент при помощи CSS-трансформаций или атрибута для SVG-трансформации, нам доступны две функции: skewX(angle) и skewY(angle) . Первая функция наклоняет элемент вдоль оси x , а вторая наклоняет его вдоль оси y .

В CSS-трансформациях значение angle указывается с единицей измерения. Оно может быть представлено в градусах ( deg ), радианах ( rad ), оборотах ( turn ), градах ( grad ) или даже в виде calc() , чтобы комбинировать любые эти единицы измерения (но имейте ввиду, что на данный момент calc() с единицами измерения для угла работает только в браузерах на движке Blink)

При наклоне элемента с помощью атрибута для SVG-трансформации наше значение angle всегда представляет безразмерное значение градусов.

Это означает, что у нас есть два равнозначных способа наклона SVG-элемента (результат можно видеть на предыдущем рисунке справа):

rect < transform: skewX(60deg); /* не работает в IE */ >

• использование атрибута для SVG-трансформации:

Если вы хотите получить тот же самый эффект, который мы получаем при применении аналогичной функции наклона для HTML-элемента, то для этого у нас есть три способа, как и при масштабировании:

• использование CSS-трансформации при помощи transform-origin

rect < /* не работает в IE */ transform: skewX(60deg); /* не работает в Firefox, если мы только не заменим значения % на значения с абсолютной длиной */ transform-origin: 50% 50%; >

• использование цепочки CSS-трансформаций

rect < /* не работает в IE */ transform: translate(140px, 105px) skewX(60deg) translate(-140px, -105px); >

• использование цепочки функций трансформации в виде значения атрибута для SVG-трансформации:

Следующий демо-пример иллюстрирует как работает «цепочный» метод:

Сокращение цепочки

Всё в порядке, цепочки трансформаций делают своё дело. Можно поворачивать, масштабировать и наклонять SVG-элементы, и они ведут себя так же, как вели бы и HTML-элементы при тех же самых трансформациях. А если мы применяем цепочку трансформаций в виде значения для SVG-атрибута, то у нас даже есть возможность получить желаемый результат в IE. Но это уродство! Неужели нет более простого способа сделать это?

Ну, если мы начнём с нашего SVG-прямоугольника, точка 50% 50% которого находится в точке 0 0 SVG-холста, то мы можем «вырезать» один сдвиг в нашей цепочке, сокращая наш код поворота:

Мы также могли бы избавиться от первого сдвига при помощи правильно подобранного атрибута viewBox для элемента , содержащего наш прямоугольник. У атрибута viewBox есть четыре значения, которые разделены пробелом. Первые два указывают координаты x и y верхнего левого угла SVG-холста в пользовательских единицах измерения, а другие две указывают его width и height в пользовательских единицах измерения. Если атрибут viewBox не указан, то координаты верхнего левого угла будут 0 0 .

Ниже можно увидеть разницу между элементом , у которого не указан viewBox , и элементом с viewBox=’-140 -105 280 210′ :

svg-transforms-fig9

Рисунок 9: Элемент , у которого не указан атрибут viewBox , и элемент с viewBox

Возвращаясь к нашему примеру, если мы установим viewBox так, чтобы точка 0 0 SVG-холста разместилась там, где у нас находится точка 50% 50% нашего прямоугольника, то наш код станет таким:

Практическое применение

Размещение точки 0 0 нашего SVG-холста и любого другого желаемого элемента прямо в середине облегчает работу с трансформациями, потому что в этом случае точка 0 0 SVG-холста совпадает с точкой 50% 50% элемента, который мы хотим трансформировать. Следующий демо-пример (жмите воспроизведение/пауза) показывает три четырёхконечные звёзды, которые изначально расположены в середине, а затем повёрнуты, смещены, наклонены и сжаты без необходимости в установке transform-origin или в добавлении сдвигов в цепочке:

Давайте рассмотрим, как работает это демо шаг за шагом.

Создается звезда очень легко — простой многоугольник с восемью точками. Демо-пример ниже показывает, как они позиционируются относительно начальной точки ( 0 0 ) SVG-холста. Наводите мышкой на пары x,y в коде или на сами точки, чтобы увидеть что чему соответствует.

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

Первое, что мы сделаем, это отмасштабируем наши звёзды от 0 до 1 :

use < animation:ani 4s linear infinite; > @keyframes ani < 0% < transform: scale(0); > 25%, 100% < transform: scale(1); > >

Это даст нам следующий результат:

Следующее, что мы хотим сделать, это добавить поворот к нашей покадровой анимации. Но нам нужен разный поворот для каждой звезды — допустим, случайный угол плюс определённый угол, рассчитываемый по порядковому номеру звезды. Это означает, что мы не можем применить одну и ту же покадровую анимацию для всех трёх звёзд; нам нужно три разных анимации. Также это поможет нам сделать заливку разной.

$n: 3; $?: 360deg/$n; $?: random($?/1deg)*1deg; @for $i from 1 through $n < $?: $? + ($i - 1)*$?; use:nth-of-type(#$i>) < fill: hsl($?, 100%, 80%); animation: ani-#$i> 4s linear infinite; > @keyframes ani-#$i> < 0% < transform: scale(0); > 25% < transform: scale(1); > 50%, 100% < transform: rotate($?); > > >

Вы можете посмотреть результат в коде ниже:

Следующим шагом будет сдвиг и масштабирование нашей звезды:

@keyframes ani-#$i> < 0% < transform: scale(0); > 25% < transform: scale(1); > 50% < transform: rotate($?); > 75%, 100% < transform: rotate($?) translate(13em) scale(.2); > >

Мы почти у цели! Нам просто надо наклонить звёзды и применить трансформацию для масштабирования, чтобы подправить их размеры после наклона.

@keyframes ani-#$i> < 0% < transform: scale(0); > 25% < transform: scale(1); > 50% < transform: rotate($?); > 75% < transform: rotate($?) translate(13em) scale(.2); > 83% < transform: rotate($?) translate(13em) scale(.2) skewY(30deg) scaleX(.866); > 91% < transform: rotate($?) translate(13em) scale(.2) skewY(60deg) scaleX(.5); > 100% < transform: rotate($?) translate(13em) scale(.2) skewY(90deg) scaleX(0); > >

Здесь я добавила больше одного ключевого кадра для точности. В то время как угол наклона изменяется линейно, корректирующий коэффициент масштаба — нелинейно, его значение — это косинус угла наклона, и как видно на следующем изображении, график функции косинуса между 0° и 90° — не прямая.

Рисунок 10: график синуса (синий) и косинуса (красный)

Однако, этот пример на чистом CSS немного глючит в Firefox и не работает ни в каком IE, поскольку ни одна из версий IE не поддерживает CSS-трансформации для SVG-элементов. Всё это можно исправить, если использовать атрибуты для SVG-трансформации и анимировать их значения при помощи JavaScript. Вы можете посмотреть JavaScript-версию ниже (нажмите, чтобы запустить).

P.S. Это тоже может быть интересно:
  • Голограммы, пленочные засветки и шейдеры на чистом CSS
  • День зимнего солнCSSтояния: новые публикации CSS и приятный сюрприз Safari
  • Тёмная сторона CSS: выходим за рамки и взрываем звезды с border-image и градиентами

Если вам понравилась статья, поделитесь ей!

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

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