ページ表示時にタイプライター風にテキストを表示します。カーソルの点滅動作はCSSで実装します。
タイプライター風テキスト
htmlのコードは下記になります。カーソルは空のspanタグで表示します。
<p id="js-visual_txt" class="visual_txt"><b>タイプライター風テキスト</b><span class="visual_cursor"></span></p>
続いてCSSのコードです。
テキストとカーソルはフレックスボックスで横並びにします。テキストはspanタグで内包してbタグ内に出力しますが、このspanタグもフレックスボックスで横並びにします。spanタグには動的にカスタムデータ属性を付与しますが、カスタムデータ属性の値がload以外の時は横幅を0で設定し、値がloadになった時点で1emにします。
カーソルには点滅するanimationを指定します。点滅は止めないためanimation-iteration-count: infiniteを指定します。また点滅の動作は@keyframes以外にanimation-timing-function: steps(1)とanimation-direction: alternateで実現しています。
.visual_txt {
font-size: 40px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
}
.visual_txt.isLoaded {
opacity: 1;
}
.visual_txt > b {
display: flex;
align-items: center;
}
.visual_txt > b > [data-char] {
display: block;
width: 0;
overflow: hidden;
transition-property: width;
transition-duration: 0s;
}
.visual_txt > b > [data-char="load"] {
width: 1em;
}
.visual_cursor {
display: block;
width: 2px;
height: 40px;
background: #000;
animation-name: cursor;
animation-duration: 0.5s;
animation-iteration-count: infinite;
animation-timing-function: steps(1);
animation-fill-mode: backwards;
animation-direction: alternate;
}
@keyframes cursor {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 1;
}
}
@media screen and (max-width: 680px) {
.visual_txt {
font-size: 20px;
}
.visual_cursor {
width: 1px;
height: 20px;
}
}
最後にjQueryのコードです。
まず1番目の処理として、spritStr関数を呼び出してテキストを1文字ずつspanタグで内包します。その際カスタムデータ属性をinitの値で付与します。次にタイプライター風に時間差でテキストが表示されるように、1文字ずつspanタグのCSSにtransition-delayを設定します。最後にprop(‘outerHTML’)で要素自身を含めたhtmlを変数htmlに代入していきます。これを文字の数だけ繰り返して、spanタグをbタグ内にセットします。
2番目の処理はテキストとカーソルを含むpタグにクラス名isLoadedを付与します。これでpタグのopacityは1となりますが、spanタグはwidth: 0のためまだ非表示の状態です。
最後に3番目の処理として、spanタグのカスタムデータ属性の値をinitからloadへ変更します。これでspanタグのwidthが1emとなります。ポイントはsetTimeoutを入れてinitとloadの状態に時間差を付けることです。この処理がないとtransition-delayが発動できず、全ての文字が1度に表示されてしまいます。
$(function() {
function spritStr(str) {
var html = '',
obj;
for (i = 0; i < str.length; i++) {
obj = $('<span data-char="init">' + str.substr(i, 1) + '</span>');
$(obj).css({
'transition-delay': i * 0.2 + 's'
});
html += $(obj).prop('outerHTML');
}
return html;
}
$('#js-visual_txt > b').html(spritStr($('#js-visual_txt > b').text()));
$('#js-visual_txt').addClass('isLoaded');
setTimeout(function () {
$('#js-visual_txt > b > [data-char="init"]').attr('data-char', 'load');
}, 100);
});