2022.10 スクロール連動

完成イメージ

教材

github からダウンロードしてください。

教材ダウンロード以外は実際のサイトには飛ばなくても大丈夫です。
リンク先は共有画面で紹介しますので、一緒に見ましょう。

inview を使います

スクロールに連動して画像などに動きをつける場合によく使用されます。
inview は jQuery のプラグインとして実装されています。

inview 公式リポジトリ: https://github.com/protonet/jquery.inview

01. まずは jQuery 導入から

jQuery は古くからある JavaScript ライブラリです。
まだブラウザごとの実装の差が大きかった頃、AJAX の普及期において大流行しました。(2006年リリース)

jQuery 公式サイト: https://jquery.com/

※JavaScript 自体が高機能になり脱 jQuery の流れもあるので、それについては後述します(なので jQuery のコードはなんとなくの理解で OK です)

よく使われるライブラリは CDN で配信されています。
それぞれのサイトにアップするより、CDN を使った方がブラウザにキャッシュされるのでユーザにとっては速度面や容量面で親切です。

クライアントさんによっては外部サイト NG の場合もあるので、状況にあわせてダウンロードして使用してください(最近は少ないけど大企業ではよくありました)

jQuery 公式の CDN または、よく使われている Google の CDN を使用します。

今回は Google の CDN を例に進めます。
jQuery 3 を HTML (index.html) の <head> タグ内に追記します。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

正しく読み込まれているか確認するために、JavaScript (js/scroll.js) に下記を記述して動作確認します。

$('body').css('background-color', '#EFE');

背景色が変わることを確認できたらこのコードは消してください

これは jQuery の記法で、CSS のプロパティを jQuery から変更する方法になります。

確認用コードの補足 (あとで読んでね)

jQuery では CSS のセレクタを使用して要素を指定できます。
※ $(‘body’) は <body> タグを指します

ここから jQuery のツールを使うことができます。
今回はそのうち CSS のプロパティを変更できる css() メソッドを使用して background-color を変更しています。

css(‘background-color: #EFE’) ではなく、css(‘プロパティ名’, ‘設定値’) という形式になっている点に注意してください。

02. inview を読み込む

inview は公式の CDN などはないので、下記を利用します。

cdnjs: https://cdnjs.com/libraries/protonet-jquery.inview

jQuery に依存している(jQuery が使える状態で動作する前提になっている)ので、jQuery の読み込みよりもあとに追記します。(index.html)

<script src="https://cdnjs.cloudflare.com/ajax/libs/protonet-jquery.inview/1.1.2/jquery.inview.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

body タグ内に下記を記述しておきます。

    <div class="photo-block">
        <img src="images/photo-01.jpg">
    </div>
    <div class="photo-block">
        <img src="images/photo-02.jpg">
    </div>
    <div class="photo-block">
        <img src="images/photo-03.jpg">
    </div>
    <div class="photo-block">
        <img src="images/photo-04.jpg">
    </div>
    <div class="photo-block">
        <img src="images/photo-05.jpg">
    </div>
    <div class="photo-block">
        <img src="images/photo-06.jpg">
    </div>

画像ファイルは 00-htdocs にあるので、必要に応じてコピーしてください

CSS (css/style.css) には下記だけ記述しておきます。

body {
    margin: 0;
}

img {
    width: 100%;
    vertical-align: middle;
}

この時点で Chrome デベロッパーツールのコンソールにエラーが出ていなければ OK とします。

03. イベントに応じてクラスを追加する

jquery.inview.js を読み込むことで、inview というイベントが使用できるようになります。
これは画面をスクロールして、その要素が画面内に表示された時に発生するイベントとなります。

jQuery と組み合わせることで、inview イベント発生のタイミングでその要素にクラスを追加してみましょう。

JavaScript (js/scroll.js) に下記を記述します。

$('.photo-block').on('inview', function () {
    $(this).addClass('on-screen');
});

いったんこの状態で Chrome Developer Tool を起動して、HTML を確認しながらスクロールしてみてください。

コードの補足 (あとで読んでね)

jQuery では on() メソッドを使うことでイベント(ユーザの操作など)を受信します。
※要素をクリックしたときは on(‘click’, function() {…}) と記述

今回はクラスに photo-block をもつ要素が画面に表示されたタイミングで発生するイベント (inview) を受信したいので $(‘photo-block’).on(‘inview’, function{…}) のように記述できます。

関数の中にはイベント受信した際に実行する処理を記述します。
今回は on-screen クラスを追加したいので jQuery の addClass() を使って、$(this).addClass(‘on-screen’) としています。

このとき this はイベントを受け取った自分自身を指す JavaScript のオブジェクトです。
addClass メソッドを使いたいので jQuery のオブジェクトに変換して $(this) と書きます。
(定型の書き方と覚えてしまって良いです)

次に CSS でアニメーションを指定します。
まずは簡単にフェードインさせます。

CSS (css/style.css) に下記を追記します。

.photo-block {
    opacity: 0;
    transition: opacity 1s ease-in;
}

.photo-block.on-screen {
    opacity: 1;
}

最初は非表示 (opacity: 0)、画面に表示されたタイミングでフェードインさせます。

04. アニメーションのバリエーション

全部の画像に違う動きをつけてみます。

HTML (index.html) の画像部分を下記に置き換えます。
※別々のクラスを追加しています

    <div class="photo-block fadein">
        <img src="images/photo-01.jpg">
    </div>
    <div class="photo-block slidein-left">
        <img src="images/photo-02.jpg">
    </div>
    <div class="photo-block slidein-right">
        <img src="images/photo-03.jpg">
    </div>
    <div class="photo-block slideup">
        <img src="images/photo-04.jpg">
    </div>
    <div class="photo-block zoomin">
        <img src="images/photo-05.jpg">
    </div>
    <div class="photo-block zoomout">
        <img src="images/photo-06.jpg">
    </div>

CSS (css/style.css) に下記を追加します。
※transition や animation で動きをつけています

.slidein-left.on-screen {
    animation: slidein-left 1s ease-out;
}

@keyframes slidein-left {
    from {
        transform: translateX(-30%);
    }

    to {
        transform: translateX(0%);
    }
}
.slidein-right.on-screen {
    animation: slidein-right 1s ease-out;
}

@keyframes slidein-right {
    from {
        transform: translateX(50%);
    }

    to {
        transform: translateX(0%);
    }
}
.slideup {
    overflow: hidden;
}

.slideup.on-screen img {
    animation: slideup 1s ease-out;
}

@keyframes slideup {
    from {
        transform: translateY(50%);
    }

    to {
        transform: translateY(0%);
    }
}
.zoomin {
    overflow: hidden;
}

.zoomin img {
    transition: transform 1s ease-out;
}

.zoomin.on-screen img {
    transform: scale(1.2);
}
.zoomout {
    overflow: hidden;
}

.zoomout img {
    transition: transform 1s ease-out;
    transform: scale(1.2)
}

.zoomout.on-screen img {
    transform: scale(1.0);
}

Vanilla JS

JavaScript 自体の機能が良くなり、ブラウザごとの互換性も目立った問題が少なくなってきたことで、jQuery を使わなくてもいろんなことができるようになってきました。

同じ内容を JavaScript のみで実装しているので参考にしてみてください。
jQuery などのライブラリを使うのに対して、プレーンな状態というニュアンスでバニラと呼ぶことがあります。

window.addEventListener('DOMContentLoaded', function (e) {
    const target = document.querySelectorAll('.photo-block');

    const options = {
        root: null,
        rootMargin: '0px 0px',
        threshold: 0.25,
    };

    let observer = new IntersectionObserver(callback, options);

    target.forEach(t => {
        observer.observe(t);
    });

    function callback(entries) {
        entries.forEach((entry) => {
            if (entry.isIntersecting) {
                entry.target.classList.add('on-screen');
            } else if (entry.target.classList.contains('on-screen')) {
                entry.target.classList.remove('on-screen');
            }
        });
    };
});

用語集

CDNとは

CDNはContent Delivery Network(コンテンツ デリバリー ネットワーク)を省略した言葉。
JavaScript ライブラリや CSS など共通して使用するファイルを配信することで、余分なダウンロードを回避するための仕組み。同じデータを各サイトでそれぞれ配信すると重複してダウンロードされるが、CDN を使えばそのファイルは一度読み込まれることで、以降はキャッシュされるのでその分時間短縮してコンテンツを表示できるようになります。
https://www.stream.co.jp/blog/blogpost-41362/

Ajax(エイジャックス)

Ajaxとは、Asynchronous JavaScript and XML の略語で、非同期通信を「JavaScriptの技術で実行すること」を指します。
健在は XML よりも JSON との通信が主流です。
非同期とはそれ以前の HTML 全体を読み込んでブラウザに表示するのに対して、コンテンツの一部を並列に通信を行うこと(HTML 本体と同期しない)。
これにより、ページ読み込みの体感速度が上がり、ユーザの操作にあわせて後からデータを取得することが可能になった。
https://wa3.i-3-i.info/word12672.html
https://hnavi.co.jp/knowledge/blog/ajax/

CSS

vertical-align

https://webukatu.com/wordpress/blog/19247/

transform

要素を回転、拡大縮小、傾斜、移動することできる
https://developer.mozilla.org/ja/docs/Web/CSS/transform
http://www.htmq.com/css3/transform.shtml

transition

下記をまとめて指定する

・transition-property

transition効果を適用するCSSプロパティ名を指定する
https://developer.mozilla.org/ja/docs/Web/CSS/transition-property

・transition-duration

変化に掛かる時間を指定する(単位 s,ms)
https://developer.mozilla.org/ja/docs/Web/CSS/transition-duration

・transition-timing-function

変化のタイミング・進行割合を指定する
http://www.htmq.com/css3/transition-timing-function.shtml
https://developer.mozilla.org/ja/docs/Web/CSS/transition-timing-function

・transition-delay

変化がいつ始まるかを指定する(単位 s,ms)
http://www.htmq.com/css3/transition-delay.shtml
https://developer.mozilla.org/ja/docs/Web/CSS/transition

animation

https://developer.mozilla.org/ja/docs/Web/CSS/animation

transition と animation の違い

https://www.asobou.co.jp/blog/web/css-animation3

単位 s, ms

s(秒)
ms(ミリ秒) 1秒の1000分の1(0.001秒)

easing

linear (リニア、直線的、線形)な変化だとアニメーションがしっくりこない場合はイージングを利用します。今回のフェードインの場合、半透明な時間が長い方が見やすいため ease-in を使い最初の変化がゆっくりになるように調整しました。
https://ics.media/entry/18730/