Хотелось бы рассмотреть ряд примеров стилизации текста и как использовать pattern
& mask
в связке с какими-то эффектами.
1. "Гусеничный" stroke (linearGradient
& animate
):
2. Текст, отбрасывающий от себя тень из
диагональных линий (pattern
& mask
):
3. Заполнение текста водой (SVG
(pattern
& mask
) & CSS
(@keyframes
)):
P.S. В данном вопросе присутствуют примеры, взятые из открытого доступа(2 и 3). Вопрос создан с целью привлечь к SVG
и показать его возможности.
Допустим нам необходимо добавить текст к существующей растровой картинке в стиле диалога, комикса.
При этом необходимо, чтобы изображение и текст были адаптивны,- сохраняли взаимное расположение при изменении размера.
Пошаговая инструкция:
SVG
<image xlink:href="https://i.stack.imgur.com/6HVU6.jpg" width="400" height="300"/>
Рисуем в векторном редакторе контур, где будет расположен текст
<path d="M350 280a400 400 0 0 0 4 -150a100 60 0 1 0 -14 4a400 400 0 0 1 10 146z"/>
Добавляем текст внутрь контура. К сожалению в svg
нет автоматического
переноса текста, как в HTML
, но есть возможность ручного переноса
текста с помощью атрибута <tspan>
При необходимости делаем более тонкую регулировку размера, позиции контейнера и текста
<g transform="scale(1.1) translate(-40 0)" >
svg {
width:40%;
height:40%;
}
text {
font-family: Lobster;
font-size:24px;
text-anchor:middle;
fill:#474447;
}
path {
fill:#fff;
stroke:#474447;
stroke-width:2;
}
<link href='https://fonts.googleapis.com/css?family=Lobster|Raleway' rel='stylesheet' type='text/css'>
<link href="google-font.css" rel="stylesheet" type="text/css">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 300" preserveAspectRatio="xMinYMin meet">
<image xlink:href="https://i.stack.imgur.com/6HVU6.jpg" width="400" height="300"/>
<g transform="scale(1.1) translate(-40 0)" >
<path stroke-miterlimit="50" d="M350 280a400 400 0 0 0 4 -150a100 60 0 1 0 -14 4a400 400 0 0 1 10 146z"/>
<text>
<tspan x="302" y="60" >Вы вызываете</tspan>
<tspan x="302" y="85" >больше проблем,</tspan>
<tspan x="302" y="110">чем пользы.</tspan>
</text>
</g>
</svg>
Картинка и текст адаптивны.
Работает во всех современных браузерах + IE11, Edge
Постепенно будем рассматривать и создавать подобные примеры.
Первый пример<symbol></symbol>
.Элемент <symbol>
используется для определения объектов графического шаблона, которые могут быть созданы элементом <use>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400" height="400">
<symbol id="text">
<text font-size="5em" text-anchor="middle" x="160" y="55">Some text</text>
</symbol>
<use xlink:href="#text"/>
</svg>
<linearGradient></linearGradient>
.Думаю здесь всё понятно, его можно подключать к различным элементам холста. В данном примере мы "залили" фон текста gradient'ом, но это не всё, что он может. Мы можем применить gradient для stroke
и не только.<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400" height="400">
<symbol id="text">
<text font-size="5em" text-anchor="middle" x="160" y="55">Some text</text>
</symbol>
<linearGradient id="grad">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
<use xlink:href="#text" fill="url(#grad)"/>
</svg>
stroke-dashoffset
с помощью <animate/>
.Атрибут stroke-dashoffset
определяет смещение stroke
относительно начального положения
Атрибут stroke-dasharray
имеет от 2х и больше значений. Первое значение определяет длину линии, а второе - пробел между линиями
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400" height="100">
<symbol id="text">
<text text-anchor="middle" x="160" y="55">Some text</text>
</symbol>
<linearGradient id="grad">
<stop offset="0%" stop-color="red"/>
<stop offset="60%" stop-color="black"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
<use xlink:href="#text" stroke-dashoffset="0" stroke-dasharray="10 15" fill="none" stroke-width="3" stroke="url(#grad)" font-size="5em">
<animate attributeName="stroke-dashoffset" values="250;0" dur="7s" repeatCount="indefinite"/>
</use>
</svg>
Можно приступать к самому "гусеничному" эффекту. Мы должны наложить текст на текст и изменить атрибуты stroke-dashoffset
& stroke-dasharray
.
Первый пример готов:
@import url(https://fonts.googleapis.com/css?family=Open+Sans:800);
* {
margin: 0;
padding: 0;
}
body {
background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
font-family: Open Sans;
text-transform: uppercase;
letter-spacing: 5px;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/2000/svg" version="1.1">
<symbol id="stroke-dash">
<text text-anchor="middle" x="50%" y="50%">Stroke</text>
</symbol>
<linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#05a"/>
<stop offset="100%" stop-color="#0a5"/>
</linearGradient>
<use xlink:href="#stroke-dash" stroke="url(#linear)" stroke-dasharray="10 1" stroke-width="3" stroke-dashoffset="0" font-size="4em">
<animate attributeName="stroke-dashoffset" values="250;0" dur="15s" repeatCount="indefinite"/>
</use>
<use xlink:href="#stroke-dash" stroke="url(#linear)" stroke-dasharray="10 15" stroke-width="3" stroke-dashoffset="0" font-size="4em">
<animate attributeName="stroke-dashoffset" values="250;0" dur="15s" repeatCount="indefinite"/>
</use>
</svg>
P.S. В данном примере мы ознакомимся с pattern
& mask
.
pattern
на любом квадрате, заполнив его кругами:pattern
можно использовать в качестве заливки или обводки для различных элементов, будь то текст, фигуры или изображения.
<link href='https://fonts.googleapis.com/css?family=Cabin+Condensed:700' rel='stylesheet' type='text/css'>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<pattern id="pattern" width="10" height="10" patternUnits="userSpaceOnUse">
<circle id="circle" cx="5" cy="5" r="5" fill="#000"/>
</pattern>
</defs>
<rect x="0" y="0" width="250" height="250" fill="url(#pattern)"/>
</svg>
pattern
& mask
. mask
в нашем контексте является поверхностным слоем, который скрывает часть контента.
.stripes {
width: 100px;
height: 50px;
mask: url("#mask");
}
.red {
fill: red;
}
.blue {
fill: blue;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/2000/svg" version="1.1" height="150" width="150">
<defs>
<pattern id="strokeEffect" width="1" height="3" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<rect x="0" y="0" width="1" height="1" fill="#fff"/>
</pattern>
<mask id="mask">
<rect height="100%" width="100%" style="fill: url(#strokeEffect)"/>
</mask>
</defs>
<rect class="stripes red" y="0"/>
<rect class="stripes" y="50"/>
<rect class="stripes blue" y="100"/>
</svg>
Воссоздадим второй пример, используя вышеперечисленное.
Второй пример готов:
body {
background-color: #2e2e2e;
}
<link href='https://fonts.googleapis.com/css?family=Cabin+Condensed:700' rel='stylesheet' type='text/css'>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="620" height="500">
<defs>
<pattern id="strokeEffect" width="1" height="3" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<rect x="0" y="0" width="1" height=".8" fill="#ffffff"/>
</pattern>
<text id="text" x="250" y="100" font-size="5em" text-anchor="middle" letter-spacing="15" font-family="'Cabin Condensed'">Some text</text>
<mask id="mask">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<use x="-6" y="-6" stroke="#000" stroke-width="5" xlink:href="#text" opacity="1" fill="#000"/>
</mask>
</defs>
<use x="6" y="6" xlink:href="#text" opacity="1" fill="url(#strokeEffect)" mask="url(#mask)"/>
<use x="0" y="0" xlink:href="#text" fill="#fff"/>
</svg>
body {
background: #141414;
text-align: center;
}
.water-fill {
-webkit-animation: wave 0.7s infinite linear, fill-up 10s infinite ease-out alternate;
animation: wave 0.7s infinite linear, fill-up 10s infinite ease-out alternate;
}
@-webkit-keyframes wave {
0% {
x: -400px;
}
100% {
x: 0;
}
}
@keyframes wave {
0% {
x: -400px;
}
100% {
x: 0;
}
}
@-webkit-keyframes fill-up {
0% {
height: 0;
y: 130px;
}
100% {
height: 160px;
y: -30px;
}
}
@keyframes fill-up {
0% {
height: 0;
y: 130px;
}
100% {
height: 160px;
y: -30px;
}
}
<link href='https://fonts.googleapis.com/css?family=Cabin+Condensed:700' rel='stylesheet' type='text/css'>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="575px" height="120px" viewBox="0 0 575 120" xml:space="preserve">
<defs>
<pattern id="water" width=".25" height="1.1" patternContentUnits="objectBoundingBox">
<path fill="white" d="M0.25,1H0c0,0,0-0.659,0-0.916c0.083-0.303,0.158,0.334,0.25,0C0.25,0.327,0.25,1,0.25,1z"/>
</pattern>
<text id="text" transform="matrix(1 0 0 1 -8 117)" font-family="'Cabin Condensed'" font-size="161">LOADING</text>
<mask id="text_mask">
<use xlink:href="#text" fill="white"/>
</mask>
</defs>
<rect class="water-fill" mask="url(#text_mask)" fill="url(#water)" width="1600" height="120"/>
</svg>
Делаем выводы:)
2.1. Происходит смещение pattern
по оси X
.
2.2. Эффект волны происходит за счёт ширины rect
, которая равна 1600
и отрицательному смещению по оси X
от -400
до 0
. Мы можем поэкспериментировать, то есть изменить значения и посмотреть что выйдет:
P.S. Результат не впечатляет, думаю вы разобрались почему так происходит. Если нет, значит вот краткий ответ: Мы делаем шире rect
, в то время как pattern
"подстраивается" под эту ширину, после этого мы смещаем rect
по оси X
.
2.3. Далее мы вставляем его в mask
, voilà, эффект волны для текста готов:)
.water-fill {
animation: wave 0.7s infinite linear, fill-up 10s ease-out alternate;
}
@keyframes wave {
0% {
/*New*/
x: -200px;
}
100% {
x: 0;
}
}
@keyframes fill-up {
0% {
y: 120px;
height: 0;
}
100% {
y: 0;
height: 120px;
}
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="water" width="0.25" height="1" patternContentUnits="objectBoundingBox">
<path fill="dodgerblue" d="M0.25,1H0c0,0,0-0.659,0-0.916c0.083-0.303,0.158,0.334,0.25,0C0.25,0.327,0.25,1,0.25,1z"/>
</pattern>
</defs>
<!--New (width)-->
<rect class="water-fill" fill="url(#water)" width="400" height="120"/>
</svg>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Почему-то не показываются маленькие иконки на сайте
Есть два блока, надо сделать функцию на javascript, чтобы по нажатию на кнопку 1 блок принял стиль display: block;, а второй display:none;
В шапке веб-страницы расположены якоря как менюШапка при прокрутке веб-страницы вниз получает фиксированную позицию