[Перевод] Эффект неисправного монитора для текста, картинок и SVG
Эффект Glitch Лукаса Беббера выглядит очень круто — как будто вы смотрите на текст на старом мониторе, который слишком часто роняли на пол и у него «плавает» вертикальная синхронизация и сведение.Реализация этого эффекта на CSS выглядит вполне убедительно. Мне пришлось немного поломать голову, чтобы выяснить, как он работает, и теперь я хочу объяснить это вам. Кроме того, я воспроизвёл этот эффект не только для текста, но и для растровых изображений и SVG, а так же написал несколько примесей Sass, чтобы облегчить работу с ним.
Три копии текстаHTML для этого примера выглядит просто:
Изменяем копии Каждая из дополнительных копий идентична оригиналу за исключением того, что: они смещены влево или вправо; У них есть цветной ореол, созданный с помощью text-shadow. Именно смещение и ореол служат основой для эффекта неисправного монитора. .glitch: before { /* … всё, что нужно, чтобы сделать слой идентичным оригиналу */
/* отличия от оригинала */ left: 2 px; text-shadow: -1 px 0 red; /* Важно: непрозрачный фон закрывает предыдущий слой */ background: black; } .glitch: after { /* … всё, что нужно, чтобы сделать слой идентичным оригиналу */
/* отличия от оригинала */ left: -2 px; text-shadow: -1 px 0 blue; /* Важно: непрозрачный фон закрывает предыдущий слой */ background: black; } Теперь наши три копии выглядят так:
Обрезаем копии Пока что нам видна только самая верхняя из трёх копий. Скорее всего, это версия :: after, если только вы не меняли z-index. Но это не важно, так как мы будем попеременно показывать части всех трёх копий с помощью свойства clip. В данный момент это свойство уже считается устаревшим, его должно заменить clip-path, но на момент написания статьи именно свойство clip работало лучше. Конечно, со временем это изменится, так что нужно иногда поглядывать на ситуацию. В случае чего, их легко будет поменять, например, с помощью Autoprefixer.У clip довольно странный синтаксис. Требуются четыре значения, логично было бы предположить, что это координаты верхнего левого угла и длина с шириной, или координаты верхнего левого и нижнего правого углов, но вместо этого числа означают отступы, как в свойствах margin или padding (top/right/bottom/left).
.glitch: before { clip: rect (44 px, 450 px, 56 px, 0); /* Получился прямоугольник с верхним левым углом 0, 44 px и нижним правым 450 px, 56 px */ } Вот как может выглядеть результат обрезки, для наглядности фон сделан непрозрачным и слои смещены друг относительно друга:
Анимируем обрезку Для свойства clip можно использовать анимации CSS, меняя положение обрезающего прямоугольника. Вот пример такой анимации: @keyframes glitch-anim { 0% { clip: rect (70 px, 450 px, 76 px, 0); } 20% { clip: rect (29 px, 450 px, 16 px, 0); } 40% { clip: rect (76 px, 450 px, 3 px, 0); } 60% { clip: rect (42 px, 450 px, 78 px, 0); } 80% { clip: rect (15 px, 450 px, 13 px, 0); } 100% { clip: rect (53 px, 450 px, 5 px, 0); } } Обратите внимание, что левый и правый край остаются неизменными, меняются только верхний и нижний край. И эти значения выбраны совершенно произвольно. С помощью Sass вполне можно генерировать их случайным образом: @keyframes glitch-anim { $steps: 10; @for $i from 0 through $steps { #{percentage ($i*(1/$steps))} { clip: rect (random (100)+px, 9999 px, random (100)+px, 0); } } } Так как нам понадобятся два набора случайных обрезающих прямоугольников, надо будет сделать два набора ключевых кадров и применить их к двум копиям: .glitch: before { …
animation: glitch-anim-1 2s infinite linear alternate-reverse; }
.glitch: after { …
animation: glitch-anim-2 2s infinite linear alternate-reverse; } В этом месте мы можем отрегулировать скорость анимации зациклить её. Эффект готов:
Примеси Sass Я подумал, что хорошо бы добавить этому эффекту возможность удобного повторного использования. Например, написать примесь Sass с параметрами, с помощью которых можно контролировать эффект: .example-one { font-size: 100 px; @include textGlitch («example-one», 17, white, black, red, blue, 450, 115); } Вот что у меня получилось: /* (TEXT) PARAMS ================= 1. Namespace 2. Intensity 3. Text color 4. Background color (flat) 5. Highlight #1 color 6. Highlight #2 color 7. Width (px) 8. Height (px) */
@mixin textGlitch ($name, $intensity, $textColor, $background, $highlightColor1, $highlightColor2, $width, $height) { color: $textColor; position: relative; $steps: $intensity; // Ensure the @keyframes are generated at the root level @at-root { // We need two different ones @for $i from 1 through 2 { @keyframes #{$name}-anim-#{$i} { @for $i from 0 through $steps { #{percentage ($i*(1/$steps))} { clip: rect ( random ($height)+px, $width+px, random ($height)+px, 0 ); } } } } } &: before, &: after { content: attr (data-text); position: absolute; top: 0; left: 0; width: 100%; background: $background; clip: rect (0, 0, 0, 0); } &: after { left: 2 px; text-shadow: -1 px 0 $highlightColor1; animation: #{$name}-anim-1 2s infinite linear alternate-reverse; } &: before { left: -2 px; text-shadow: 2 px 0 $highlightColor2; animation: #{$name}-anim-2 3s infinite linear alternate-reverse; } } Конечно, можно придумать ещё миллион способов, как реализовать эту примесь — всё зависит от того, какие параметры вы хотите настраивать, какая у вас разметка HTML и т.д. Я также написал ещё две примеси, одну для растровых изображений, вторую — для SVG. Они отличаются деталями реализации — там не используются псевдоэлементы, смещение и цветной ореол тоже делаются по-другому и т.д. Вот все три примеси в одном файле. А вот так выглядит их работа: