タイピング風のアニメーションを作成
目次
デモ
つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。(Wikipediaより)つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。(Wikipediaより)
解説
使用技術
- TailwindCSS
- JavaScript
以下のコードでAI Chatのようなタイピングのアニメーションを作成することができます。
スクリーンリーダーを使用しているユーザーにも情報を正確に伝える必要があるため aria-labelには本文と同じものを指定してください。
<div class="js-container">
<p class="text-xl leading-relaxed" data-text-type="typing" aria-label="つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。(Wikipediaより)">
つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。(Wikipediaより)つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。(Wikipediaより)
</p>
</div>
またanimationのCSSは独自のものを使用するのでtailwind.cofig.jsには以下の記述を追加してください
export default {
theme: {
keyframes: {
blink: {
"0%, 100%": { opacity: 1 },
"50%": { opacity: 0 },
},
},
// カスタムアニメーションの設定
animation: {
blink: "blink 600ms steps(1) infinite",
},
},
};
テキストをマスクしてタイピング風のアニメーションも作成できるのですが、カーソルを1文字づつ横に移動させるようなアニメーションを実装しようと思うとCSSだけでは難しかったのでJSを使用しています。 テキストを配列に格納し、1文字ずつ表示するようにしています。 1文字表示後末尾にカーソルを移動させるようにしています。
// JavaScript
window.addEventListener("DOMContentLoaded", () => {
const pauseStart = 100;
const typeSpeed = 30;
const textContainer = document.querySelector(".js-container");
const textElement = textContainer.querySelector(
'[data-text-type="typing"]',
);
// テキストを配列に格納
if (!textElement || !textElement.textContent) return;
const textArray = textElement.textContent.split("");
// 文字を非表示にする
textElement.textContent = "";
// 1文字ずつ表示する
let i = 0;
setTimeout(() => {
const interval = setInterval(() => {
if (i >= textArray.length) {
setTimeout(() => {
clearInterval(interval); // アニメーション完了時にclearIntervalでインターバルを停止
// ここに、アニメーション完了後に削除したい要素を消去する処理を追加
const elementToRemove = document.querySelector(".js-cursor");
elementToRemove?.remove();
return;
}, 1500);
}
if (i >= textArray.length) {
clearInterval(interval);
return;
}
textElement.textContent += textArray[i];
textElement.innerHTML +=
'<span class="js-cursor animate-blink pointer-events-none absolute inline-block aspect-[1/20] h-[1lh] bg-black align-top duration-1000"></span>';
i++;
}, typeSpeed); // 1文字あたりの表示速度を調整
}, pauseStart);
});