setTimeoutによる時間差アニメーション表示
こんばんは!
今回は実務で普段勉強していることがためになったので、まとめてみようかなと思います。
現在あるサイトを作成してまして、先方からの要望で、あるアニメーションを頼まれました。
実装内容
スクロールイベントでコンテンツを時間差で左右上の順で表示させる。
デモページはこちら↓
まぁ、JSのプラグインの「wow.js」や「animate.css」を組み合わせても簡単なのですが、如何せん重い。。。
この1つの実装のためにプラグインを使用するのは性に合わないので、JSで記述してみました。(JQueryの記述ですが...)
まず、スクロールイベントでよく使用するのは、この記述だと思います。
<!--画像のJS 左から右へ-->
$(function () {
$(window).scroll(function () {
$('.fadeLeft').each(function () {
let targetElement = $(this).offset().top;
let scroll = $(window).scrollTop();
let windowHeight = $(window).height();
if (scroll > targetElement - windowHeight + 200){
this.css('opacity', '1');
this.css('transform', 'translateY(0%)');
}
});
return false;
});
});
上記の記述ではclass名、fadeLeftが付与されているものがウィンドゥの高さから200pxのところまで来ると透過を戻し、位置を元に戻します。
※初めにopacity:0;とtranslateX(-50px)をcssで付けておきます。
普通のfadeinならこれで済むのですが、このままだと3つ一辺にアニメーションされてしまうので、それぞれにsetTimeoutで時間差表示させます。
そこで初めに以下のように記述しました。
<!--画像のJS 左から右へ-->
$(function () {
$(window).scroll(function () {
$('.fadeLeft').each(function () {
let targetElement = $(this).offset().top;
let scroll = $(window).scrollTop();
let windowHeight = $(window).height();
if (scroll > targetElement - windowHeight + 200){
setTimeout(function(){
this.css('opacity', '1');
this.css('transform', 'translateY(0%)');
},500)
}
});
return false;
});
});
setTimeout関数にcssの変化後を追加し、0.5秒後に発火させる。
これで普通にいけるかと思ったのですが、
実装してみると全然動かない!
ここで迷いました_:(´ཀ`」 ∠):
ここでひらめいたのが独学で勉強してたthisの挙動です!!!!
前回のthisの記事で、thisは関数の中に入っていると、クローバルオブジェクトを参照してしまい、jsの記述全体を見てしまいます。
そのため、thisが正しく値を取って来られずに動いていなかったです。
そこで、thisを一旦thatという変数に格納し、それから関数を書いてみました。
<!--画像のJS 左から右へ-->
$(function () {
$(window).scroll(function () {
$('.fadeLeft').each(function () {
let targetElement = $(this).offset().top;
let scroll = $(window).scrollTop();
let windowHeight = $(window).height();
if (scroll > targetElement - windowHeight + 200){
let that = $(this);
setTimeout(function(){
that.css('opacity', '1');
that.css('transform', 'translateY(0%)');
},00)
}
});
return false;
});
});
そうするとうまく動きました!!!
thisの挙動がいかにややこしいかがわかった瞬間ですね。
また、setTimeout自体がthisを正しく評価しないので、上記のように変数で格納するか、bindで束縛する必要があるようです。
SPの際のレイアウト
SPのレイアウトでは以下のデザインでした。
PCの際には、それぞれが0.5秒ごと時間差で表示されるようにJSを記述しました。しかし、SPのレイアウトでは、テキストボックスが下に配置されるので、そのままのJSだと1秒後にしたからふわっと出てきてしまい凄い違和感がありました。
そこでJSをPCの場合のみ1秒後にイベント発火、SPの場合はスクロール後発火に記述し直します。こういう感じです。
<!--テキストボックスのJS 下から上へ-->
$(function () {
$(window).scroll(function () {
$('.fadeUp').each(function () {
let wid = $(window).width();
let targetElement = $(this).offset().top;
let scroll = $(window).scrollTop();
let windowHeight = $(window).height();
if ((wid > 768) && (scroll > targetElement - windowHeight + 200)) {
let that = $(this);
setTimeout(function(){
that.css('opacity', '1');
that.css('transform', 'translateY(0%)');
},1000)
} else if(scroll > targetElement - windowHeight + 200){
let that = $(this);
that.css('opacity', '1');
that.css('transform', 'translateY(0%)');
}
});
return false;
});
});
ここで使えるのが条件分岐ですね!
ウィンドゥ幅が768pxより大きい場合は1秒後に発火させ、
それ以外の場合は普通にスクロール後に発火に記述し直しました。
else if→elseでも良かったかも。
以上の記述で、時間差のアニメーションを作成することが出来ました。
学習していた内容が活きて少し嬉しかったです!
cssアニメーションでも可能な実装だとは思うのですが、JSっていろんなことが可能ですね。ますます好きになりました^ ^