👌
スクロール量を1回だけ取得するロジックのテスト
const getPosition = () => {
const scrollTop = window.pageYOffset;
offsetTop = el.getBoundingClientRect().top + scrollTop;
endPosition = offsetTop + el.clientHeight;
winHeight = window.innerHeight;
}
getPosition();
window.addEventListener('resize', getPosition);
先日公開した記事について
ScrollFunctionクラス内でGetPositionをインスタンス化して実行すると、オブザーバー領域に入った要素毎にスクロール量を取得してしまう。
本来であれば1回だけ取得すればいい。
1回だけ取得するにはオブザーバー領域にあるインスタンスの最後の要素がスクロール量を取得すれば良いのではないかと考えた。
以下はスクロール量を1回だけ取得するロジックのテストとして記載する。
なお頭の中で考えただけなので、まだ未検証である。
実際に検証したところ、if文で領域内にある最後のインスタンスでのみscrollTopを取るので、他のインスタンスに関して領域内にあってもアニメーションしない(scrollTopを取れてないので)
よって、このロジックは間違いでした。。
このクソコードはここで供養します🙏
class GetPosition {
constructor() {
}
getScrollTop() {
return window.pageYOffset;
}
}
//それぞれのインスタンスがオブザーバー領域にあるか判別するための配列
let sfFlgs = [];
new ScrollFunction(".js-01", 500, "-30%", "10%", "80%", sfFlgs);
new ScrollFunction(".js-02", 500, "-30%", "10%", "80%", sfFlgs);
new ScrollFunction(".js-03", 500, "-30%", "10%", "80%", sfFlgs);
class ScrollFunction {
static Count = 0; //インスタンス化の個数初期値
constructor(target, scrollMax, rootMargin, Min, Max, fps = 60, sfFlgs) {
...
this.sfFlgs = sfFlgs;
this.sfCount = ScrollFunctionAll.Count;
this.sfFlgs[this.sfCount] = false; //flgs配列にfalseを代入しておく
ScrollFunctionAll.Count += 1; //個数+1
this.scrollAnimation();
}
_scrollFunction() {
...
const gp = new GetPosition();
...
let scrollTop;
let trueNum = 0; //flgsのtrueの数
const scrollAnime = (timestamp) => {
//flgs配列のアイテムがtrueならtrueNumに加算する
for(let i = 0; i < this.sfFlgs.length; i++) {
if(this.sfFlgs[i]) {
trueNum += 1;
}
}
//flgsアイテムが1つのみでtrue
if(this.sfFlgs[0] && this.sfFlgs.length == 1) {
scrollTop = gp.getScrollTop();
} else { //flgsアイテム2つ目以降について
//trueかつflgs配列のtrueの数が1つ(オブザーバー領域に1つのアイテムしか存在しない)
if(this.sfFlgs[this.sfCount] && trueNum == 1) {
scrollTop = gp.getScrollTop();
//trueかつflgs配列のtrueの数が2つ以上(オブザーバー領域に複数存在)かつ最後の要素
} else if(this.sfFlgs[this.sfCount] && trueNum > 1 && this.sfCount == (this.sfFlgs.length - 1)) {
scrollTop = gp.getScrollTop();
}
}
trueNum = 0; //初期化
if (isVisible) {
frameId = requestAnimationFrame(scrollAnime);
}
}
frameId = requestAnimationFrame(scrollAnime);
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
isVisible = entry.isIntersecting;
if (isVisible) {
this.sfFlgs[this.sfCount] = true;
frameId = requestAnimationFrame(scrollAnime);
} else {
this.sfFlgs[this.sfCount] = false;
//画面外のときは削除
cancelAnimationFrame(frameId);
}
});
});
//observer監視開始
observer.observe(el);
});
}
}
Discussion