スクロールして特定の要素が画面に入ったら、
テキストアニメーションする実装をしたので備忘録として。
CodePen
https://codepen.io/yaajitaake4/pen/zYjvZBO
コード
HTML
index.html
<p class="text">スクロールしてください</p>
<div class="box">
<div class="text-animation">アニメーション01</div>
</div>
<div class="box">
<div class="text-animation">アニメーション02</div>
</div>
CSS(SCSS)
style.scss
// 余白用
.text {
margin-bottom: 1000px;
}
.box {
background-color: #eee;
margin-bottom: 200px;
padding: 100px 0;
}
// アニメーション用
.text-animation {
opacity: 0;
&.show {
opacity: 1;
.text-animation-span {
display: inline-block;
overflow: hidden;
}
span {
display: inline-block;
letter-spacing: 0.1em;
animation: showText .5s backwards;
}
}
}
@keyframes showText {
0% {
opacity: 0;
transform: translateY(100%);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
JavaScript
script.js
document.addEventListener('DOMContentLoaded', () => {
const boxElement = document.querySelectorAll('.box');
const textElement = document.querySelectorAll('.text-animation');
// スクロールしたら表示
document.addEventListener('scroll', () => {
for (let i = 0; i < boxElement.length; i++) {
// windowの上端から要素までの距離 + 要素の高さ(ここで表示のタイミングを調整)
const getElement = boxElement[i].getBoundingClientRect().top + boxElement[i].clientHeight;
if (window.innerHeight > getElement) {
textElement[i].classList.add('show');
}
}
});
for (let i = 0; i < textElement.length; i++) {
const textElements = textElement[i],
animeText = textElements.textContent,
animeTextArray = []; // spanタグで囲んだ文字を格納する
textElements.textContent = ''; // 後ほど追加するので空に
for (let j = 0; j < animeText.split('').length; j++) {
const t = animeText.split('')[j]; // 文字を分割
if (t === ' ') {
animeTextArray.push(' '); // スペースはそのまま格納
} else {
animeTextArray.push( // テキストをspanタグで囲む
'<span class="text-animation-span"><span style="animation-delay: ' + j * 0.1 + 's">' + t + '</span></span>'
);
}
}
// 囲んだ要素を追加
for (let k = 0; k < animeTextArray.length; k++) {
textElements.innerHTML += animeTextArray[k];
}
}
});
今後はintersectionObserverやreduceメソッドを使ったり、
改良していきたいなと思います。