Frontender Magazine

Техника создания текстурного текста

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

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

Для каждого примера я привёл иллюстрацию конечного результата и ссылку в конце описания каждого из них. Для просмотра примера также достаточно просто кликнуть по соответствующей иллюстрации.

Применение фонового изображения для текста посредством использования свойства -webkit-background-clip: text

Мы начнём с CSS-свойства background-clip, применение которого даёт следующий результат:

пример №1

Данное CSS-свойство background-clip определяет область закрашивания фона элемента, или область, внутри которой будет прорисовываться фон. По умолчанию, фон занимает всё пространство между границами элемента со значением border-box и может принимать другие значения, такие как padding-box и content-box.

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

Для Webkit в свойство background-clip добавлено четвёртое значение, text, которое обрезает фоновое изображение по тексту на переднем плане, с учётом декоративных элементов и теней. Если в придачу к обрезке фона для текста установить прозрачный цвет шрифта, используя Webkit-свойство -webkit-text-fill-color, сквозь текст будет просматриваться необходимое нам фоновое изображение.

На момент написания статьи значение text свойства background-clip не было внесено ни в один стандарт, так что, к сожалению, оно работает только в браузерах на движке WebKit. Для других браузеров придётся использовать более простое запасное решение на основе CSS, или же полифил.

Ниже мы создадим текст с фоном, используя свойство -webkit-background-clip и опишем фолбек на основе CSS, благодаря которому в браузерах на движках, отличных от WebKit, будет виден текст на фоне картинки.

Для нашего примера (см. скриншот выше) мы будем использовать элемент с фоном и заголовок первого уровня внутри него. Нам необходимо обрезать фон так, чтобы казалось, будто бы он применён только для текста внутри элемента.

<div class="container">
    <!-- элемент, фон которого нам нужно обрезать -->
    <div class="clipped">
        <h1>CO<br/>OK</h1>
    </div>
    <!-- произвольный контент -->
    <p><span>The #1 cooking magazine in the world.</span> New healthy and 
    delicious recipes every week. Subscribe to the weekly issue of COOK 
    magazine and stay up-to-date on the latest kitchen trends and tips and 
    tricks from the world's #1 chefs. <br/>
    Download our app available for Android, iOS and Windows phones.</p>
</div>

Мы будем использовать полужирное начертание шрифта, чтобы сквозь текст лучше просматривался наш фон. Для элемента .clipped мы устанавливаем фоновое изображение, которое обрезается по контуру текста свойством background-clip со значением text . Далее, мы устанавливаем белый цвет для текста, так как браузеры не на движке WebKit будут отображать текст на фоне изображения, и нам необходимо выбрать такой цвет шрифта, который будет хорошо читаться на нашем фоне. Затем прописываем прозрачность в качестве цвета заливки текста, это правило отменит белый цвет текста в браузерах на WebKit так, что фоновое

изображение будет видно сквозь наш текст.

.clipped {
    background: url(../img/kitchen.jpg) no-repeat center center;
    background-size: cover;
    color: #fff;
    text-align: center;
    padding: 2em;
    /* -webkit-background-clip обрезает фон элемента по контуру текста */
    -webkit-text-fill-color: transparent; /* переопределяет цвет текста с белого на прозрачный в браузерах на webkit */
    -webkit-background-clip: text;
}

Взгляните на пример 1: Текст с фоном, используется background-clip:text

Если вы посмотрите пример не в WebKit-браузере, то увидите просто белый текст на фоне изображения.

Для тех случаев, когда изображение играет важную роль в передаче визуального посыла, отображение фонового изображения под непрозрачным текстом — это наверное самое лучшее запасное решение для браузеров не на движке WebKit. Однако при желании можно также в качестве альтернативы отобразить обычный текст без фонового изображения. Дивья Маниан (Divya Manian) написала отличную статью с объяснением техники создания подобного фолбека с обычным текстом, а Рейчел Нэйборс даже создала специальный миксин под Sass на основе кода Дивьи, он доступен на Codepen.

Так же как и фоновое изображение, для текста в качестве фона можно применить градиент. Так как градиенты в CSS приравниваются к изображению, в примере выше их можно прописать для элемента .clipped, в результате чего получим текст с градиентом в качестве фона. Ризе Сельчук Сайдам (Riza Selçuk Saydam) создал очень хороший интерактивный пошаговый пример на Codepen, который объясняет, как можно создать подобный текст с градиентом. Взгляните на него, если вам потребуется визуальное объяснение этого приёма.

Применение текстуры для текста с помощью mask-image: url();

Свойство для следующего приёма на CSS, который мы рассмотрим, также на данный момент поддерживается только браузерами на основе WebKit, и работает только с префиксом -webkit-. А вообще, вам может пригодится в дальнейшем эта таблица поддержки браузерами различных новых свойств.

В этом примере мы будем использовать CSS-маски для создания красивого эффекта текстурного текста. На текущий момент CSS-маски уже вошли в черновик нового стандарта, над которым работает W3C. Так что у нас есть надежда, что в скором времени и другие браузеры будут поддерживать это свойство.

Однако, пока мы создадим пример, который будет корректно работать только в браузерах на WebKit, и добавим простой фолбек для браузеров, построенных на другом движке. Для примера мы будем использовать CSS-свойство mask-image для применения к тексту эффекта брызг. В итоге у нас должен получиться следующий результат:

пример№2

При использовании CSS-масок мы заставляем текст принять форму изображения-маски, вместо альтернативного подхода, когда изображение принимает форму текста, как в случае с применением background-clip, описанным выше.

Свойство mask-image принимает одно из трёх значений: изображение с альфа-прозрачностью, прозрачные участки которого будут участками, где контент не будет отображаться, CSS-градиент или просто none. Для нашего примера мы будем использовать изображение с альфа-прозрачностью, которое выглядит следующим образом:

splatter-mask_1-codrops

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

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

Чтобы эффект был более реалистичным, я добавил для элемента, содержащего текст, некий акварельный фон, который будет просвечивать в местах, где текст «стёрт». Таким образом создаётся красивый переход от текста к фону. И для всей этой красоты используется только CSS. Неплохо, да? Очень жаль, что на данный момент поддержка этой техники среди остальных браузеров оставляет желать лучшего. Однако, чуть ниже мы поговорим о том, как можно сделать такой эффект более кроссбраузерным.

Сейчас для нашего примера нам понадобится контейнер, в который обёрнуты два заголовка:

<div class="container>
  <h1>Art</h1>
  <h2>Digital Magazine</h2>
</div>

Мы применим эффект брызг к элементу h1. Вот необходимое стилевое оформление для этого эффекта:

.container h1 {
    font: 35em/100% "Oswald", sans-serif;
    margin: 0 auto;
    padding: 0;
    text-align: center;
    color: #fff;
    /* свойство, которое создаёт эффект брызг */
    -webkit-mask-image: url(../img/splatter-mask_1.png);
    mask-image: url(../img/splatter-mask_1.png);
}

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

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

Взгляните на пример 2: Текстурный текст с применением mask-image.

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

Более подробно о CSS-масках можно почитать в спецификации W3C, кроме того взгляните на ещё один искусный пример текстурного текста в этой статье Трента Уолтона (Trent Walton).

Создание текстурного текста с помощью SVG

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

Обрезка фона по контуру текста с использованием <clippath> SVG

В данном примере мы используем элемент <clippath> и SVG для воссоздания эффекта от background-clip: text.

пример№3

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

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

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

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

Сначала мы создадим элемент SVG, содержащий весь наш SVG-код. Затем определим контур обрезки и применим его для элемента image через атрибут clip-path:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1200" height="400" viewBox="0 0 1200 400">
    <!-- добавление заголовка для улучшения доступности -->
    <title>Добавление фона для текста с использованием SVG clipPath</title>
    <defs> 
      <clippath id="my-path">
        <text x="50" y="300" font-size="200" >WATERCOLOR</text>
      </clippath>
    </defs>
    <image xlink:href="img/watercolor_1.jpg" clip-path="url(#test)" width="100%" height="100%" preserveAspectRatio="none" />
</svg>

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

В коде выше мы создали элемент text, прописали для него размер шрифта и указали координаты по оси x и y, которые определяют, где внутри SVG будет отрисован текст. Затем мы разместили текстовый элемент внутри элемента clippath, которому был присвоен ID, чтобы к нему можно было обратиться. Затем мы поместили элемент clippath внутрь элемента defs. Элемент defs может быть использован для хранения контента, который не отображается напрямую. Этот скрытый контент может быть вызван и отображён другими элементами SVG, что делает его идеальным для хранения шаблонов с графическими элементами многократного использования. В нашем случае он идеально подходит для определения контура обрезки, к которому мы хотим обратиться через атрибут нашего элемента с изображением.

Затем мы добавили изображение, прописали для него ширину и высоту и установили для атрибута preserveAspectRatio значение none, чтобы соотношение сторон не было фиксированным. Будь оно таковым, высота и ширина не применялись бы при нарушении соотношения сторон.

И наконец, мы вызываем ранее определённый контур обрезки, используя атрибут clip-path для изображения. Атрибут clip-path принимает идентификатор элемента clippath в качестве значения, и применяет контур обрезки для изображения.

Взгляните на пример 3: Фон текста с использованием <clippath>.

Вместо того, чтобы использовать атрибут clip-path для применения контура обрезки к изображению, можно также применить его с помощью CSS следующим образом:

image {
    clip-path: url(#my-path);
}

Этот подход должен работать как следует во всех современных браузерах: Chrome, Safari, Opera, Firefox и IE9+. А значит, если вы захотите использовать способ с CSS-свойством background-clip: text;, вы можете, например, проверить поддержку этого свойства браузером с помощью библиотеки Modernizr и предоставить в качестве альтернативы приём с SVG для остальных браузеров. Нечто похожее делает полифил, который создал Тим Петруски (Tim Pietrusky), однако вместо фонового изображения и его обрезки с помощью clippath, в нём также используется приём с SVG. При использовании полифила текст заполняется фоновым изображением, которое по изначальной задумке должно было быть обрезано. В следующей части нашей статьи мы рассмотрим способ заливки текста узором через SVG.

Применение фона для текста посредством его заливки с помощью элемента

<pattern>

Ещё один способ применить фон, или же узор для текста — это, как ни странно, просто заливка текста узором, вместо использования фонового изображения и обрезки его под текст. Для этого примера мы зальём текст узором, имитирующим дерево, который я скачал с SubtlePatterns.

пример№4

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

Так же как и в предыдущем примере, у нас есть SVG-элемент с заголовком для доступности, элемент text, который мы хотим заполнить узором и элемент defs, который мы будем использовать для определения узора. Узор состоит из изображения image и имеет идентификатор, который позже будет использован для обращения к нему и последующего применения к нашему тексту. Узор будет вызываться через атрибут fill внутри элемента с текстом или через CSS-свойство fill.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="700" height="400" >
    <!-- добавление заголовка для доступности -->
    <title>Применения для текста фона с узором в SVG</title> -->
    <!-- Источник: http://lea.verou.me/2012/05/text-masking-the-standards-way/ -->
    <defs>
        <pattern id="filler" patternUnits="userSpaceOnUse" width="400" height="400" >
            <image xlink:href="img/purty_wood.png" width="1200" height="600" preserveAspectRatio="none" />
        </pattern>
    </defs>
    <text x="100" y="70%" font-size="200" fill="url(#filler)">WOOD</text>
</svg>

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

text {
    fill: url(#filler);
}

Взгляните на пример 4, которое работает во всех современных браузерах, в действии - это готовый фон для текста посредством заполнения изображением SVG.

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

пример№5

Создать и использовать градиент в SVG очень просто. Градиент создаётся через
элементы radialGradient или linearGradient, ему присваивается идентификатор, а затем для обращения к нему используется атрибут fill или CSS-свойство, как мы делали выше для <pattern>. Ниже простой пример, где градиент используется для заливки текста.

На примере 5 продемонстрирована заливка текста градиентом.

И конечно же, градиент можно установить фоновым изображением контейнера, а затем обрезать его фон с помощью clippath, как мы делали в предыдущей части статьи.

Применение текстуры для текста с помощью SVG <mask>

пример№6

Точно так же, как мы применили маску из изображения для элемента с помощью CSS-свойства mask-image, можно добиться практически того же эффекта с помощью SVG маски.

Изображение с прозрачными и непрозрачными участками будет определять места, в которых будет отрисовываться текст, как мы видели это в предыдущей части, касающейся применения CSS-свойство mask-image. Однако, между CSS-масками и SVG-масками есть одно важное отличие: при использовании SVG-маски, области отрисовки определяются не значением альфа-канала, а значением яркости, в отличие от CSS-маски. Следовательно, изображение с чёрными и прозрачными кляксами, которое мы использовали в качестве маски выше, нужно заменить на изображение с белыми и прозрачными участками. Для того, чтобы воссоздать эффект акварельного текста, представленный ранее, нам придётся использовать изображение-маску вроде следующего:

маска яркости

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

Мы создадим image, обёрнутый в SVG-элемент mask, которому будет присвоен идентификатор, чтобы к нему можно было обратиться. А потом обернём mask в элемент defs, который используется для определения маски без её непосредственного отображения.

Иначе говоря, мы определяем (defs) SVG-маску (mask), которая является изображением (image) со следующим адресом (URL маски яркости, созданной ранее), и затем применяем эту маску к нашему тексту, используя атрибут mask элемента text или, конечно же, через CSS, используя свойство mask.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="380" >
    <!-- добавляем заголовок для доступности -->
    <title>Добавление текстуры для текста с использованием SVG-маски</title>
        <defs>
            <mask id="mask">
                <image width="1200px" height="1200px" xlink:href="img/splatter-mask_luminance.png" preserveAspectRatio="none"/>
            </mask>
        </defs>
    <text x="50" y="70%" font-size="168" fill="white" mask="url(#mask)">WATERCOLOR</text>
</svg>

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

Взгляните на кроссбраузерный результат в примере 6.

Если заинтересует этот прием, вы можете прочитать больше о комбинировании CSS и SVG масок в этой прекрасной статье Кристиана Шефера (Christian Schaefer), опубликованной в блоге The Nitty Gritty. Маски SVG обладают гораздо большим потенциалом, и всё становится ещё интересней, если в качестве маски применить, к примеру, анимированный фон на основе canvas.

Создание текстурного текста в помощью HTML5 <canvas>

Последняя техника, которую мы рассмотрим, предусматривает использование HTML5 элемента <canvas> для создания описанных выше эффектов. С помощью <canvas> можно обрезать один элемент по контуру другого, заливать текст текстурой и применять для текста эффекты вроде маски, изменив значение свойства globalCompositeOperation контекста <canvas>.

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

У нас есть элемент <canvas>, для которого мы указываем высоту и ширину. Перед закрывающим тегом мы добавим текстовый контент, который смогут прочитать скринридеры, а также он будет использоваться браузерами с отключённым JavaScript в качестве альтернативы. Здесь, однако, следует отметить, что в Firefox этот текст не отображается в качестве альтернативы в случае, когда JavaScript отключён, что вероятно, является ошибкой браузера.

<canvas id="canvas" width=1000 height=600 >
 <!-- резервный контент для доступности и для браузеров без js -->
  WATER
</canvas>

Теперь, когда у нас готова разметка, нарисуем текстурный текст.

Для нашего первого примера мы создадим текст в <canvas>, и зальём его выбранным узором чтобы получить следующий результат:

пример№7

Нам нужен элемент <canvas> и его контекст отрисовки, к которому мы затем добавим изображение для последующей заливки нашего текста.

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//добавляем изображение, которое будет использоваться как узор заливки
var img = document.createElement("img");
img.src="img/water.jpg";
//отрисовка текста
img.onload= function(){
  drawText();
}
//функция, которая отрисовывает текст и заливает его текстурой из img
function drawText() {
    ctx.font = "bold 200pt Oswald";
    ctx.fillStyle = ctx.createPattern(img, 'repeat');
    ctx.textAlign = 'center';
    var x = canvas.width / 2;
    ctx.fillText("WATER", x, 400);
    ctx.fill();
}

Давайте пройдёмся по коду выше. Вся отрисовка происходит в функции drawText. Мы определяем стиль шрифта в свойстве font, а затем используя метод createPattern, из изображения, созданного выше, создаём узор и устанавливаем его в качестве значения для свойства fillStyle, которое определяет стиль заливки для шрифта. И наконец, мы отрисовываем текст в <canvas>, используя метод fillText, принимающий в качестве аргумента строку с текстом, который должен быть отрисован, а также несколько координат по x и y, которые определяют, в каком месте <canvas> будет отрисован текст.

Взгляните на пример 7 в действии.

Необходимо отметить одну важную деталь: если вы используете в <canvas> подключённый шрифт, он иногда может не отображаться, поскольку отрисовка <canvas> может произойти до того момента, как будет загружен шрифт. Чтобы этого избежать, можно, например, использовать загрузчик шрифтов вроде Web Font Loader, созданного разработчиками из Typekit и Google, и отрисовывать <canvas> уже после загрузки шрифта:

WebFontConfig = {
    google: { families: [ 'Oswald' ] },
    fontactive: function() {
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var img = document.createElement("img");
        img.src="img/water.jpg";

        img.onload= function(){
            drawText();
        }

        function drawText() {
            ctx.font = "bold 200pt Oswald";
            ctx.fillStyle = ctx.createPattern(img, 'repeat');
            ctx.textAlign = 'center';
            var x = canvas.width / 2;
            ctx.fillText("WATER", x, 400);
        }
    }
};
(function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
     '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
})();

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

Перейдём к следующему приёму. Мы создадим эффект, похожий на обрезку для нашего <canvas>, изменив значение свойства globalcompositeOperation нашего контекста. Конечный результат будет выглядеть так:

пример№8

У контекста <canvas> есть свойство globalcompositeOperation, которое

определяет композиционные операции между так называемыми «исходным элементом» и «целевым элементом». Проще говоря, оно определяет как то, что вы хотите нарисовать будет сочетаться с тем, что уже нарисовано в <canvas>. Исходный элемент — это то, что вы хотите нарисовать, а целевой элемент — это то, что уже нарисовано до настройки свойства globalCompositeOperation. С помощью этого свойства можно нарисовать новые элементы и фигуры под уже существующими, скрыть некоторые участки с помощью маски, а также очистить некоторые участки <canvas>.

Свойство globalCompositeOperation может принимать одно из 16 значений, каждое из которых хорошо продемонстрировано в визуальном примере на MDN. Если вам ещё не приходилось работать с этим свойством, обязательно взгляните на этот пример, так как он поможет лучше разобраться со свойствами, которые мы будем использовать дальше. Ниже приведена иллюстрация с результатом применения каждого из этих значений. В исходном коде примера «целевой элемент» является синим прямоугольником, который нарисован на <canvas> первым, а «исходный элемент» — красный круг, который нарисован после указания значения для globalCompositeOperation.

композиция холста

На простом языке значение source-in этого свойства можно интерпретировать как «отрисовка участков/областей исходного и целевого элементов в местах их пересечения». Итак, если у вас есть два элемента, и один из них уже нарисован, а другой вы собираетесь нарисовать, отображаться будут только те участки, где эти два элемента пересекаются.

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

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var img = document.createElement("img");
img.onload = function () {
   drawText();
}
img.src="img/fire.jpg";
function drawText() {

    // добавление текста в canvas
    ctx.font = "bold 180pt IM Fell Great Primer SC";
    ctx.fillStyle = 'white';
    ctx.textAlign = 'center';
    var x = canvas.width / 2;
    ctx.fillText("FIRE", x, 325);

    // используем композицию, чтобы фоновое изображение
    // отрисовывалось только там, где отрисован текст
    ctx.globalCompositeOperation = "source-in";
    ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
}

В коде выше внутри функции drawText у нас есть 3 «секции», которые определяют, что именно будет в результате отрисовано в <canvas>. В первой секции мы указываем текст, а также все его стилевые свойства, а затем отрисовываем его с помощью метода fillText. Затем, мы устанавливаем для globalCompositeOperation нашего контекста значение source-in. Далее мы добавляем в <canvas> изображение.

Таким образом вы видите, что «исходный элемент» в этом случае — это элемент, который должен быть добавлен после установки значения для globalCompositeOperation(изображение), а «целевой элемент» — это текст, который был добавлен перед ней. Устанавливая значение source-in, мы говорим браузеру, что следует отрисовывать изображение только в тех местах, где оно пересекается с текстом, именно так мы получаем нужный нам эффект обрезки.

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

Когда будете их просматривать, обратите внимание, что если установить значение source-atop в нашем примере, результат будет тем же. Это значение, source-atop, говорит браузеру что, нужно отрисовывать участки/области исходного элемента (изображения) только там, где он пересекается с целевым элементом (текстом), а также, что нужно отрисовывать остальные части целевого элемента, даже если они не пересекаются с исходным элементом. В нашем случае оно даёт все тот же желанный для нас результат.

Взгляните на пример 8 для этого приёма.

Примечание: на момент написания этой статьи не все значения свойства globalCompositeOperation поддерживаются всеми современными браузерами без исключения. Кроссбраузерными являются шесть значений, они работают в Chrome, Safari, Firefox и Opera: source-over, source-atop, destination-over, destination-out, lighter и xor. Больше информации о кроссбраузерной поддержки вы можете почерпнуть из этой статьи. Примеры посложнее с использованием свойства globalCompositeOperation для более подробного обучения созданию очень крутых типографических эффектов с помощью canvas можно найти в этой публикации на HTML5Rocks.

Последним нашим примером мы рассмотрим не менее важный способ создания ещё одного эффекта с помощью canvas, однако на этот раз мы добавим для текста текстуру так, чтобы он переходил в фон, как мы делали раньше с помощью SVG и CSS. Готовый результат будет выглядеть следующим образом:

пример№9

Мы будем использовать изображение с альфа-каналом в качестве «маски». Текст, в свою очередь, должен отрисовываться только там, где он пересекается с чёрными участками изображения и должен быть «стёрт» в прозрачных местах изображения. Это значит, что нам нужно, чтобы наши исходный и целевой элементы отрисовывались только на участках взаимного пересечения. Исходя из данного рассуждения и иллюстрации значений globalCompositeOperation, представленной чуть выше, для получения необходимого нам результата мы будем использовать значение source-in.

Ниже представлено изображение, которое мы будем использовать в качестве «маски». Чёрные участки — это места пересечения изображения с текстом. Так же как и в части про CSS-маски, просто представьте что текст и изображение — это два отдельных слоя, разместите их один над другим и затем сотрите все части текста и изображения, где они не пересекаются друг с другом. Вы получите конечный эффект, который является результатом применения значения source-in.

мазки

Код Javascript такой же как и выше, только значение для globalCompositeOperation будет отличаться. Мы перейдём сразу к живому примеру, где можно посмотреть исходный код и поковыряться в нём.

Взгляните на пример 9 в действии

Здесь мы снова добавили для canvas фон, чтобы эффект перехода текста в фон выглядел немного реалистичнее. У нас получился «поцарапанный» фон с поцарапанным текстом, которые прекрасно сочетаются.

Анимирование фона текста

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

Мери Лу (Mary Lou) написала статью об эксперименте с CSS свойством background-clip: text и создании изящных эффектов для фона текста, обязательно почитайте её.

Трент Уолтон (Trent Walton) также написал статью, в которой описал создание текста с фоном из градиента и анимирование этого фона, которое даёт очень красивый и простой эффект.

И как всегда, несколько очень креативных экспериментов над CSS свойством background-clip с применением анимации CSS можно легко найти на Codepen. Среди них хотелось бы особенно выделить вот этот действительно крутой эксперимент от Лукаса Бебера (Lucas Bebber), в котором он создал интересный эффект заполнения текста водой и предложил фолбек для браузеров, не поддерживающих background-clip: text. Загляните по ссылке и на него и поиграйте с его кодом, в нём использованы очень крутые приёмы для создания эффекта заполнения водой.

Использование изображения вместо текста

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

За последние годы появилось множество готовых решений и Крис Койер (Chris Coyier) проделал огромную работу по их сбору, обозначив их плюсы и минусы и сведя результаты в так называемый Музей использования изображения вместо текста на основе CSS.

Если вы не хотите использовать ни один из описанных выше приёмов для создания текста с графическим эффектом, а вместо этого предпочитаете использовать один из существующих приёмов замены текста изображением, непременно взгляните на самый свежий приём от Скота Келлума (Scott Kellum). Он назвал его «Новым методом Келлума». Метод предполагает использования в своём роде «пустого» шрифта, добавленного через правило @font-face; символы этого шрифта не имеют ширину или начертание, что делает текст невидимым и, следовательно, позволяет избежать применения других приёмов, предполагающих скрытие исходного текста чтобы виден был только его фон.

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

Заключение

Надеюсь вы научились одной-двум полезным методикам из этой статьи. Я считаю, что мы рассмотрели большинство возможных способов создания текстурного текста с помощью CSS и HTML. Моим любимым является приём с использованием SVG, просто из-за его хорошей кроссбраузерной поддержки. Полагаю, однажды всё-таки придёт тот день, когда все браузеры будут поддерживать CSS-маски и значение text свойства background-clip, и мы наконец сможем использовать их без необходимости добавления альтернативных вариантов. И тогда лучшим выбором, без сомнения, станет метод на основе CSS.

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

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Sara Soueidan
Автор:
Sara Soueidan
GitHub:
SaraSoueidan
Twitter:
@SaraSoueidan
Сaйт:
http://sarasoueidan.com/
Наталья Фадеева
Переводчик:
Наталья Фадеева
вКонтакте:
natatik_l
Twitter:
@very_busy_girl
GitHub:
NatalieF