SVG на практике

Автор: Chris Coyier    Источник: alistapart.com
18.10.2016
1212
0
img
Отрывок из 6 главы книги Криса Койера «Practical SVG»

Наверное, вам хочется получить контроль над размерами всей графики, которую вы используете на сайте. «Эй, ты! Лого! Ты должно быть такого размера:»

<img class="logo" src="logo.png" />
.logo {
  width: 220px;
  height: 80px;
}

И так все и происходит.

Но если элемент, который вы масштабируете, это svg, то результат может быть не совсем таким, как вы ожидаете. Масштабирование SVG – это более сложная задача, чем масштабирование изображения. Я говорю это не для того, чтобы напугать вас. Это сложнее в хорошем смысле, потому что дает вам больше контроля и открывает некоторые интересные возможности.

Запомните эти два понятия, когда работаете с размерами SVG:

  • viewport – это просто высота и ширина элемента: видимая область SVG изображения. Часто она устанавливается с помощью атрибутов width и height прямо на SVG или через CSS;
  • viewBox – это атрибут SVG, который определяет координаты системы и соотношение сторон. Четыре значения – это x, y, ширина и высота.

Предположим, что мы работаем с неким SVG, как этот:

<svg height="100" viewbox="0 0 100 100" width="100"></svg>

В этом случае viewport и viewBox в идеальной гармонии. SVG будет нарисован точно в той области, что он визуально занимает.

See the Pen adqEmQ by Chris Coyier (@chriscoyier) on CodePen.

А теперь удвоим ширину и высоту, например, так:

<svg height="200" viewbox="0 0 100 100" width="200"></svg>

Как думаете, SVG просто отобразится в области 100 на 100 в верхнем левом углу элемента размером 200 на 200? Нет! Все внутри SVG будет идеально увеличено, чтобы отобразиться в новой, большой области.

See the Pen VeQyQY by Chris Coyier (@chriscoyier) on CodePen.

Соотношение сторон квадрата все еще идеально совпадает. Поэтому не правильно думать о цифрах в SVG как о пикселях, потому что это не пиксели; это просто цифры случайной системы координат.

Но что, если соотношение сторон не совпадает?

<svg height="75" viewbox="0 0 100 100" width="300"></svg>

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

See the Pen vLdpdN by Chris Coyier (@chriscoyier) on CodePen.

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

<svg preserveaspectratio="xMaxYMax"></svg>

После x и Y идут значения Min, Mid или Max. Причина, почему SVG обычно центрируется внутри viewport – потому что он имеет значение по умолчанию xMidYMid. Если вы поменяете его на xMaxYMax, то это скажет SVG: «Убедись, что уходишь по горизонтали максимально вправо, насколько можешь, а вертикально максимально вниз, насколько можешь. А потом стань на столько большим, насколько можешь, без обрезания».

Часть «без обрезания» – это еще один аспект preserveAspectRatio. Дефолтное значение - xMidYMid meet – обратите внимание на «meet». Вы можете поменять «meet» на «slice» и тем самым сказать SVG: «Заполни всю область, обрезание допустимо».

Ниже 9 возможных вариантов выравнивания, скомбинированных с частичкой «meet»:

Еще 9 вариантов выравнивания, скомбинированных с частичкой «slice»:

Я сделал тестовый инструмент, чтоб поиграть с этой идеей. Сара Суидан (Sara Soueidan) также написала статью на эту тему, где она сделала отличное наблюдение, связывающее эту идею с CSS. У свойства background-size есть 2 значения: contain и cover. Свойство «contain» значит, что картинка должна быть полностью видна, даже если придётся ужать ее, что делает это свойство таким же как «meet». Свойство «cover» значит, что картинка должна покрыть всю область, даже если придётся её частично обрезать, что делает это свойство таким же как «slice».

Даже у выравнивающей части значения есть CSS аналог: background-position. Значение по умолчанию для background-position - это "0 0", то есть «вверху слева». Это то же самое, что и xMinYMin. Если вы измените это значение, к примеру, на "50% 100%", то это будет то же самое, что xMidYMax!

Ниже несколько примеров, показывающие эту связь.

preserveAspectRatio= "xMinYmax meet" background-position: 0 100%;
background-size: contain;
preserveAspectRatio= "xMidYMid meet" background-position: 50% 50%;
background-size: contain;
preserveAspectRatio= "xMinYmax slice" background-position: 0 100%;
background-size: cover;
preserveAspectRatio= "xMidYMid slice" background-position: 50% 50%;
background-size: cover;

Но что, если вы захотите исключить соотношение сторон окна и масштабировать SVG как растровую картинку? Просто отключите preserveAspectRatio.

<svg preserveaspectratio="none" viewbox="0 0 100 100"></svg>

See the Pen yevpvj by Chris Coyier (@chriscoyier) on CodePen.

Амелия Беллами-Ройдс (Amelia Bellamy-Royds) написала исчерпывающую статью о масштабировании SVG, в которой она описала тот факт, что внутри SVG могут быть другие SVG с разным соотношением сторон и поведением. Это значит, что вы можете какие-то части изображения масштабировать, а какие-то нет, что очень круто и уникально для SVG.

Методы масштабирования рабочей области

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

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

Быстрый способ создать такую рабочую область – кадрирование в Illustrator: берете инструмент Tool, а затем выбираете в меню пункт “Fit to Artwork Bounds”.

Преимущество такого подхода – это выравнивание. Если вам понадобится выровнять с чем-то какую-то из этих иконок, то это будет просто. Нет никакого загадочного пространства, которое нужно учитывать и подправлять CSS позиционирование.

.icon.nudge {
  position: relative;
  right: -2px; /* UGHCKKADKDKJ */
}

Недостаток техники кадрирования – относительные размеры. Представьте, что вы изменили ширину и высоту иконок, например, так:

.icon {
  width: 1em;
  height: 1em;
}

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

На примере ниже две иконки одинаково масштабированы в виде квадрата. Иконка “expand” выглядит отлично, так как у нее квадратное соотношение сторон. А вот у иконки “zap it” соотношение сторон узкое, поэтому она выглядит так, как будто зависла в квадратной области.

Еще один подход – делать рабочую область одинаковую по размеру.

В этом случае преимущества и недостатки будут точно противоположны. У вас могут возникнуть проблемы с выравниваем, так как не все края иконок совпадают с краями viewBox. Возможно, понадобится что-то подправлять.

Зато не будет проблем с относительными размерами, потому что viewBox одинаковый для всех. Если какая-то иконка выглядит слишком большой или маленькой, вы можете отрегулировать рабочую область так, чтобы иконка соответствовала набору.

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

Адаптивный SVG

Отличительная черта адаптивного дизайна – меняющийся макет. Контент, включая изображения, разрабатывается так, чтобы заполнить контейнеры и экран. Если адаптивный дизайн – это что-то новое для вас, то статья Итана Маркотта – это отличный способ начать его изучение. SVG очень хорошо подходит для адаптивного дизайна:

  • Адаптивный дизайн гибкий. Как и SVG! Он отлично выглядит при любом размере.
  • Адаптивный веб дизайн заботится о том, как веб сайт выглядит и ведет себя в разных браузерах. Сравнительно маленькие файлы и удивительно гибкая система SVG могут стать частью этого.

Но, наверное, самая очевидная связь SVG с адаптивным дизайном – это возможность взаимодействовать с CSS @media queries. Media queries двигает, прячет или показывает элементы с помощью CSS, исходя из высоты и ширины окна браузера. Это могут быть любые элементы: сайдбар, навигация, рекламный блок, что угодно. Так же это могут быть и SVG элементы.

Представьте логотип, который отображается с разным уровнем детализации в зависимости от того, сколько доступно места. Это как раз то, о чем думал Джо Харрисон (Joe Harrison), когда создавал демо, используя всем известный логотип.

В вебе у нас всегда есть возможность поменять картинку на другую. Но в этом случае картинка не меняется, это все – одна и та же картинка. Ну или может быть одной и той же. Подпись «D» - это все та же «D», что используется в более сложной версии логотипа. Легко и просто с CSS.

Допустим, мы организовали SVG таким образом:

<svg class="disney-logo">
 <g class="magic-castle">
    <!-- paths, etc -->
  </g>
  <g class="walt">
    <!-- paths, etc -->
  </g>
  <g class="disney">
    <path class="d"></path>
    <!-- paths, etc -->
  </g>
</svg>

Это, кстати, очень легко делается в Illustrator. Созданные группы и имена превратятся в ID в конечном SVG, и вы сможете использовать эти ID для стилизации. Хотя я все-таки предпочитаю использовать классы, потому что они не уникальны (на странице не окажется несколько одинаковых ID) и потому что у них более низкий и более управляемый уровень CSS специфики. Достаточно просто заменить ID на классы с помощью функции «найти и заменить» в редакторе кода.

CSS может быть примерно таким:

@media (max-width: 1000px) {
  .magic-castle {
    display: none;
  }
}
@media (max-width: 800px) {
  .walt {
    display: none;
  }
}
@media (max-width: 600px) {
  .disney > *:not(.d) {
    display: none;
  }
}

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

Все может быть даже еще забавнее! Учитывая то, как используется SVG, media queries могут быть разными. У SVG, используемого как img, iframe или object, есть свой собственный viewport. Это значит, что CSS, встроенный внутри него, взаимодействует с media queries, основываясь на ширине SVG, а не на ширине всего окна браузера. То есть, вы можете написать media queries, зависящие от ширины картинки, а не всей страницы.

Это очень интересная идея: элемент, который сам себя настраивает на основе своих собственных атрибутов, а не атрибутов страницы. «Я могу быть шире? Ок. Я могу быть выше? Ок.» По этому, SVG быстрее реагирует на ситуацию, чем документ, частью которого он является.

Как я писал, SVG упоминается как «элемент запросов» в CSS, но пока что такого термина не существует в официальном HTML/CSS.

Анимация

Говоря о вещах, в которых хорош SVG, давайте перейдем к анимации. Все, что мы делали раньше, подготовило нас к этому. Держитесь крепче!