見出し画像

setTimeoutによる時間差アニメーション表示

こんばんは!
今回は実務で普段勉強していることがためになったので、まとめてみようかなと思います。
現在あるサイトを作成してまして、先方からの要望で、あるアニメーションを頼まれました。


実装内容
スクロールイベントでコンテンツを時間差で左右上の順で表示させる。

グループ 7

デモページはこちら↓

まぁ、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のレイアウトでは以下のデザインでした。

スクリーンショット 2022-02-18 0.51.44

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っていろんなことが可能ですね。ますます好きになりました^ ^







大阪在住の29歳。web制作会社勤務。noteを通してたくさんの出会いを作っていきたいです。台湾が大好きで中国語勉強中。日台夫婦。日々の挑戦の記録や、社会の生きづらさ、台湾のことなどを書いていこうと思います。2023年台湾に移住予定です。