目的
webアプリやサイトを構築する時って、インタラクティブな演出(スクロールするとアニメーションする、クリックすると光るetc)を入れるとリッチだなって人は認識すると思うのですが、機能ではないので工数との兼ね合いもあって優先はされないものだと思います。
プラグインも良いんですが、機能編集とか面倒なので
- 低コストなら今後使われやすい
- 弱い分野なのでスキルアップできる
- 拡張が簡単
- 編集が簡単
- 今後サンプルとしてデザイナやディレクタに見せれた方がやりやすい(この動きどうですか?っていう提案ができる)
こんな理由で取り組んでみました。
レイジーロード
参考:https://www.hoshinoresorts.com/recruit/
レイジーはjavascriptで表示領域内にコンテンツが来たら表示するっていう機能を作ってあげれば、あとはcssで簡単にリッチ感を出していけるかなと思ったので、今回はレイジーに取り組みました。表示される時のアニメーションの作成・編集を簡単にして、バリエーションを出したいと思います。
SEO観点では、プロジェクトではあんまり使われないですが、コンテンツを選べば大丈夫かと思います。
(display:noneはダメってよく聞くけど、opacity:0もダメなのかな)
サンプル
<!--index.html-->
・・・
<ul>
<li><div class="item" data-scroll-anime="in_blur_up"></div></li>
<li><div class="item" data-scroll-anime="in_blur_rotate_up"></div></li>
</ul>
・・・
スクロールした時、data属性のvalueをそのままclassに当てます。
/* css */
/* in_blur_up */
.item.isActive.in_blur_up {
animation: in_blur_up 1s ease-in-out;
}
@keyframes in_blur_up {
from {
opacity: 0;
filter: blur(10px);
transform: translateY(25%);
}
to {
opacity: 1;
filter: blur(0);
transform: translateY(0);
}
}
data属性のclassがついた時、keyframesで1度アニメーションします
class scrollAnimation {
constructor() {
this.setParameter();
this.setItemsInfo();
this.bindEvent();
}
setParameter() {
this.items = [];
this.$item = document.querySelectorAll(".item");
}
setItemsInfo() {
for (let i = 0; i <= this.$item.length - 1; i++) {
const obj = {};
const item = this.$item[i];
obj.item = item;
obj.offsetTop = item.offsetTop;
obj.itemHeight = item.offsetTop + item.clientHeight;
this.items = [...this.items, obj];
}
}
bindEvent() {
window.addEventListener("scroll", () => this.addAnimation());
}
addAnimation() {
const scrollTop = window.scrollY;
const scrollBottom = scrollTop + window.innerHeight;
this.items.forEach(item => {
if (
item.offsetTop === 0 ||
(scrollTop <= item.offsetTop && scrollBottom >= item.itemHeight)
) {
item.item.classList.add("isActive");
if (item.item.dataset.scrollAnime) {
item.item.classList.add(item.item.dataset.scrollAnime);
}
}
});
}
}
new scrollAnimation();
objectを生成します。
itemとitemのy位置、y+itemの高さで登録します。
scrollイベントの中で、objectをeachして、画面内にアイテムがあれば、classを追加します。
scrollのなかで、eachしているので処理が重い部分を
どうにかしたいのが今後の課題です。
得た知識(めも)
①水平スクロールバー(表示されている場合)を含む、ブラウザウィンドウの ビューポート (viewport) の高さを返します。
var intViewportHeight = window.innerHeight;
②要素の高さ、幅の取得
var client_w = document.getElementById('box').clientWidth;
var client_h = document.getElementById('box').clientHeight;
③add class
element.classList.add("mystyle");
④data属性の取得
// data-name="tarou"だった場合
var name = document.getElementById('item').dataset.name;
// name = tarou
終わりに
todo:
パフォーマンスチューニング