Меню

Базовое знакомство с Scalable Vector Graphics

26.06.2018 - CSS, SVG

Первое знакомство с SVG

Мы можем вставлять SVG в документ разными способами. Самый простой — вставить как обычную картинку через тег img.

<img src="image.svg" >

Как нам нарисовать svg в документе?

Для начала откроем svg тэги. Далее укажем ширину и высоту svg тэгов — таким образом мы устанавливаем viewport для нашего рисунка (типа канваса).

Теперь мы должны сказать браузеру, что мы собираемся использовать XML с не HTML тэгами, и какую версию SVG мы собираемся использовать.

Давайте нарисуем простую версию иконки монитора.

Сначала укажем тег rect и укажем его свойства height и width.
Теперь создадим второй прямоугольник, и также укажем ему высоту и ширину, а также зальем белым цветом с помощью атрибута fill.

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

Ну и в конце нарисуем «подставку» небольшим черным прямоугольником.

В самом конце нам нужно подстроить размер вьюпорта под размер иконки.

<svg
    width="100"
    height="100"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1">
<rect height="80" width="100">
<rect height="50" width="80" fill="white" x="10" y="10">
<rect height="10" width="40" x="30" y="90">
</svg>

Рисование окружностей в SVG

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

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

Теперь нам нужно нарисовать а-ля «кнопку».
Воспользуемся тэгом circle, первым делом укажем центр окружности с помощью cx и cy. Затем укажем радиус с помощью атрибута r. Зальем наш кружок белым цветом.

Теперь нужно скруглить края прямоугольника.
Прежде чем скруглять, познакомимся с элипсами. Элипсы рисуются с помощью elipse тэгов. Мы также указываем центр элипса с помощью cx и cy атрибутов. Но в отличие от окружностей, элипс имеет два радиуса — rx и ry.

Теперь воспользуемся этим знанием, чтобы скруглить края прямоугольника. Воспользуемся атрибутами rx и ry внутри прямоугольника, чтобы создать невидимый элипс для скругления краев. Края как бы описывают границы эллипса. Если мы хотим округлить края равномерно, то можем указать только один параметр — rx.

<svg
    width="200"
    height="200"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1">
<rect height="100" width="70" fill="white" stroke="#FF2626" stroke-width="10" x="5" y="5" rx="5" ry="5" />
  <circle cx="40" cy="105" r="3" fill="white"/>

</svg>

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

circle {
    animation: grow 2s infinite;
    transform-origin: center;
}

@keyframe grow {
    0% {transform: scale(1);}
    50% {transform: scale(0.5);}
    100% {transform: scale(1);}
}

Отрисовка фигур (линии, текст, полигоны)

Нарисуем бэйдж.

Начнем с окружности. Укажем центр, отсутствие заливки, обводку и её толщину.
Мы, кстати, можем указать эти параметры из CSS.

Обратите внимание, что при описании атрибутов из CSS обязательно указывать единицу величины. А также, всё что касается координат, должно оставаться inline в объекте.

Теперь нарисуем линию с помощью тэга line. Для того чтобы это сделать, нам нужно определить координаты двух точек — x1, y1, x2, y2. Укажем её атрибуты также в CSS.

Далее добавим текст в наш значок. Для этого воспользуемся тэгом text и укажем координаты левого нижнего края. Свойства текста опишем в CSS. Обратим внимание, чтобы переназначить опорную точку текста — воспользуемся атрибутом text-anchor.

Теперь нарисуем последнюю фигуру — полигон. Полигон это фигура состоящая из нескольких точек. Воспользуемся тэгом polygin, у него есть атрибут points, куда мы передадим три разных набора точек. Остальные атрибуты также опишем в CSS.

circle {
    fill: none;
    stroke: #008B6F;
    stroke-width: 7px;
}

line {
    stroke: black;
    stroke-width: 5px;
}

text {
    font-size: 60px;
    text-anchor: middle;
    font-family: sans-serif;
    stroke: #000;
    stroke-width: 3px;
    fill: #f6f7f3;
}

polygon {
    fill: #008B6F;
    stroke: black;
    stroke-width: 2px;
}
<svg
    width="268"
    height="268"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1">
    <circle r="130" cx="134" cy="134" fill="none" stroke="#008B6F" stroke-width="7"/>
    <line x1="47" y1="198" x2="221" y2="198" />
    <polygon points="52,190 134,30 216,190"/>
    <text x="134" y="142">SVG</text>
</svg>

Groups

Для того что бы понять как использовать группы, нарисуем три мелких треугольника.
Если мы попробуем засунуть эти три полигона к значку, то они появятся в левом верхнем углу. Как нам сместить их все в нужную нам позицию?

Первый дурной вариант, это сместить каждую точку каждого треугольника на 45px вправо и 67px вниз.
Но есть нормальный вариант. Мы можем сгруппировать их с помощью тэга <g>. Теперь мы можем взаимодействовать со всей группой. Группа позволяет нам делать разные вещи, такие как перемещать, вертеть и увеличивать. В нашем случае, нам нужно сместить группу. Для этого воспользуемся атрибутом transform и методом translate.

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

polygon {
    fill: #008B6F;
    stroke: #000;
    stroke-width: 2px;
}

.triangle_group polygon {
    stroke-width: 1px;
}
<svg
    width="268"
    height="268"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1">
    <circle r="130" cx="134" cy="134" fill="none" stroke="#008B6F" stroke-width="7"/>
    <line x1="47" y1="198" x2="221" y2="198" />
    <polygon points="52,190 134,30 216,190"/>
    <text x="134" y="142">SVG</text>
     <g class="triangle_group" transform="translate(45,67)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
     <g class="triangle_group" transform="translate(198,67)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
     <g class="triangle_group" transform="translate(121.5,211)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
</svg>

Мы также можем поворачивать, и менять размеры нашей группы. Повернем, например нашу левую группу с помощью метода rotate, у которого 3 параметра — угол поворота, и x, y координаты опорной точки. У нижней группы мы изменим размер, для этого воспользуемся методом scale. Он принимает один аргумент — во сколько раз изменить размер. Размер изменяется относительно левого верхнего угла. Поэтому во время изменения размеру будет смещение. Чтобы исправить это — нужно добавить еще один метод translate и нивелировать смещение

<svg
    width="268"
    height="268"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1">
    <circle r="130" cx="134" cy="134" fill="none" stroke="#008B6F" stroke-width="7"/>
    <line x1="47" y1="198" x2="221" y2="198" />
    <polygon points="52,190 134,30 216,190"/>
    <text x="134" y="142">SVG</text>
     <g class="triangle_group" transform="translate(45,67) rotate(10 12.5 12.5)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
     <g class="triangle_group" transform="translate(198,67) rotate(-10 12.5 12.5)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
     <g class="triangle_group" transform="translate(121.5,211) scale(0.6) translate(8, 8)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
</svg>

Что по поводу адаптивности

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

Вторым шагом, нам нужно указать ширину и высоту вьюпорта в динамических величинах. В нашем случае укажем ширину 50%, а высоту auto. viewBox принимает 4 параметра. Первые два это точка начала координат нашего вьюпорта, а вторые два это ширина и высота. А указать размеры нашего вьюпорта мы можем через CSS.

svg {
    height: auto;
    width: 50%;
}
<svg
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    viewBox="0 0 268 268">
    <circle r="130" cx="134" cy="134" fill="none" stroke="#008B6F" stroke-width="7"/>
    <line x1="47" y1="198" x2="221" y2="198" />
    <polygon points="52,190 134,30 216,190"/>
    <text x="134" y="142">SVG</text>
     <g class="triangle_group" transform="translate(45,67) rotate(10 12.5 12.5)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
     <g class="triangle_group" transform="translate(198,67) rotate(-10 12.5 12.5)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
     <g class="triangle_group" transform="translate(121.5,211) scale(0.6) translate(8, 8)">
    <polygon points="0,25 5,15 10,25"/>
    <polygon points="7,10 12,0 17,10"/>
    <polygon points="15,25 20,15 25,25"/>
    </g>
</svg>

Pathes (Пути)

<path d="M7,10 L7,10 L12,0 L17,10 Z" />

Cubic Bezier

Определяется двумя рычажками, по одной на каждую точку

<path d="M100,300 C0,150 250,-100 25,50"/>

Quadratic Bezier

Определяется одной опорной точкой, к которой стремится линия

<path d="M100 200 Q200 0 300 200" />

Elliptical Arc Curve

Сложная архихрень, которую не надо запоминать как рисовать вручную координатами.

Стилизация путей

Pathы можно стилизовать как и другие линии с помощью fill, stroke, stroke-width, stroke-linecap, stroke-dasharray, stroke-dashoffset и т.д. Также можно анимировать.

Symbols

В самом начале мы рисовали телефон. Если нам нужно один свг разместить например 2 раза на странице… Один раз в хэдере, а второй в тексте. То в коде будет дублирование тэга с svg.
Но… ! Если Вам нужно использовать иконку во многих местах на странице, Вам придет на помощь — Symbol. Символ сохраняет SVG элемент, для последующего использования. Для того, чтобы использовать symbol нужно обернуть одноименным тэгом, тот участок, который мы хотим использовать вновь. Символу нужно задать id.

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

Теперь для использования нашего символа, мы создадим новый svg. Также укажем что это вьюбокс. Для использования символа внутри SVG будем использовать use тэг. В нем есть атрибут xlink который указывает на символ, который должен отображаться. Он не может указывать на class, он может указывать только на id. Также мы должны указать xlink namespace, чтобы мы могли его использовать. Таким образом мы можем указать даже на внешний источник. Например:

<use xlink:href="path-to-file.svg#phone" />
.defined-icon {
    display: none;
}

#phone rect, #phone circle {
    fill: white;
}

#phone rect {
    stroke: #ff2626;
    stroke-width: 10px;
}

.displayed-icon {
    height: auto;
    width: 30%;
}
<svg xmlns="http://www.w3.org/2000/svg" class="defined-icon">
    <symbol id="phone">
        <rect x="5" y="5" width="70" height="100" rx="5"/>
        <circle r="3" cy="105" cx="40"/>
    </symbol>
</svg>
// ...

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 110" class="displayed-icon"
    version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
    <use xlink:href="#phone" />
</svg>

Accessibility

У svg есть два элемента, которые делают доступность возможной — title и description.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 110" class="displayed-icon"
    version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>Иконка телефон</title>
    <desc>Примитивная иконка телефона с тачпадом</desc>
    <use xlink:href="#phone" />
</svg>
Метки: ,

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

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