いわりょのBlog

IT関連で学んだことを書いていきます。

複数の写真を時間差で表示させる

実現すること

↑こんなの

方法

まずはざっとHTMLを書いていきます。

    <div class="wrapper grid">
            <div class="item img-fade-up'">
                <img src="image_1.jpg">
            </div>
            <div class="item img-fade-up'">
                <img src="image_2.jpg">
            </div>
            <div class="item img-fade-up'">
                <img src="image_3.jpg">
            </div>
            <div class="item img-fade-up'">
                <img src="image_4.jpg">
            </div>
            <div class="item img-fade-up'">
                <img src="image_5.jpg">
            </div>
            <div class="item img-fade-up'">
                <img src="image_6.jpg">
            </div>
    </div><!--wrapper grid-->

表示方法はグリッドプロパティを使うので親要素をクラスgridとして、表示する6枚の写真はクラスitemにします。
クラスimg-fade-upはエフェクト用で使います。

見た目調節

//幅や余白調整
.wrapper{
    max-width: 1100px;
    margin: 0 auto;
    padding:0 4%;
}

//表示をグリッド形式にして調整
.grid{
    display: grid;
    gap: 26px;
    grid-template-columns: repeat(auto-fit,minmax(250px ,1fr));
    margin-bottom: 50px;
}

//写真の調整
.item img{
    width:100%;
    height: 350px;
    object-fit: cover;
}
エフェクト用のCSS

//好みの位置にずらして消しておく。
.img-fade-up {
    opacity: 0;
    transform : translate(0, 40px);
    transition : all .7s;
}

//クラスが追加されたときの状態
.img-fade-up.effect-scroll{
    opacity : 1;
    transform : translate(0, 0);
}

これだけでは何も動かないのでJavascriptを追加していきます。
jQueryだと簡単です。
今回は指定したところまでスクロールされた時に、写真が表示させるようにしていきます。

$(window).on('scroll',function (){
   //表示させる要素の位置を取得
    var elemPos = $('.grid').offset().top;
  //スクロール量を取得
    var scroll = $(window).scrollTop();
  //画面サイズを取得
    var windowHeight = $(window).height();

    if( scroll > elemPos - windowHeight + 200 ){
    
    //時間差でフェイドインするクラスを追加する
      $('.img-fade-up').each(function(i){

        var $this = $(this);

        $this.delay( i * 400 ).queue(function(next){

          $this.addClass('effect-scroll');
          next();

        });
      });
    }
});

スクロールイベントでgrid要素の位置とスクロール量、画面サイズを取得して、それらを使って常にif文で指定した範囲に入っているかを確認している状態です。

今回の設定はスクロールして行って、要素が画面に入り込んでから200pxの高さまできたら表示イベントが発火するようにしています。

そのあとの処理が表示するためのクラス(effect-scroll)を各img-fade-up要素に時間差で追加いくので、順番に画像がされるようになります。

Javascriptの動きがよくわからない人用の解説

個人的に時間差処理のところがよくわからない人がいると思います(自分だけだと思いますが最近まで意味不明でした、、、)
疑問に思ったこと2つを無理やり解釈しました。

疑問1 $this.delay( i * 400 )って何してるんや? iはなんやねん

まずは時間をずらす処理だけに注目します。

delay()のところ

      $('.img-fade-up').each(function(i){

        var $this = $(this);
         //↓ここ
        $this.delay( i * 400 ).queue(function(next){

        (中略)

        });
      });
    }

まずこの処理は6つあるimg-fade-up要素(※今回は6つhtmlに書いたので)をeachで1つずつ取り出して処理を実行しています。これを6回繰り返します。

したがって$thisは言うまでもなく、6つのうちの1つの繰り返し処理毎に取り出したimg-fade-up要素です。

それに$this.delay(遅らせる時間)で時間を遅らせてから、queueというメソッドを実行しているわけです。queueを呼び出すことでクラス追加の処理が行われるので画面上に隠れていた要素が現れます。

このことからeachの繰り返しの中でdelayの()内の遅らせる時間を少しずつ増やしていくことによって、ずらして各要素を出現させることができます。

どうやって時間を繰り返し処理毎に増やしているのかというと、eachメソッドでindex引数をうまいこと使うことによって実現させています。

jQueryオブジェクト.each(function(index) {

  index 

//1回目 index === 1
//2回目 index === 2
//3回目 index === 3
//n回目 index === n
});)

引数のindexのところは表記は自由らしい!
あーということは「i」はindexを表していたのか!

したがってdelay( i * 400 )(iはindexと同じ)と書くことでループ毎にずらす時間を400ミリ秒ずつ増やすことができているのでした。

疑問2 そもそもqueueってなんぞ?next()は何してんの?

      $('.img-fade-up').each(function(i){

        var $this = $(this);
        
        $this.delay( i * 400 ).queue(function(next){
        //↓ここ
        $this.addClass('effect-scroll');
          next();

        });
      });
    }

queueの説明をしだすとめちゃくちゃ長くなりそうなので、まtた別の記事でまとめたらリンク貼ろうと思います。

なので今回は結論だけ言っちゃうとnext()は必要ありません笑
queueメソッドは指定した要素のキューに関数を登録し、キューに老禄されている順に関数を実行される仕組みです。
その過程の中でnext()は次の登録した関数を実行させるために使われるのですが、今回の実装だと隠れた要素を出現させる以外($this.addClass('effect-scroll'))に使用する関数は登録されていないのでなくても動きます。
しかし、開発過程で同じ処理を繰り返し使いたかったり、登録する関数が増える可能性があることを考えると、一応書いておくのがベストだと思います。