jQuery / JavaScriptで、ページスクロール時にアクションを起こしたい


ページをスクロールした時に、スクロールした距離に応じて、オブジェクトの移動や透過をさせたい。パララックス効果についても簡潔な例を知りたい。




パララックス効果と一言に言ってもいろいろな表現があるとは思いますが、  
スクロール量に応じてスライドしてきたり文字がフェードしてきたりするようなもののサンプルを書いてみました。

細かいところは気にしていませんので、何かのヒントになればという程度のものです。  
Chromeでしか確認していません。  
（一応 safariでも見てみましたがバウンスのせいか見づらいです）

[code]

    $(window).load(function() {
      var height = $(window).height();
      $(".scr").each(function(i, ele) {
        // ページの高さを確定する。
        var $ele = $(ele);
        var page = $ele.attr("data-page-slidein");
        $ele.css("top", height * page);
        $ele.height(height);
      });
    
      $(window).scroll(function() {
        var scrTop = $(this).scrollTop();
        $(window).scrollLeft(0);
    
        $(".scr").each(function(i, ele) {
          var $ele = $(ele);
    
          var opaPage = $ele.attr("data-page-appear");
          var page = $ele.attr("data-page-slidein");
    
          if (page * height < scrTop) {
            // 画面内にとどまる処理
            $ele.css("top", scrTop);
          }
    
          if (opaPage != "") {
            // 透明度の処理。自分の出現ページが画面に
            // どの程度表示されているかの割合から求めている。
            var value = (opaPage * height - scrTop) / height;
            $ele.css("opacity", 1 - value);
          }
        });
      });
    });
[/code]

[code]

    body {
      margin: 0;
      padding: 0;
    }
    
    .scr {
      height: 100%;
      position: absolute;
      width: 100%;
      top: 100%;
    }
    
    .page1 {
      background-color: #00b3ee;
    }
    
    .page2 {
      background-color: #d58512;
    }
    
    .first-page,
    .last-page {
      background-color: white;
    }
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <!-- data-page-slidein  何ページ分スクロールすると そのdivがスライドしてくるか -->
    <!-- data-page-appear   divのFadeInが完了するタイミング ： 何ページ分スクロールしたとき不透明になる。ブランクならフェードしない -->
    <div class="scr first-page" data-page-slidein="0" data-page-appear="">
      Index Page
    </div>
    
    <div class="scr page1" data-page-slidein="1" data-page-appear="">
      ページ１
    </div>
    
    <div class="scr" data-page-slidein="1" data-page-appear="2">
      <div style="position:relative; left:100px; top:40px; color:white; font-size:16pt;">遅れて表示</div>
    </div>
    
    <div class="scr page2" data-page-slidein="3" data-page-appear="">
      ページ２
    </div>
    
    <div class="scr" data-page-slidein="3" data-page-appear="4">
      <div style="position:relative; left:190px; top:140px; color:blueviolet; font-size:16pt;">現れる</div>
    </div>
    
    <div class="scr" data-page-slidein="3" data-page-appear="5">
      <div style="position:relative; left:300px; top:40px; color:indianred; font-size:16pt;">テキスト</div>
    </div>
    
    <div class="scr last-page" data-page-slidein="7" data-page-appear="7">
      Last Page
    </div>
[/code]

[このページ](http://www.akita.co.uk/computing-history/)のような動きをまねしてみたものです。

* * *

以下ソースです。

`HEAD`でjQueryと後で記載するcssとjsをロードします。

[code]

        <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script src="js/sample.js"></script>
        <link rel="stylesheet" href="css/style.css"/>
    
[/code]

本体となるHTMLは以下です。  
対象とするには `scr` css-classを指定します。  
コメントにも書きましたが `data-page-slidein`でスライドしてくるタイミング、`data-page-
appear`で画面にフェードインするタイミングを、「何ページ分スクロールしたときか」で指定します。

[code]

    <body>
        <!-- data-page-slidein  何ページ分スクロールすると そのdivがスライドしてくるか -->
        <!-- data-page-appear   divのFadeInが完了するタイミング ： 何ページ分スクロールしたとき不透明になる。ブランクならフェードしない -->
        <div class="scr first-page" data-page-slidein="0" data-page-appear="">
            Index Page
        </div>
    
        <div class="scr page1" data-page-slidein="1" data-page-appear="">
            ページ１
        </div>
    
        <div class="scr" data-page-slidein="1" data-page-appear="2">
            <div style="position:relative; left:100px; top:40px; color:white; font-size:16pt;">遅れて表示</div>
        </div>
    
        <div class="scr page2" data-page-slidein="3" data-page-appear="">
            ページ２
        </div>
    
        <div class="scr" data-page-slidein="3" data-page-appear="4">
            <div style="position:relative; left:190px; top:140px; color:blueviolet; font-size:16pt;">現れる</div>
        </div>
    
        <div class="scr" data-page-slidein="3" data-page-appear="5">
            <div style="position:relative; left:300px; top:40px; color:indianred; font-size:16pt;">テキスト</div>
        </div>
    
        <div class="scr last-page" data-page-slidein="7" data-page-appear="7">
            Last Page
        </div>
    </body>
    
[/code]

cssファイルです。scrクラスの指定が主です。スライドしてくるdivに関しては背景色を指定した方がいいでしょう。

[code]

    body{
        margin:0;
        padding: 0;
    }
    .scr{
        height:100%;
        position:absolute;
        width:100%;
        top:100%;
    }
    
    .page1{
        background-color: #00b3ee;
    }
    
    .page2{
        background-color: #d58512;
    }
    
    .first-page, .last-page{
        background-color: white;
    }
    
[/code]

メインとなるjavascriptです。

スライド表示に関しては ページの高さ×ページ数 を
topとして設定して普通にスクロールされて登場するだけですが、divが画面の一番上まで来たらそれより下にスクロールしてもその位置をキープするようにしています。

`data-page-
appear`に数字を設定しておくと、その数字のページの１ページ前からフェードインしはじめ、スクロールがそのページに達すると完全に不透明になるような処理を入れてあります。つまりフェードする区間は１ページ分です。

[code]

    $(window).load(function(){    
        var height = $(window).height();
        $(".scr").each(function(i,ele) {
            // ページの高さを確定する。
            var $ele=$(ele);
            var page = $ele.attr("data-page-slidein");
            $ele.css("top", height * page);
            $ele.height(height);
        });
    
        $(window).scroll( function(){
            var scrTop = $(this).scrollTop();
            $(window).scrollLeft(0);
    
            $(".scr").each(function(i,ele){
                var $ele = $(ele);
    
                var opaPage= $ele.attr("data-page-appear");
                var page = $ele.attr("data-page-slidein");
    
                if(page * height  < scrTop ) {
                    // 画面内にとどまる処理
                    $ele.css("top", scrTop);
                }
    
                if(opaPage != ""){
                    // 透明度の処理。自分の出現ページが画面に
                    // どの程度表示されているかの割合から求めている。
                    var value = (opaPage*height - scrTop)/height;
                    $ele.css("opacity", 1-value);
                }
            });
        });
    });
    
[/code]

