【Веб-анимация】Мрачная анимация дождя, полная технологий

внешний интерфейс JavaScript CSS
【Веб-анимация】Мрачная анимация дождя, полная технологий

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

Digital Char Rain Animation

Или что-то вроде этого:

CodePen Home Matrix digital rain (animated version) By yuanchuan

Используется на некоторых фонах, похожих на технологические темы, это очень затягивает.

вертикальный текст

Первый шаг — реализовать вертикальное расположение текста:

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

  1. Используйте свойства, управляющие выравниванием текстаwriting-modeконтролируетсяwriting-mode: vertical-lrи т. д. расположит текст вертикально, но для чисел и английского языка он будет повернут на 90° для отображения:
<p>1234567890ABC</p>
<p>中文或其他字符ォヶ</p>
p {
    writing-mode: vertical-lr; 
}

Конечно, в данном случае отображение английских символов нам не подходит.

  1. Контролируйте ширину контейнера и контролируйте, чтобы в строке отображался только 1 китайский символ.

Этот метод является наиболее простым и удобным, но из-за специфики английского языка для естественного переноса непрерывных длинных строк нам также необходимо сотрудничать.word-break: break-all:

p {
    width: 12px;
    font-size: 10px;
    word-break: break-all;
}

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

Случайный выбор строки с помощью CSS

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

Но слишком сложно заставить CSS случайным образом генерировать символы для каждой строки. Итак, здесь мы используем препроцессор CSS SASS/LESS.

И поскольку маловероятно использовать CSS для переноса одного тега, например<p>Метка вставляет символы, поэтому мы отображаем символы в метке и помещаем их в каждую<p>псевдоэлемент элемента::beforeизcontentсреди.

Мы можем заранее установить набор строк, а затем использовать функцию SASS, случайно генерируемую в каждом элементеcontent, псевдокод выглядит следующим образом:

<div>
    <p></p>
    <p></p>
    <p></p>
</div>
$str: 'ぁぃぅぇぉかきくけこんさしすせそた◁▣▤▥▦▧♂♀♥☻►◄▧▨♦ちつってとゐなにぬねのはひふへほゑまみむめもゃゅょゎをァィゥヴェォカヵキクケヶコサシスセソタチツッテトヰンナニヌネノハヒフヘホヱマミムメモャュョヮヲㄅㄉㄓㄚㄞㄢㄦㄆㄊㄍㄐㄔㄗㄧㄛㄟㄣㄇㄋㄎㄑㄕㄘㄨㄜㄠㄤㄈㄏㄒㄖㄙㄩㄝㄡㄥabcdefghigklmnopqrstuvwxyz123456789%@#$<>^&*_+';
$length: str-length($str);

@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}

@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

p:nth-child(1)::before {
    content: randomChars(25);
}
p:nth-child(2)::before {
    content: randomChars(25);
}
p:nth-child(3)::before {
    content: randomChars(25);
}

Кратко объясните приведенный выше код:

  1. $strопределяет строку случайных строк,$lengthУказывает длину строки
  2. randomChar() использует SASSrandom()метод, случайным образом выбирая 0 -$lengthЦелое число, обозначено как$r, повторное использование SASSstr-sliceметод, каждый раз с$strВыберите индекс как$rслучайные персонажи
  3. randomChars() заключается в вызове метода randomChar() в цикле из$strПроизвольно сгенерировать строку строк, длина - это параметр, переданный в$number

Таким образом, символы в каждом столбце каждый раз разные:

Конечно вышеописанный способ не самый лучший на мой взгляд, псевдоэлемент CSScontentОн поддерживает кодировку символов, напримерcontent: '\3066';будут отображаться как символы, таким образом, установив интервал символов, случайные символы могут быть лучше сгенерированы с помощью функции SASS, но я пытался в течение длительного времени, и конечный продукт, сгенерированный функцией SASS, будет в\а также3066Добавление пробелов между такими числами не может быть преобразовано в символы с помощью кодировки символов и, наконец, сдается...

Ввод с помощью CSS

Хорошо, продолжайте, далее нам нужно использовать CSS для достижения эффекта набора текста, то есть пусть символы появляются один за другим, вот так:

纯 CSS 实现文字输入效果

Здесь с помощью анимацииstepsРеализация фичи, то есть покадровая анимация.

Принцип слева направо тот же, что и сверху вниз.Возьмем для примера слева направо.Предположим,у нас есть 26 английских символов.Мы знаем длину строки, состоящей из 26 английских символов.Тогда нам нужно только установить анимация, которая меняет свою ширину от0 - 100%После 26 кадров вы можете сотрудничать сoverflow: hidden, каждый кадр шагов может отображать один символ.

Конечно, необходимо использовать несколько советов, как мы узнаем длину строки по количеству символов, которые она?

Сфокусируйся на:Благодаря характеристикам моноширинных шрифтов с CSS вchединица измерения.

Если вы не знаете, что такое семейство моноширинных шрифтов, вы можете прочитать эту мою статью —«Семейство шрифтов, которое вы должны знать».

В CSS,chЕдиница представляет собой ширину числа «0». Если шрифт является моноширинным шрифтом, то есть ширина каждого символа одинакова, тоchможет стать шириной каждого английского символа, тогда26chНа самом деле это длина всей строки.

Используйте эту функцию, чтобы соответствовать анимацииsteps, мы можем легко использовать CSS для достижения эффекта анимации при наборе текста:

<h1>Pure CSS Typing animation.</h1>
h1 {
    font-family: monospace;
    width: 26ch;
    white-space: nowrap;
    overflow: hidden;
    animation: typing 3s steps(26, end);
}

@keyframes typing {
    0{
        width: 0;
    }
    100% {
        width: 26ch;
     }
}

Вы можете получить следующие результаты:

纯 CSS 实现文字输入效果

Вы можете нажать здесь для полного кода:

CodePen Demo — чистый CSS для достижения эффекта ввода текста

Превратить в эффект вертикального набора текста

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

Основной псевдокод выглядит следующим образом:

<div>
    <p></p>
    <p></p>
    <p></p>
</div>
$str: 'ぁぃぅぇぉかきくけこんさしすせそた◁▣▤▥▦▧♂♀♥☻►◄▧▨♦ちつってとゐなにぬねのはひふへほゑまみむめもゃゅょゎをァィゥヴェォカヵキクケヶコサシスセソタチツッテトヰンナニヌネノハヒフヘホヱマミムメモャュョヮヲㄅㄉㄓㄚㄞㄢㄦㄆㄊㄍㄐㄔㄗㄧㄛㄟㄣㄇㄋㄎㄑㄕㄘㄨㄜㄠㄤㄈㄏㄒㄖㄙㄩㄝㄡㄥabcdefghigklmnopqrstuvwxyz123456789%@#$<>^&*_+';
$length: str-length($str);

@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}

@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

p {
    width: 12px;
    font-size: 10px;
    word-break: break-all;
}

p::before {
    content: randomChars(20);
    color: #fff;
    animation: typing 4s steps(20, end) infinite;
}

@keyframes typing {
    0% {
        height: 0;
    }
    25% {
        height: 100%;
    }
    100% {
        height: 100%;
    }
}

Таким образом, мы достигаем эффекта вертикального набора текста:

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

Исходя из этого делаем 2 преобразования:

  1. В зависимости от продолжительности анимацииanimation-time, и задержка анимацииanimation-delay, увеличивая случайность в определенном диапазоне
  2. В конце или во время каждой анимации повторно заменяйте псевдоэлементcontent, то есть регенерироватьcontent

Этого очень легко добиться с помощью SASS.Основной код SASS выглядит следующим образом:

$n: 3;
$animationTime: 3;
$perColumnNums: 20;

@for $i from 0 through $n {
    $content: randomChars($perColumnNums);
    $contentNext: randomChars($perColumnNums);
    $delay: random($n);
    $randomAnimationTine: #{$animationTime + random(20) / 10 - 1}s;

    p:nth-child(#{$i})::before {
        content: $content;
        color: #fff;
        animation: typing-#{$i} $randomAnimationTine steps(20, end) #{$delay * 0.1s * -1} infinite;
    }

    @keyframes typing-#{$i} {
        0% {
            height: 0;
        }
        25% {
            height: 100%;
        }
        100% {
            height: 100%;
            content: $contentNext;
        }
    }
}

Взгляните на эффект, было хорошее улучшение:

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

Конечно, при быстрой анимации это почти незаметно.

Увеличение изменения света и тени и прозрачности

Последним шагом будет увеличение изменений света и тени и прозрачности.

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

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

Последний способ — позаимствовать еще один псевдоэлемент для синхронизации маски для достижения конечного эффекта. Давайте пошагово рассмотрим процесс.

Добавляйте яркие цвета и выделяйте текст

Первым шагом является добавление ярких цветов и бликов к тексту.Это очень просто, просто выберите яркий цвет под черным фоном и используйтеtext-shadowПусть текст сияет.

p::before {
    color: rgb(179, 255, 199);
    text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 5px currentColor, 0 0 10px currentColor;
}

Взгляните на эффект: слева — белый символ, посередине — изменение цвета символа, а справа — изменение цвета шрифта и добавление тени шрифта:

Добавить маску синхронизации к тексту

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

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

蒙层遮罩原理图

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

p::after {
    content: '';
    background: linear-gradient(rgba(0, 0, 0, .9), transparent 75%, transparent);
    background-size: 100% 220%;
    background-repeat: no-repeat;
    animation: mask 4s infinite linear;
}

@keyframes mask {
    0% {
        background-position: 0 220%;
    } 
    30% {
        background-position: 0 0%;
    }
    100% {
        background-position: 0 0%;
    }
}

Ну, окончательный эффект вместе, наверное, такой:

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

Полный код и эффект

Хорошо, разобрали основные шаги и, наконец, перешли к полному коду, применив механизм шаблонов Pug и синтаксис SASS.

Полный код занимает не более 100 строк.

.g-container
    -for(var i=0; i<50; i++)
        p
@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@200&display=swap');

$str: 'ぁぃぅぇぉかきくけこんさしすせそた◁▣▤▥▦▧♂♀♥☻►◄▧▨♦ちつってとゐなにぬねのはひふへほゑまみむめもゃゅょゎをァィゥヴェォカヵキクケヶコサシスセソタチツッテトヰンナニヌネノハヒフヘホヱマミムメモャュョヮヲㄅㄉㄓㄚㄞㄢㄦㄆㄊㄍㄐㄔㄗㄧㄛㄟㄣㄇㄋㄎㄑㄕㄘㄨㄜㄠㄤㄈㄏㄒㄖㄙㄩㄝㄡㄥabcdefghigklmnopqrstuvwxyz123456789%@#$<>^&*_+';
$length: str-length($str);
$n: 50;
$animationTime: 4;
$perColumnNums: 25;

@function randomChar() {
    $r: random($length);
    @return str-slice($str, $r, $r);
}

@function randomChars($number) {
    $value: '';

    @if $number > 0 {
        @for $i from 1 through $number {
            $value: $value + randomChar();
        }
    }
    @return $value;
}

body, html {
    width: 100%;
    height: 100%;
    background: #000;
    display: flex;
    overflow: hidden;
}

.g-container {
    width: 100vw;
    display: flex;
    justify-content: space-between;
    flex-wrap: nowrap;
    flex-direction: row;
    font-family: 'Inconsolata', monospace, sans-serif;
}

p {
    position: relative;
    width: 5vh;
    height: 100vh;
    text-align: center;
    font-size: 5vh;
    word-break: break-all;
    white-space: pre-wrap;
    
    &::before,
    &::after {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 100%;
        overflow: hidden;
    }
}

@for $i from 0 through $n {
    $content: randomChars($perColumnNums);
    $contentNext: randomChars($perColumnNums);
    $delay: random($n);
    $randomAnimationTine: #{$animationTime + random(20) / 10 - 1}s;
  
    p:nth-child(#{$i})::before {
        content: $content;
        color: rgb(179, 255, 199);
        text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 5px currentColor, 0 0 10px currentColor;
        animation: typing-#{$i} $randomAnimationTine steps(20, end) #{$delay * 0.1s * -1} infinite;
        z-index: 1;
    }

    p:nth-child(#{$i})::after {
        $alpha: random(40) / 100 + 0.6;
        content: '';
        background: linear-gradient(rgba(0, 0, 0, $alpha), rgba(0, 0, 0, $alpha), rgba(0, 0, 0, $alpha), transparent 75%, transparent);
        background-size: 100% 220%;
        background-repeat: no-repeat;
        animation: mask $randomAnimationTine infinite #{($delay - 2) * 0.1s * -1} linear;
        z-index: 2;
    }

    @keyframes typing-#{$i} {
        0% {
            height: 0;
        }
        25% {
            height: 100%;
        }
        100% {
            height: 100%;
            content: $contentNext;
        }
    }
}

@keyframes mask{
    0% {
        background-position: 0 220%;
    } 
    30% {
        background-position: 0 0%;
    }
    100% {
        background-position: 0 0%;
    }
}

Окончательный эффект показан на заглавном изображении:

Digital Char Rain Animation

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

CodePen Demo -- Digital Char Rain Animation

наконец

ВдохновленЮань ЧуанЭффект учителяCodePen Demo -- Matrix digital rain, исходный эффект реализован с помощью JavaScript. В этой статье для вывода используется чистый CSS.

Другие замечательные эффекты CSS могут следовать за мнойCSS-вдохновение

Ну вот и конец этой статьи, надеюсь она вам поможет :)

Если вы хотите получить самую интересную информацию о CSS, не пропустите мой официальный аккаунт --Интересные факты о внешнем интерфейсе iCSS😄

Другие замечательные технические статьи по CSS собраны в моемGithub -- iCSS, продолжайте обновлять, добро пожаловать, нажмите звездочку, чтобы подписаться на коллекцию.

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