JavaScriptのIntersection Observer APIと、Web Animations APIを組み合わせて、スクロールによって反応するアニメーション効果を加えます。
キーワード:Intersection Observer API、Web Animations API、配列、繰り返し(forEach)
作成例(完成イメージ)
- 作成例:https://ngsm-syr.github.io/javascript_scroll/
- コード:https://github.com/ngsm-syr/javascript_scroll/
【準備】フォルダ:javascript_scroll
①JavaScriptを書くための準備で作成したフォルダ(空のHTML、CSS、JavaScriptが入っている)を準備します。GitHubからもダウンロードできます。
②フォルダの名前を「javascript_scroll」に変更します
③画像を3枚程度用意します。作例と同じ画像を使う方は、Githubからダウンロードしてください。
画像は images フォルダに入れます。
HTMLとCSSファイルの準備
まず、コンテンツ部分を用意します。
▼index.html
<header>
<h1>SCROLL</h1>
</header>
<main>
<img src="images/img01.png" alt="img01" id="img01">
</main>
▼style.css
body {
text-align: center;
}
h1 {
margin: 50vh 0;
}
img {
max-width: 100%;
}
Intersection Observer APIとは
ターゲットとなる要素が、指定領域(ビューポート)に入ったかどうかを検知する方法です。これによって、スクロールして、ターゲット要素が範囲に入ったときに、動作を呼び出すことができます。要素が範囲に入ることを「交差」と表現します。
Intersection→交差
Observer→監視者
【補足】従来、スクロールによって反応する仕組みをつくるには、scrollイベントを使う必要がありました。イベントが起こるタイミングを割り出すのに、画面サイズが変わるたびに再計算が必要なため、負荷のかかる方法でした。
Intersection Observer API の使い方
①監視対象が現れたときに実行したい内容を定義する
▼script.js
//実行する機能
const show = () => {
console.log('ログを表示');
}
【補足】アロー関数
上記のような関数の定義方法をアロー関数といいます。=>の部分が矢(arrow)のように見えることが名前の由来です。
const 関数名 = () => {
//実行内容
}
functionを使った書き方をすると以下のようになります。
function show() {
console.log('表示します');
}
functionを使った書き方の方が歴史が古く、アロー関数の方が新しい書き方になります。解説書等では両方見かけることがありますので、どちらの形式も確認しておいてください。
②監視機能の設定
▼script.js
//実行する機能
const show = () => {
console.log('ログを表示');
}
//監視機能の設置
const observer = new IntersectionObserver();
③動作内容を指示
▼script.js
//実行する機能
const show = () => {
console.log('ログを表示');
}
//監視機能の設置
const observer = new IntersectionObserver(show);
④監視対象を指示
▼script.js
const show = () => {
console.log('ログを表示');
}
//監視機能の設置
const observer = new IntersectionObserver(show);
//監視対象の指示
observer.observe();
⑤何を監視するのかを指定
▼script.js
const show = () => {
console.log('ログを表示');
}
//監視機能の設置
const observer = new IntersectionObserver(show);
//監視対象の指示
observer.observe(document.querySelector('#img01'));
ログが表示されるタイミングから、Intersection Observerの機能は、ページが読まれた瞬間、要素が範囲に入った瞬間、範囲から外れた瞬間に呼び出されることがわかります。
- 途中経過:https://ngsm-syr.github.io/javascript_scroll_a/
- コード:https://github.com/ngsm-syr/javascript_scroll_a/
⑥監視対象の情報取得
Intersection Observer APIでは、対象要素のサイズ、名前などの情報が「配列」で渡されます。次のように書くと、配列に渡される情報が確認できます。
▼script.js
const show = (entries) => {
console.log(entries);
}
0番目の配列のみ取得
(画像が1つのため、先頭の配列のみを取得)
▼script.js
const show = (entries) => {
console.log(entries[0]);
}
要素を取得
▼script.js
const show = (entries) => {
console.log(entries[0].target);
}
⑦アニメーションを加える
▼script.js
const show = (entries) => {
const keyframes = {
opacity: [0, 1],
translate: ['200px 0',0]
}
entries[0].target.animate(keyframes,600);
}
【応用】複数の要素に別々の動きを設定する
3枚の画像に、それぞれ別の動きを設定した例です。
- 途中経過:https://ngsm-syr.github.io/javascript_scroll_b/
- コード:https://github.com/ngsm-syr/javascript_scroll_b/
【応用】複数の要素に同じ要素を設定する
同じクラス名をつけた要素に、同じ動きができるように、繰り返し処理を使って設定します。
▼index.html
<img src="images/img01.png" alt="img01" class="img">
<img src="images/img02.png" alt="img02" class="img">
<img src="images/img03.png" alt="img03" class="img">
すべての画像に同じクラス名を追加します。
▼style.css
img {
max-width: 100%;
margin: 20vh 0;
}
画像同士がくっつかないように上下にマージンを設定します。
▼script.js
const show = (entries) => {
entries.forEach((entry) => {
const keyframes = {
opacity: [0, 1],
translate: ['200px 0',0]
}
entry.target.animate(keyframes,600);
});
}
const observer = new IntersectionObserver(show);
//監視対象
const images = document.querySelectorAll('.img');
images.forEach(img =>{
observer.observe(img);
});
複数の要素に同じ動作をさせるため、forEachを使って、繰り返しの処理をします。
交差しているときだけ動作するようにします。
▼script.js
//交差しているときだけ
const show = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting){
const keyframes = {
opacity: [0, 1],
translate: ['200px 0',0]
}
entry.target.animate(keyframes,600);
}
});
}
スクロールのたびに動作すると、煩わしいときもありますので、一度表示したあとは、動作しないようにします。監視対象から外すことで実現します。
▼script.js
//一度表示したら動作を止める
const show = (entries, obs) => {
entries.forEach((entry) => {
if (entry.isIntersecting){
const keyframes = {
opacity: [0, 1],
translate: ['200px 0',0]
}
entry.target.animate(keyframes,600);
//一度表示されたら止める
obs.unobserve(entry.target);
}
});
}
- 途中経過:https://ngsm-syr.github.io/javascript_scroll_c/
- コード:https://github.com/ngsm-syr/javascript_scroll_c/
参考書籍・リンク
- 「すらすらわかるJavaScript 新版」桜庭洋之,望月幸太郎, 翔泳社,2022
- 「1冊ですべて身につくJavaScript入門講座」Mana, SBクリエイティブ, 2023
- 「独習JavaScript」CodeMafia 外村将大, 翔泳社, 2021
- https://developer.mozilla.org/ja/docs/Web/API/IntersectionObserver
- https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API