Имитация ввода текста

Оцените материал
(0 голосов)

Проблема

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

Решение

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

Еще одна вещь, о которой не следует забывать, — каждая анимация по мере увеличения длительности порождает все больший снижающий эффект: короткая анимация делает интерфейс более стильным и в некоторых случаях даже способна повысить удобство использования. Но чем длиннее анимация, тем скорее она начинает раздражать пользователя. Следовательно, даже если эту технику можно было бы применить к длинному многострочному тексту, в большинстве случаев это было бы очень плохой идеей. Приступим к кодированию! Предположим, что мы хотим применить этот эффект к заголовку верхнего уровня ( <h1> ), для которого мы уже определили стиль, включающий моноширинный шрифт, и который выглядит так:

HTML
<h1>CSS is awesome!</h1>

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


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

@keyframes typing {
from { width: 0 }
}
h1 {
width: 7.7em; /* Ширина текста */
animation: typing 8s;
}

Все правильно, ведь так? Однако, как вы видите на рисунке выше, у этого безобразия нет ничего общего с эффектом, которого мы хотели добиться. Наверное, вы уже догадались, в чем проблема. Вопервых, мы забыли применить  white-space: nowrap; для предотвращения переноса текста на новую строку, поэтому по мере увеличения ширины элемента количество строк меняется.

Во-вторых, мы забыли применить  overflow: hidden; поэтому обрезания не происходит. Исправив эти недочеты, мы начинаем видеть реальные проблемы нашей анимации, а именно:
‰ очевидно, что анимация получается плавной, вместо того чтобы отображать текст символ за символом;‰ менее очевидная проблема заключается в том,что до сих пор мы указывали ширину в единицах измерения  em, что, конечно, лучше, чем делать это в пикселах, но тоже не идеально. Откуда взялось значение 7,7?  Как его вычислить?

Первую проблему можно решить с помощью функции расчета времени  steps(), как это описано в уроке  «Как сделать покадровую анимацию» и «Как сделать мерцающую анимацию». К сожалению, требуемое количество шагов равно количеству символов в нашей строке, а значит, такой код будет сложно поддерживать, а в случае динамического текста — попросту невозможно создать. Однако, как мы увидим чуть далее, вычисление этого значения можно автоматизировать, используя крошечный фрагмент кода JavaScript. Обойти вторую проблему нам помогут единицы измерения  ch .  ch — это одна из новых единиц измерения, которая была добавлена в спецификации CSS и представляет ширину глифа 0.

Это одна из наименее известных новых единиц измерения, так как в большинстве случаев нас мало волнует возможность определять размеры элементов относительно ширины глифа 0. Однако моноширинные шрифты — особый случай. В моноширинных шрифтах ширина глифа 0 совпадает с шириной любого другого глифа. Следовательно, для того чтобы задать ширину в единицах измерения  ch, нужно указать количество символов. В нашем примере их  15 . Соберем все вместе:

@keyframes typing {
from { width: 0; }
}
h1 {
width: 15ch; /* Ширина текста */
overflow: hidden;
white-space: nowrap;
animation: typing 6s steps(15);
}

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

Догадаетесь, чего не хватает?

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

@keyframes typing {
from { width: 0 }
}
@keyframes caret {
50% { border-color: transparent; }
}
h1 {
width: 15ch; /* Ширина текста */

overflow: hidden;
white-space: nowrap;
border-right: .05em solid;
animation: typing 6s steps(15),
caret 1s steps(1) infinite;
}


Обратите внимание, что, в отличие от анимационного эффекта для отображения текста, курсор должен мерцать бесконечно (даже после того, как мы показали весь текст), отсюда и ключевое слово infinite. Помимо этого, мы не указываем цвет рамки, так как он должен определяться автоматически и совпадать с цветом текста. Несколько кадров из результирующей анимации показанына рисунке.


Наша анимация работает просто великолепно, но проблему сопровождения этого кода мы пока не решили: для каждого заголовка необходимо определять собственный стиль, зависящий от количества символов, и обновлять значения каждый раз, когда мы меняем что-то в содержимом. Это как раз та задача, с которой превосходно способен справиться JS:
JS
$$('h1').forEach(function(h1) {
var len = h1.textContent.length, s = h1.style;
s.width = len + 'ch';
s.animationTimingFunction = "steps("+len+"),steps(1)";
});

Эти несколько строк кода JS позволяют нам успешно догнать и схватить обоих зайцев: наша анимация не только реалистично выглядит, но и проста в сопровождении! Все это прекрасно, но что произойдет, если окажется, что браузер не поддерживает анимацию CSS? По сути, такой браузер пропустит весь код, как-либо связанный с анимацией, и прочитает только следующее:
h1 {
width: 15ch; /* Ширина текста */
overflow: hidden;
white-space: nowrap;
border-right: .05em solid;
}
В зависимости от того, поддерживает ли такой браузер единицы измерения ch, пользователь увидит один из запасных вариантов, показанных на рисунке ниже.


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

@keyframes caret {
50% { border-color: currentColor; }
}
h1 {
/* ... */
border-right: .05em solid transparent;
animation: typing 6s steps(15),
caret 1s steps(1) infinite;
}

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

ПОПРОБУЙТЕ САМИ!

http://play.csssecrets.io/typing

Десерт на сегодня - прыжок с высоты 233 метров:

Прочитано 350 раз Последнее изменение Суббота, 24 июня 2017 14:00
Другие материалы в этой категории:
Понравилась запись? Подпишитесь на обновления по почте:

Нетология

TemplateMonster

geekbrains.ru/

Поиск по сайту

Google+