Эффект неисправного монитора для текста, картинок и SVG

Original author: Chris Coyier
  • Translation
  • Tutorial
Эффект Glitch Лукаса Беббера выглядит очень круто — как будто вы смотрите на текст на старом мониторе, который слишком часто роняли на пол и у него «плавает» вертикальная синхронизация и сведение.

Реализация этого эффекта на CSS выглядит вполне убедительно. Мне пришлось немного поломать голову, чтобы выяснить, как он работает, и теперь я хочу объяснить это вам. Кроме того, я воспроизвёл этот эффект не только для текста, но и для растровых изображений и SVG, а так же написал несколько примесей Sass, чтобы облегчить работу с ним.



Три копии текста


HTML для этого примера выглядит просто:

<div class="glitch" data-text="GLITCH">GLITCH</div>

С помощью псевдоэлементов создаются две дополнительные копии основного элемента, которыми можно управлять индивидуально:

.glitch {
  position: relative;
}
.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Все три копии текста расположены друг над другом:

image

Изменяем копии


Каждая из дополнительных копий идентична оригиналу за исключением того, что:

  • они смещены влево или вправо;
  • У них есть цветной ореол, созданный с помощью text-shadow.

Именно смещение и ореол служат основой для эффекта неисправного монитора.

.glitch::before {
  /* ... всё, что нужно, чтобы сделать слой идентичным оригиналу */

  /* отличия от оригинала */
  left: 2px;
  text-shadow: -1px 0 red;
  
  /* Важно: непрозрачный фон закрывает предыдущий слой */
  background: black;
}
.glitch::after {
  /* ... всё, что нужно, чтобы сделать слой идентичным оригиналу */

  /* отличия от оригинала */
  left: -2px;
  text-shadow: -1px 0 blue;
  
  /* Важно: непрозрачный фон закрывает предыдущий слой */
  background: black;
}

Теперь наши три копии выглядят так:

image

Обрезаем копии


Пока что нам видна только самая верхняя из трёх копий. Скорее всего, это версия ::after, если только вы не меняли z-index. Но это не важно, так как мы будем попеременно показывать части всех трёх копий с помощью свойства clip. В данный момент это свойство уже считается устаревшим, его должно заменить clip-path, но на момент написания статьи именно свойство clip работало лучше. Конечно, со временем это изменится, так что нужно иногда поглядывать на ситуацию. В случае чего, их легко будет поменять, например, с помощью Autoprefixer.

У clip довольно странный синтаксис. Требуются четыре значения, логично было бы предположить, что это координаты верхнего левого угла и длина с шириной, или координаты верхнего левого и нижнего правого углов, но вместо этого числа означают отступы, как в свойствах margin или padding (top/right/bottom/left).

.glitch::before {
  clip: rect(44px, 450px, 56px, 0);
  /*
    Получился прямоугольник с верхним левым углом 0, 44px
    и нижним правым 450px, 56px
  */
}

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

image

Анимируем обрезку


Для свойства clip можно использовать анимации CSS, меняя положение обрезающего прямоугольника. Вот пример такой анимации:

@keyframes glitch-anim {
  0% {
    clip: rect(70px, 450px, 76px, 0);
  }
  20% {
    clip: rect(29px, 450px, 16px, 0);
  }
  40% {
    clip: rect(76px, 450px, 3px, 0);
  }
  60% {
    clip: rect(42px, 450px, 78px, 0);
  }
  80% {
    clip: rect(15px, 450px, 13px, 0);
  }
  100% {
    clip: rect(53px, 450px, 5px, 0);
  }
}

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

@keyframes glitch-anim {
  $steps: 10;
  @for $i from 0 through $steps {
    #{percentage($i*(1/$steps))} {
      clip: rect(random(100)+px, 9999px, 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: 100px;
  @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: 2px;
    text-shadow: -1px 0 $highlightColor1;
    animation: #{$name}-anim-1 2s infinite linear alternate-reverse;
  }
  &:before {
    left: -2px;
    text-shadow: 2px 0 $highlightColor2; 
    animation: #{$name}-anim-2 3s infinite linear alternate-reverse;
  }
  
}

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

Я также написал ещё две примеси, одну для растровых изображений, вторую — для SVG. Они отличаются деталями реализации — там не используются псевдоэлементы, смещение и цветной ореол тоже делаются по-другому и т.д. Вот все три примеси в одном файле. А вот так выглядит их работа:



Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 43

    +2
    Можете демку куда-то выложить?
      +14
        +2
        Интересно скачут обрезанные копии, когда выделяешь текст.
        • UFO just landed and posted this here
            +4
            Да ладно вам, мне нравилось)
              0
              Круто! Сразу игрушку вспомнил

              WATCH_DOGS

                0
                Кому что. :) Я вот вспомнил загрузочный экран с кассеты на ZX Spectrum.
                Там за счет высокочастотной смены фона при известной частоте развертки трубки телевизора добивались красивых эффектов различных полосок и даже летающих цветных трубок.

                www.pouet.net/content/screenshots/53846.png

                Интересно, можно ли повторить такое на современных бытовых LCD?
          +1
          Спасибо.
          +1
          По клику на картинку доступны демки.
          +1
          Крутотень. Подумал, что монитор начал умирать.
            +2
            Это супер люкс. Пойду над вконтактиком жены пошучу :)
              +11
              Всем коллективом пошли зарывать пасхалку в рабочий UI :)
                +11
                А закрыте окон сделайте как выключение кинескопа, с характерным сворачиванием в точку.
                  0
                  На Xperia live with walkman примерно так блокировка экрана сделана — изображение «сворачивается». Выглядит лампово.
                    +2
                    На стоковом Android на Nexus 5 этот же эффект. Не мог нарадоваться, как впервые у себя это увидел.
                      0
                      По-моему, это Cyanogen начал, нет?
                +1
                Не думаю, что юзеры оценят.
                • UFO just landed and posted this here
                  +1
                  Эффект на гифке более энергичный, чем в примере. Игрались с параметрами?
                    0
                    Нет, просто запись скринкаста с резкими прыжками, как в этой демке, оказалась довольно нетривиальным делом. Всё, что нашлось в центре приложений убунты пишет видео со сжатием, и гифки получаются замыленные. Пришлось сооружать комбинацию из ffmpeg (то есть уже avconv), imagemagick и gimp — возможно где-то в цепочке не уследил.
                    • UFO just landed and posted this here
                    0
                    Запилить бы плагин к браузеру, чтобы всю страницу делал такой
                    • UFO just landed and posted this here
                      +9
                      На черепушке становится видно, что эффект реализован неправильно. Когда происходит «съезд картинки», то с одной стороны одно получает красного признака, а с другой — циан (синий + зелёный). Легко понять как это происходит — при компоновке люминофора RGB, если фокусировка одного из лучей съежает (чёрт, я вспомнил, как в детстве на ламповом цветном 60 см телевизоре весом примерно 60кг крутил подстрочные ручки для «сведения» картинки — и я даже вспомнил это слово), то он оказывается сдвинут в сторону на сколько-то пикселов. Слева красного много (красный призрак), справа мало (циан призрак).

                      Кстати, если уж делать по совести, но надо все три луча разводить. И каждый в разном направлении, и у каждого должно быть раздельное «гуляние» горизонтальной развёртки.
                        0
                        Я б вообще сказал, что эффект нарушения сведения здесь не в кассу. Сведение будет нарушено либо статически, либо если все шевелится из-за нестабильности напряжений на электромагнитах (если реализовано электронное управление сведением, чтобы через меню можно было крутить) целиком на весь экран, а не в отдельных строках. И вообще все выглядит неестественно: обычно таких четких ступенек не возникает.
                          0
                          Да, дело тут явно в сведении быть не может. Вот когда у RGB кабеля плохо контачит оплетка, рассогласование по волновому сопротивлению выходит там, его неоднородность, возникают в нем отражения, хитрые нарушения АЧХ, в т. ч. и на hsync может влиять. Вот на это больше похоже. Если еще балансом белого на сдвигах играть и придумать как сделать на них троящиеся окантовки отражений, будет совсем хорошо с реализмом.
                          +1
                          А на красном тексте вылезают зелёные ореолы, которых там вообще не может быть в реальности. Эффект смотрится естественно только на белом тексте.
                          +1
                          круто, но у меня видяха и без css делает такие эффекты :)
                          завтра пошучу над дизайнером :)
                          0
                          Вот только это эффект сбоя горизонтальной синхронизации, а не вертикальной. Кажется он зовётся «выбивание строк». При срыве вертикальной синхронизации по вертикали мельтешили бы кадры.
                            0
                            Мне бы флэтизацию лучше. Пробовал комбинировать размытие с малым радиусом и зашкаливающую контрастность — выходит что-то отдалённо похожее, но не плоскота. Интересует решение исходя из возможностей CSS/SVG-фильтров, так-то на JS можно алгоритм реализовать…
                            • UFO just landed and posted this here
                                0
                                Ну понятно, что идеальной перерисовки достичь нереально, но хотя бы разбиение на регионы + однотонная заливка — вполне посильная задача. Но не для CSS…

                            Only users with full accounts can post comments. Log in, please.