ウェブのリッチな表現としてスクロールに応じたエフェクトがあります。これまでJavaScriptの .addEventListener
の scroll
イベントで実装していましたが、Intersection Observer API
を使うと簡単で効率良く実装できます。
この記事では、そんな Intersection Observer API
を使ってタイピング風アニメーションを作っています。
ぜひ参考にしてみてください。
Intersection Observer API
Intersection Observer APIを、Google翻訳で訳すと「交差点オブザーバーAPI」という名前です。これは要素と要素の交差を検知するAPIです。
スクロールに対応したアニメーションは、「Intersection Observer API」で要素の検知をして、アニメーションをCSSで別途作ることで、簡単にスクロールアニメーションを実装することができます。
以下に詳しくあるので、こちらもあわせて参考にしてみてください。
参考 Intersection Observer APIMDN web docsタイピング風アニメーションで表示されるサンプル
早速サンプルです。このブロックがビューボートに入ると、テキストがタイピングされるように表示されていきます。
もう一度はじめからアニメーションを見る場合、ここのエリアを表示域から一旦外してもう一回戻ってみてください。
実装の手順と方法
コードの解説の前に、実装の手順と方法について解説します。
はじめに、設置したい場所にHTMLを記述します。
<div class="text">タイピング風に表示されるテキスト</div>
次に、JavaScriptのコードをページに記述します。
コードは <body>〜</body>
で、</body>
の閉じタグ(クロージングタグ)の前に記述しましょう。
const doObserve = (element) => {
const targets = document.querySelectorAll('.text'); /* ターゲットの指定 */
const options = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver((items) => {
items.forEach((item) => {
if (item.isIntersecting) {
item.target.classList.add('typing'); /* スクロールでターゲットに付与するclassの指定 */
} else {
item.target.classList.remove('typing'); /* 表示域から外れた時にターゲットから削除するclassの指定 */
}
});
}, options);
Array.from(targets).forEach((target) => {
observer.observe(target);
});
};
doObserve('.observe_target');
最後に、CSSを記述します。
.text.typing {
display: inline-block;
width: 100%;
overflow: hidden;
white-space: nowrap;
border-right: 2px solid transparent;
animation: typing 3s steps(23), caret 0.3s steps(1) infinite;
margin: 0;
line-height: 1.7;
max-width: 300px;
font-size: 1.1rem;
}
@keyframes typing {
from {
width: 0;
}
}
@keyframes caret {
50% {
border-right-color: currentColor;
}
}
これで完成です。
ざっくりとしたコードの解説
コードは、HTML・JavaScript・CSSの3種です。順に解説していきます。
HTML
HTMLは以下の通り、要素を記述します。
<div class="text">タイピング風に表示されるテキスト</div>
JavaScriptで、指定したセレクタに一致するすべてのHTML要素を取得する .querySelectorAll
で「text」のclass名を指定しています。その為、これ以外の要素に「text」のclass名が付く要素がある場合、それらにもアニメーションが適応されます。
JavaScript
JavaScriptは、ざっくり言うと「ターゲットの指定」を行い、条件分岐で処理方法をそれぞれ記述します。
const doObserve = (element) => {
const targets = document.querySelectorAll('.text'); /* ターゲットの指定 */
const options = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver((items) => {
items.forEach((item) => {
if (item.isIntersecting) {
item.target.classList.add('typing'); /* スクロールでターゲットに付与するclassの指定 */
} else {
item.target.classList.remove('typing'); /* 表示域から外れた時にターゲットから削除するclassの指定 */
}
});
}, options);
Array.from(targets).forEach((target) => {
observer.observe(target);
});
};
doObserve('.observe_target');
具体的には、冒頭にある option
で「root」のキーを「null」に設定することで、要素がウィンドウに入ったかどうかの検知ができるようになります。
そして、検知された時に実行される処理は、まず IntersectionObserver
を作成し、要素に対しての検知を行なっていくと、検知したオブジェクトを取得できるようになります。
その中に「isIntersecting」というキーがあり、対象要素が検知されると値がtrue、外れるとfalseを返すというのを使って条件分岐させることで、検知されたタイミングでの処理が可能になり、このコードでは、class名の追加・削除をそれぞれ行なっています。
CSS
CSSは、@keyframes
で作ったアニメーションを指定テキストにあてる記述です。
.text.typing {
display: inline-block;
width: 100%;
overflow: hidden;
white-space: nowrap;
border-right: 2px solid transparent;
animation: typing 3s steps(23), caret 0.3s steps(1) infinite;
margin: 0;
line-height: 1.7;
max-width: 300px;
font-size: 1.1rem;
}
@keyframes typing {
from {
width: 0;
}
}
@keyframes caret {
50% {
border-right-color: currentColor;
}
}
比較的コード量も少なく、JavaScriptでclass名をあててアニメーションを動かすので、カスタマイズもしやすいと思います。
さいごに
個人的にも、スクロールで画面内に入ったら処理を実行する機能をよく実装しますが、スクロールをトリガーにした処理が簡単にできるので非常に重宝しています。
.addEventListener
の scroll
イベント以外の方法として、ぜひ試してみてください。