Создание реалистичного эффекта стекла в SVG

Сегодня я расскажу, как создать эффект стеклянного текста при помощи SVG.

Шаг 1: Размещаем основное изображение

Создание реалистичного эффекта стекла в SVG

Сначала необходимо указать адрес основного изображение. Для этого используются тег <svg> с элементом <image> внутри него. Размеры атрибута viewBox и элемента <image> в SVG одинаковы. Это гарантирует, что элемента <image> будет одинакового размера с исходным изображением.

Сам файл SVG не включает растровое изображение. Но мы можем разместить ссылку на него в SVG-коде.

Шаг 2: Обработка картинки

Обработаем изображение при помощи фильтра. Создаем ещё один <svg> для хранения фильтров.

Первый фильтр (#displacement) искажает изображение. В нем используются два примитива: feTurbulence и feDisplacementMap. Они воссоздают на изображении эффект вибрации.

После добавления фильтра применим его к элементу <image>.

HTML

<svg> <!—- ещё код --> <!—ИСКАЖЕННОЕ ИЗОБРАЖЕНИЕ: вырезанное --> <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 clip-path="url(#clip)" filter= "url(#distortion)"></image> <!-- ФИЛЬТР: эффект дрожания --> <filter id="distortion"> <feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/> <feDisplacementMap in2="turbulence" in="SourceGraphic" scale="20" xChannelSelector="R" yChannelSelector="G"/> </filter> <!-- ещё программный код --></svg>

Шаг 3: Вырезаем текст

Для этого необходимо добавить элемент <text> в тег <clip-path> и присвоить ему id. Это ограничивает область вырезанного текста контейнером <text>.

Шаг 4: Открываем изображение в полном объеме

Но после того как мы вырезали текст, основная область картинки исчезла. Это можно исправить, добавив копию оригинального картинки.

Создание реалистичного эффекта стекла в SVG

Можно было бы добавить фильтр в <text> и использовать свойство in=“BackgroundImage в feDisplacementMap, чтобы исказить картинку за текстом. Но этот метод поддерживается не всеми браузерами, так что придется работать с несколькими картинками.

HTML

<svg> <!—- ещё код --> <!—ФОНОВОЕ ИЗОБРАЖЕНИЕ - видимое --> <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 ></image>     <!-- ИСКАЖЕННОЕ ИЗОБРАЖЕНИЕ: вырезанное -->  <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 clip-path="url(#clip)" filter= "url(#distortion)"></image>  <!—- ещё программный код --></svg>

Шаг 5: Снова размещаем текст

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

HTML

<svg>  <!— ещё программный код -->  <!-- ТЕКСТ - вырезанный -->  <clipPath id="clip">    <text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle">KYOTO</text>  </clipPath>          <!-- TЕКСТ - видимый -->  <text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle">KYOTO</text><!—- ещё код --></svg>

Шаг 6: Создаем темный край текста

Создадим темный край вокруг текста, который в сочетании со светлым краем добавит глубины. Для этого добавим новый фильтр и присвоим ему id=“textFilter». После чего сошлемся на него в атрибуте filter элемента <text>.

Сейчас необходимо воссоздать тень, которую будет отбрасывать стекло. Для реализации этого эффекта мы используем примитива: feMorphology, feOffset, feFlood и feComposite.

feMorphology сделает текст толще. В следующей версии примера закомментируйте три примитива( feOffset, feFlood, feComposite) и поэкспериментируйте с feMorphology.

feOffset используется для перемещения всех «пикселей» в предыдущем примитиве( feMorphology). Значения dx=’5′ и dy=’5′ перемещают «пиксели» по оси x и по оси y соответственно. Чем больше число, тем дальше они перемещаются. Установите для dx отрицательное значение и «пиксели» переместятся влево. При отрицательном значении dy они будут двигаться вверх.

Я пишу слово «пиксели» в кавычках, так как это не пиксели экрана. Это размеры, установленные для родительского элемента <svg>. Я воспринимаю их как проценты. В примере, приведенном ранее, мы использовали параметра viewBox= “0 0 1890 1260”. Это значит, что ширина контейнера <svg> составляет 1890 «пикселей». Если мы установим dx=“189”, элемент переместится по холсту SVG на 10%.

feFlood ­– отличный примитив для заливки указанной области картинки! Но теперь мы не сможем прочитать текст, поскольку фильтр просто заполняет определенную область цветом.

feComposite поможет исправить эту проблему. Этот примитив влияет на альфа-слой канала in в канале in2.

HTML

<svg>  <!—- ещё программный код -->      <!—- темный край -->  <feMorphology operator="dilate" radius="4" in="SourceAlpha" result="dark_edge_01" />    <feConvolveMatrix order="3,3" kernelMatrix=      "1 0 0 0 1 0 0 0 1" in="dark_edge_01" result="dark_edge_02" />    <feOffset dx="5" dy="5" in="dark_edge_02" result="dark_edge_03"/>    <feFlood flood-color="rgba(0,0,0,.5)" result="dark_edge_04" />    <feComposite in="dark_edge_04" in2="dark_edge_03" operator="in" result="dark_edge" />      </filter>  <!—- ещё код --></svg>

Шаг 7: Создаем светлый край

Сейчас нам необходимо сместить фигуру вверх и влево, используя отрицательные значения dx/dy. На этот раз установим белый цвет. Наша цель – достичь хорошего эффекта глубины. Но мы не будем использовать feComposite, так как альфа-канал темного края не должен закрашиваться светлым краем.

HTML

<svg>  <filter id="textFilter">    <!—- ещё программный код -->      <feMorphology operator="dilate" radius="4" in="SourceAlpha" result="light_edge_01" />      <feConvolveMatrix order="3,3" kernelMatrix=      "1 0 0 0 1 0 0 0 1" in="light_edge_01" result="light_edge_02" />      <feOffset dx="-2" dy="-2" in="light_edge_02" result="light_edge_03"/>      <feFlood flood-color="rgba(255,255,255,.5)" result="light_edge_04" />      <feComposite in="light_edge_04" in2="light_edge_03" operator="in" result="light_edge" />    <!—- ещё код -->    </filter></svg>

Шаг 8: Соединяем края

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

HTML

<svg>  <filter id="textFilter">    <!—- ещё код -->    <feMerge result="edges">      <feMergeNode in="dark_edge" />      <feMergeNode in="light_edge" />    </feMerge>    <feComposite in="edges" in2="SourceGraphic" operator="out" result="edges_complete" />  </filter></svg>

Шаг 9: Наклон

Получился хороший эффект 3D-зеркала. Но буквы все ещё выглядят плоскими. Сделаем их более округлыми при помощи эффекта наклона.  Сначала используем примитив feGaussianBlur. Он размоет существующие фильтры. Далее применим feSpecularLighting. Оригинально изображение темное, так что установим для атрибута lighting-color какой-нибудь яркий цвет. Если выбранное изображение слишком яркое, это может затруднить чтение букв. В этом случае можно задать для lighting-color более темный оттенок.

HTML

<svg>  <filter id="textFilter">      <!-- ещё программный код -->    <feGaussianBlur stdDeviation="5" result="bevel_blur" />    <feSpecularLighting result="bevel_lighting" in="bevel_blur" specularConstant="2.4" specularExponent="13" lighting-color="rgba(60,60,60,.4)">      <feDistantLight azimuth="25" elevation="40" />    </feSpecularLighting>    <feComposite in="bevel_lighting" in2="SourceGraphic" operator="in" result="bevel_complete" />  </filter></svg>

Шаг 10: Соединяем все вместе.

Сейчас применим последний примитив feMerge, чтобы увидеть окончательный результат.

HTML

<svg>  <filter id="textFilter">    <!-- ещё код -->    <feMerge result="complete">      <feMergeNode in="edges_complete" />      <feMergeNode in="bevel_complete" />    </feMerge>  </filter></svg>

HTML

<!-- ВИДИМЫЙ SVG --><svg viewBox="0 0 1890 1260">          <!-- ФОНОВОЕ ИЗОБРАЖЕНИЕ - видимое -->  <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 ></image>      <!-- ИСКАЖЕННОЕ ИЗОБРАЖЕНИЕ: вырезанное -->  <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/5946/kyoto.jpg" width="1890" x=0 height="1260" y=0 clip-path="url(#clip)" filter= "url(#distortion)"></image>      <!-- ТЕКСТ - вырезанный -->  <clipPath id="clip">    <text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle">KYOTO</text>  </clipPath>      <!-- ТЕКСТ - видимый -->  <text x="50%" y ="50%" dominant-baseline="middle" text-anchor="middle" filter="url(#textFilter)">KYOTO</text>    </svg><!-- ФИЛЬТРЫ --><svg>  <filter id="distortion">    <feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/>    <feDisplacementMap in2="turbulence" in="SourceGraphic" scale="20" xChannelSelector="R" yChannelSelector="G"/>  </filter>      <filter id="textFilter">                <!-- темный край -->    <feMorphology operator="dilate" radius="4" in="SourceAlpha" result="dark_edge_01" />    <feOffset dx="5" dy="5" in="dark_edge_01" result="dark_edge_03"/>    <feFlood flood-color="rgba(0,0,0,.5)" result="dark_edge_04" />    <feComposite in="dark_edge_04" in2="dark_edge_03" operator="in" result="dark_edge" />                     <!-- светлый край -->    <feMorphology operator="dilate" radius="4" in="SourceAlpha" result="light_edge_01" />    <feOffset dx="-2" dy="-2" in="light_edge_01" result="light_edge_03"/>    <feFlood flood-color="rgba(255,255,255,.5)" result="light_edge_04" />    <feComposite in="light_edge_04" in2="light_edge_03" operator="in" result="light_edge" />              <!-- края вместе -->    <feMerge result="edges">      <feMergeNode in="dark_edge" />      <feMergeNode in="light_edge" />    </feMerge>    <feComposite in="edges" in2="SourceGraphic" operator="out" result="edges_complete" />              <!-- наклон -->    <feGaussianBlur stdDeviation="5" result="bevel_blur" />    <feSpecularLighting result="bevel_lighting" in="bevel_blur" specularConstant="2.4" specularExponent="13" lighting-color="rgba(60,60,60,.4)">      <feDistantLight azimuth="25" elevation="40" />    </feSpecularLighting>    <feComposite in="bevel_lighting" in2="SourceGraphic" operator="in" result="bevel_complete" />    <!-- все на  месте -->    <feMerge result="complete">              <feMergeNode in="edges_complete" />              <feMergeNode in="bevel_complete" />    </feMerge>  </filter></svg>

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

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