今回は新しいデザインで簡単なスクロールアニメーションを実装します。
Webサイトで頻繁に目にするスクロールアニメーションが、
一体どういった仕組みで動いているかを学んでいこうと思います。
今回も講義終了までに完成を目指しますが、
jQueryプラグインは使わず簡単なJavaScriptのコードを書いて、
簡単なスクロールアニメーションを実装してみましょう。
https://webcre8tor.com/data/lesson/anime/
※ID・PASSは講義にて
構成ファイルのダウンロード・解凍・確認
構成ファイルのダウンロード・解凍
今回は時短のためHTMLファイルやCSSファイルなどの構成ファイルはすでに準備しています。
ひとまず構成ファイル「WebDesignExercise02.zip(zip圧縮データ)」をダウンロードしておきましょう。
※IDとPASSは講義で伝えます。
ダウンロードが終わったら構成ファイルを解凍しましょう。
構成ファイルの確認
ダウンロードした圧縮ファイル「WebDesignExercise02.zip」を解凍すると「html_anime」というフォルダがあり、そのファイル・フォルダ構成は以下の画像のようになっているはずです。
なお画像内に入りきらないので「img」フォルダの中身を別途以下の画像に明記しておきます。
画像ファイルは問題なく存在していますか??
フォルダ・ファイルが準備できたらテキストエディタを起動してVisual Studio Codeの左のエクスプローラーメニューの「html_anime」フォルダから「index.html」「main.css」「anime.js」を開いて早速始めていきましょう。
なお今回の講義内容も提出課題です。管理しやすくデータが消えないような場所に移動してください。
テンプレート部分のHTML・CSSコーディング
今回も基本は終わっているものとしてテンプレート部分はサクサク進めてしまいます。
テンプレート部分のHTMLコーディング
まずはテンプレート部分のHTMLを記述します。下記コードの全てをindex.htmlに記述しましょう。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/main.css">
<title>スクロールアニメーション</title>
</head>
<body>
</body>
</html>
以上です。
テンプレート部分のCSSコーディング
HTMLの記述が終われば今度はmain.cssの記述を追加します。下記コードの全てをmain.cssに記述しましょう。
css/main.css
@charset "utf-8";
* {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
box-sizing: border-box;
}
html , body {
height: 100%;
}
以上です。
<div id=”container”></div>のHTMLコーディング
再びindex.htmlの編集に切り替えます。
まずは今回のページで一番大きな枠、<div id=”container”></div>のHTMLコーディングです。<body></body>タグの開始タグと終了タグの間を改行し、ハイライトされている4行目・5行目のコードを記述しましょう。
index.html
<!-- 〜上部省略〜 -->
<body>
<div id="container">
<!-- /#container --></div>
</body>
</html>
以上です。
<div id=”container”></div>のCSSコーディング
再び「main.css」の編集に切り替えましょう。<div id=”container”></div>のCSSコーディングを行います。「html , body {〜}」のセレクタの下を改行し、ハイライトされている7〜18行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
html , body {
height: 100%;
}
#container {
width: 100%;
position: relative;
overflow: hidden;
/* -- ↓↓ backgroundプロパティを使って背景画像のグラデーションを設定 ↓↓ -- */
background: rgb(52,152,219);
background: -moz-linear-gradient(top, rgb(52,152,219) 0%, rgb(255,255,255) 100%);
background: -webkit-linear-gradient(top, rgb(52,152,219) 0%,rgb(255,255,255) 100%);
background: linear-gradient(to bottom, rgb(52,152,219) 0%,rgb(255,255,255) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3498db', endColorstr='#ffffff',GradientType=0 );
/* -- ↑↑ backgroundプロパティを使って背景画像のグラデーションを設定 ↑↑ -- */
}
background: linear-gradient(◯◯);
これは初めて出てきますね。今回のデザインを見ると、背景が上から下へ、青から白にグラデーションがかかっているのがわかります。
このグラデーションの指定を行っているのが、background: linear-gradient(◯◯);などの5行のコードです。やり方によってはもっと複雑なグラデーションを実装することも可能です。
以下のような便利なツールもあります。
グラデーションを直感的に調整するだけで右側のウィンドウ内にコードを生成してくれます。
<div id=”cloud”></div>のHTMLコーディング
次に雲のアニメーションのためのブロック、<div id=”cloud”></div>のコーディングを行います。
<div id=”container”></div>セクションの開始タグと終了タグの間を改行し、ハイライトされている5〜12行目のコードを記述しましょう。
index.html
<!-- 〜上部省略〜 -->
<div id="container">
<div id="cloud">
<div class="cloud01"><img class="anime" src="./img/cloud01.png" /></div>
<div class="cloud02"><img class="anime" src="./img/cloud02.png" /></div>
<div class="cloud03"><img class="anime" src="./img/cloud03.png" /></div>
<div class="cloud04"><img class="anime" src="./img/cloud04.png" /></div>
<div class="cloud05"><img class="anime" src="./img/cloud05.png" /></div>
<div class="cloud06"><img class="anime" src="./img/cloud06.png" /></div>
<!-- /#cloud --></div>
<!-- /#container --></div>
<div id=”cloud”></div>の子要素の<div></div>のclassにそれぞれ「cloud◯◯」とつけています。これはそれぞれの要素の座標(縦横の位置)が違うためで、CSSでそれぞれに指定を行うことで別々の場所で動作させるようにするためです。
また、さらにその子要素の<img />タグにはすべて「anime」というclassをつけています。今回記述するJavaScriptでは、この「anime」というclassを持つものを探し出し、条件に合ったものをアニメーションさせています。
<div id=”cloud”></div>のCSSコーディング
再びmain.cssの編集に切り替えて<div id=”cloud”></div>のCSSコーディングを行いましょう。
<div id=”cloud”></div>の記述
次は雲にアニメーションさせるキャンバスを生成しましょう。
先ほど記述した「#container {〜}」のセレクタの下を改行し、ハイライトされている14〜18行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#container {
width: 100%;
position: relative;
overflow: hidden;
background: rgb(52,152,219);
background: -moz-linear-gradient(top, rgb(52,152,219) 0%, rgb(255,255,255) 100%);
background: -webkit-linear-gradient(top, rgb(52,152,219) 0%,rgb(255,255,255) 100%);
background: linear-gradient(to bottom, rgb(52,152,219) 0%,rgb(255,255,255) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3498db', endColorstr='#ffffff',GradientType=0 );
}
#cloud {
width: 100%;
height: 2640px; /* -- アニメーションのためにコンテンツの高さを確保 -- */
position: relative; /* -- 子要素が左上の基準点を設定できるように指定 -- */
}
ここでは「height: 2640px;」として<div id=”cloud”></div>セクションの高さを指定しています。
これは雲の要素をアニメーションさせるためには絶対配置の指定を行う必要があり、子要素を絶対配置をしているために<div id=”cloud”></div>セクションの高さを保持できないからです。
<div id=”cloud”></div>セクションの高さをあらかじめ指定することで、
アニメーションさせることができる大きさの範囲のキャンバスを作り出しています。
<div id=”cloud”></div>の子要素の<div></div>(それぞれの雲の座標)、<img />のアニメーションの指定
次は6つそれぞれの雲への絶対配置指定を一括で行って、子要素に読み込んだ雲の画像へアニメーションの指定を行います。
先ほど記述した「#cloud {〜}」のセレクタの下を改行し、ハイライトされている9〜11行目・13〜20行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#cloud {
width: 100%;
height: 2640px; /* -- アニメーションのためにコンテンツの高さを確保 -- */
position: relative; /* -- 子要素が左上の基準点を設定できるように指定 -- */
}
#cloud div {
position: absolute; /* -- アニメーションさせる雲の要素をまとめて絶対配置に指定 -- */
}
#cloud div img.anime {
/* -- ↓↓ transitionプロパティでアニメーションの時間をまとめて指定 ↓↓ -- */
-webkit-transition: 1s;
-moz-transition: 1s;
-o-transition: 1s;
transition: 1s;
/* -- ↑↑ transitionプロパティでアニメーションの時間をまとめて指定 ↑↑ -- */
}
<div id=”cloud”></div>の直下の子要素に<div></div>が絶対配置されていますが、
前提としてこの<div></div>の役割はキャンバス上で座標を決めるためのもの、
対して「anime」というclassがついた<img />の役割はアニメーションさせるためのものです。
「#cloud div img.anime {〜}」に新しいプロパティ「transition」がありますが、要素に「時間的変化」をもたらすプロパティで、「要素に簡単な動きを持たせる」ことができます。
ちなみに「-webkit-」「-moz-」「-o-」などは、第05回の講義で解説した「ベンダープレフィックス」と言うものですね。
<div class=”cloud01″></div>〜<div class=”cloud06″></div>に、大まかな座標を一括で指定
一括で絶対配置指定をしましたが、完成イメージのページは画面の中央から見て左に3つ右に3つの雲がありますよね。アニメーションする要素が右側にあるか左側にあるかでプロパティが変わりますのでその指定を行いましょう。
先ほど記述した「#cloud div img.anime {〜}」のセレクタの下を改行し、ハイライトされている10〜12行目・14〜16行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#cloud div img.anime {
-webkit-transition: 1s;
-moz-transition: 1s;
-o-transition: 1s;
transition: 1s;
}
#cloud .cloud01,
#cloud .cloud03,
#cloud .cloud05 {right: 50%;} /* -- 画面右端から画面半分の位置 -- */
#cloud .cloud02,
#cloud .cloud04,
#cloud .cloud06 {left: 50%;} /* -- 画面左端から画面半分の位置 -- */
まず、上の記述の「#cloud .cloud01,#cloud .cloud03,#cloud .cloud05 {〜}」は、画面中央から見て左側にある3つの雲の指定になります。この時指定するプロパティは「right」です。
次に下の記述の「#cloud .cloud02,#cloud .cloud04,#cloud .cloud06 {〜}」は、画面中央から見て右側にある3つの雲の指定になります。この時指定するプロパティは「left」です。
左側にあるのになぜ「right」?右側なのになぜ「left」と思うかもしれませんね。
下の画像を見てみましょう。
要素を画面の左側に置くためには、画面右端から画面半分の距離をとってそこから個別に距離をとる必要があり、逆に画面の右側に置くためには、画面左端から画面半分の距離をとってそこから個別に距離をとる必要があります。
大まかに画面の左か右かを指定できたら次に6つの要素それぞれ個別に距離をとるために「margin」プロパティを使ってアニメーションの準備をします。早速次の項の解説に移りましょう。
<div class=”cloud01″></div>に、アニメーションする前、後の位置を個別に指定
さていよいよアニメーションの準備を行います。
先ほど記述した「#cloud .cloud02,#cloud .cloud04,#cloud .cloud06 {〜}」のセレクタの下を改行し、ハイライトされている7〜13行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#cloud .cloud02,
#cloud .cloud04,
#cloud .cloud06 {left: 50%;}
#cloud .cloud01 {
width: 200px;
height: 100px;
top: 500px; /* -- 画面上端から500pxの位置に指定 -- */
}
#cloud .cloud01 .anime {margin-left: -270px;} /* -- アニメーション前(この場所から) -- */
#cloud .cloud01 .stop {margin-left: -70px;} /* -- アニメーション後(この場所に移動) -- */
まず「#cloud .cloud01 {〜}」は要素の横幅と高さの指定、そして「top: 500px;」として、画面上端からの距離を指定しています。
問題は次の2つの指定です。
「#cloud .cloud01 .anime」はアニメーションする前の段階、つまり、Webページを開いた時の初期状態を指定しています。<img />タグに「anime」というclassをつけましたよね?あの時の指定はここで判別され、animeというclassを持つ<img />タグのみに適用されるわけです。
最後に「#cloud .cloud01 .stop {〜}」はアニメーションが終わった後の状態、つまり、スクロールして雲が動いて止まった位置の指定です。
ここでアニメーション前(class名 = anime)とアニメーション後(class名 = stop)の位置を指定し、特定の位置までスクロールしたら、class名を「anime」から「stop」に書き換えて「margin-left」の値を増減させることでアニメーションさせるわけです。
<div class=”cloud02″></div>〜<div class=”cloud06″></div>に同様の指定をする
<div class=”cloud01″></div>以外の雲にもアニメーションの指定をしましょう。
先ほど記述した「#cloud .cloud01 .stop {〜}」の下を改行し、ハイライトされている5〜11行目・13〜19行目・21〜27行目・29〜35行目・37〜43行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#cloud .cloud01 .stop {margin-left: -70px;}
#cloud .cloud02 {
width: 200px;
height: 100px;
top: 1000px;
}
#cloud .cloud02 .anime {margin-left: 200px;}
#cloud .cloud02 .stop {margin-left: 0px;}
#cloud .cloud03 {
width: 200px;
height: 100px;
top: 1400px;
}
#cloud .cloud03 .anime {margin-left: -380px;}
#cloud .cloud03 .stop {margin-left: -180px;}
#cloud .cloud04 {
width: 200px;
height: 100px;
top: 1700px;
}
#cloud .cloud04 .anime {margin-left: 330px;}
#cloud .cloud04 .stop {margin-left: 130px;}
#cloud .cloud05 {
width: 200px;
height: 100px;
top: 1900px;
}
#cloud .cloud05 .anime {margin-left: -360px;}
#cloud .cloud05 .stop {margin-left: -160px;}
#cloud .cloud06 {
width: 200px;
height: 100px;
top: 2050px;
}
#cloud .cloud06 .anime {margin-left: 360px;}
#cloud .cloud06 .stop {margin-left: 160px;}
これで雲のアニメーション基本設定は完了しました。
<div id=”ground”></div>のHTMLコーディング
<div id=”ground”></div>の記述
次にページの一番下に表示している芝生のようなブロック、<div id=”ground”></div>のコーディングを行います。<div id=”cloud”></div>セクションの終了タグの下を改行し、ハイライトされている4・5行目のコードを記述しましょう。
index.html
<!-- 〜上部省略〜 -->
<!-- /#cloud --></div>
<div id="ground">
<!-- /#ground --></div>
<!-- /#container --></div>
<!-- 〜下部省略〜 -->
この<div id=”ground”></div>をページの一番下に配置させるため、親要素である<div id=”container”></div>にはあらかじめ「position: relative;」を指定していますが、次項のCSSコーディングで<div id=”ground”></div>に「position: absolute;」を指定します。
<div id=”ufo”></div>の記述
最後に、人をさらおうとしたけど人違いだったことに気がついたプププうっかりUFOさんのHTMLコーディングを行いましょう。<div id=”ground”></div>セクションの開始タグと終了タグの間を改行し、ハイライトされている5行目のコードを記述しましょう。
index.html
<!-- 〜上部省略〜 -->
<!-- /#cloud --></div>
<div id="ground">
<div id="ufo"></div>
<!-- /#ground --></div>
<!-- /#container --></div>
<!-- 〜下部省略〜 -->
これでUFOの準備は完了です。
<div id=”ground”></div>のCSSコーディング
再びmain.cssの編集に切り替えてください。
<div id=”ground”></div>のCSSコーディングを行いましょう。
<div id=”ground”></div>の記述
では<div id=”ground”></div>をページの一番下に絶対配置する設定と、背景画像に芝生をタイリング(敷き詰める)する設定を行いましょう。先ほど記述した「#cloud .cloud06 .stop {〜}」の下を改行し、ハイライトされている5〜12行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#cloud .cloud06 .stop {margin-left: 160px;}
#ground {
width: 100%;
height: 60px;
position: absolute; /* -- 大地を絶対配置に指定 -- */
left: 0; /* -- 画面左端に配置 -- */
bottom: 0; /* -- 画面下端に配置 -- */
background: url(../img/ground.png) repeat-x left bottom; /* -- 背景画像の指定 描画をX方向(横方向)に繰り返す 左下から描画 -- */
}
今回は「background-image」や「background-position」を使わず「background」というプロパティで背景画像に関する指定を一括で行いました。
CSS
セレクタ {
background: 画像URL 繰り返し指定 左右の描画開始位置 上下の描画開始位置;
}
以上のように一括で指定を行うことができます。
<div id=”ufo”></div>の記述
ではUFOの指定を行いましょう。先ほど記述した「#ground {〜}」の下を改行し、ハイライトされている12〜27行目・29〜32行目のコードを記述しましょう。
css/main.css
/*-- 〜上部省略〜 --*/
#ground {
width: 100%;
height: 60px;
position: absolute; /* -- 大地を絶対配置に指定 -- */
left: 0; /* -- 画面左端に配置 -- */
bottom: 0; /* -- 画面下端に配置 -- */
background: url(../img/ground.png) repeat-x left bottom; /* -- 背景画像の指定 描画をX方向(横方向)に繰り返す 左下から描画 -- */
}
#ground #ufo {
width: 300px;
height: 340px;
position: absolute; /* -- UFOを絶対配置に指定 -- */
left: 50%; /* -- 画面左端から画面半分の位置 -- */
bottom: 230px; /* -- 画面下端から230pxの位置 -- */
/* -- ↓↓ transitionプロパティでアニメーションの時間をまとめて指定 ↓↓ -- */
-webkit-transition: 1s;
-moz-transition: 1s;
-o-transition: 1s;
transition: 1s;
/* -- ↑↑ transitionプロパティでアニメーションの時間をまとめて指定 ↑↑ -- */
transform: translateX(-50%); /* UFOの横幅の半分のサイズをマイナス方向(左)へ移動。 */
opacity: 0; /* UFOの不透明度(0:完全に透明/1:完全に不透明) */
background: url(../img/ufo.png) no-repeat center center; /* -- 背景画像の指定 描画を繰り返さない 上下左右共に中央から描画 -- */
}
#ground #ufo.stop {
bottom: 30px; /* -- 画面下端から30pxの位置 -- */
opacity: 1; /* UFOの不透明度(0:完全に透明/1:完全に不透明) */
}
「#cloud div img.anime {〜}」の指定の時にも使った「transition」プロパティを使用して「時間的変化」をもたらしています。
<div class=”cloud◯◯”></div>の時は「anime」のclassがある要素にアニメーション前の座標を指定し「stop」というclassをアニメーションが終わった際の指定にしていましたが、今回はアニメーション前の設定は<div id=”ufo”></div>自体に設定し、アニメーション後の「stop」の指定の追加のみを行います。
「stop」には「bottom」プロパティを使った縦方向の座標の増減と不透明度の指定を行える「opacity」というプロパティを使って時間的変化(アニメーション)を行わせる準備をしています。
アニメーションのためのHTML・JavaScriptコーディング
解説:jQueryの命令文「メソッド」の記述方法
jQueryについては第11回「jQueryを使ったスライドショーの設置・設定」のレクチャーの際に、本来は冗長で難解なJavaScriptの記述を簡単に扱いやすくするためのライブラリの集まりと紹介しましたね。
今回はその記述方法とCSSでの「プロパティ・値」にあたる命令文「メソッド」のレクチャーです。
非常に参考になる記事がありましたので紹介します。以下のページを開いてみてください。
jQuery本体と「anime.js」を「index.html」に読み込む
ではJavaScriptのコーディングを行ってアニメーションを実装していきましょう。
まず「anime.js」を使用するために読み込みの記述を追加しましょう。
「index.html」の<head></head>セクション内、<link rel=”stylesheet” href=”css/main.css”>の下を1行改行し、ハイライトされているjQuery本体とanime.jsを読み込む記述(6・7行目のコード)を追加してください。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/main.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="./js/anime.js"></script>
<title>スクロールアニメーション</title>
</head>
<body>
<!-- 〜下部省略〜 -->
jQuery本体と「anime.js」を読み込んだことによりアニメーションの動きを追加する準備が整いました。次に作成した「html_anime」フォルダ内の「js」フォルダ内にある「anime.js」をテキストエディタで開いてください。
今回のJavaScriptの記述は簡単にコードを書けるようにjQueryの記述方法にならって行います。
ページの読み込みが終わったら処理を開始する「$(function(){〜});」
まずはanime.jsに「$(function(){〜});」を記述します。これはjQueryのコードを記述するときのお決まりのようなものです。anime.jsの最初の行から、ハイライトされている以下のコードを記述してください。
js/anime.js
$(function(){ // DOM要素(Document Object Model)の読み込みが全て終わった時に実行する。
});
JavaScriptは基本的に、HTML内にあるタグなど(DOM要素)を全て読み込み終えた後に実行されるように記述します。
HTMLは上の行から順番に読み込まれていくので、全てを読み込んでから実行させるためには「anime.js」などを</body>の直前に読み込むように記述する必要があります。
この「$(function(){〜});」の中に、実行するコードを記述していきます。
変数を宣言する「var 変数名 = △△△」
ここではjQueryを使う上でとても便利な「変数」を使ってみましょう。
初心者の頃は「変数?なにそれ?うめぇんか?」くらいの感じでしたが使い始めると変数なしではjQueryでコードを書けなくなります。
変数は簡単に言うと「収納ボックス」です。100均とかで名前を書くことができるシールラベルがついてるものが売られてありますよね?あれを想像してください。
収納ボックスのシールラベルに名前(変数名)を書いておいて、様々な荷物を入れていきます。
早速やっていきましょう。先ほど記述した「$(function(){〜});」の間を改行し、ハイライトされている5・8・10行目のコードを記述してください。
js/anime.js
$(function(){ // DOM要素(Document Object Model)の読み込みが全て終わった時に実行する。
// 「スクロールできる上限の高さ」を求めるために、
// Webページの高さ($(document).height())から画面の高さ($(window).height())を引く。
var bottomPos = $(document).height() - $(window).height();
// UFOを変数に代入
var UFO = $('#ufo');
// UFOがアニメーションしているかどうかの判定を設定。
var UFOflag = false; // true or false
}); // 一番外のfunction()
行っていることは以下。
- 「スクロールできる上限の高さ」を計算し「bottomPos」と名前を書いたボックスに入れておく。
- <div id=”ufo”></ufo>を「UFO」と名前を書いたボックスに入れる。
- UFOがアニメーション動作を行っているかどうか(真偽)の判定を行う必要があるので「UFOflag」と名前を書いた収納ボックスに入れる。
「スクロールできる上限の高さ」を計算し「bottomPos」と名前を書いたボックスに入れておく。
スクロールアニメーションを行うにあたり、まずはどこまでスクロールが可能なのかを計算する必要があります。なぜならアニメーションはスクロールが有効な範囲内でしか動作しないためです。
つまりアニメーションが可能な範囲 = スクロールできる上限の高さということになります。
以下の画像を見てみましょう。
上の画像はページを開いた状態、すなわちスクロールする前の状態ですね。
薄く表示しているのはスクロールしないと表示されない領域で、これも含めたものがコンテンツ全体になります。この状態で求めることができるのは「$document.height() = コンテンツ全体の高さ」そして「$window.height() = ブラウザ表示領域の高さ」ですね。
次にページの一番下までスクロールした状態が下の画像です。
ページの一番下までスクロールしました。
この画像でわかるように、スクロールできる上限の高さ = コンテンツ全体の高さではありませんよね。
スクロールできる上限の高さを求めるには、ブラウザ表示領域分を差し引く必要があります。
そこで上に記述した以下のコードではスクロールできる上限の高さを計算して求め、
計算してでた結果の数値を「bottomPos」に代入していることになります。
var bottomPos = $(document).height() – $(window).height();
<div id=”ufo”></ufo>を「UFO」と名前を書いたボックスに入れる。
これはお決まりのやり方です。
例えばHTMLで「<div id=”ufo”></ufo>」という記述はJavaScriptでは「$(‘#ufo’)」と記述します。
当然jsファイル内でも「$(‘#ufo’)」と記述しますが、もし修正があった場合には記述した全ての箇所を書き換える必要性が出てきます。
そこで別の名前(UFO)を一箇所で定義して全体で記述すれば、
一箇所の変更のみで修正が完了するようにしておきます。
たとえば下の画像の記述はローディングアニメーションを実装する際によく使うものですが、
「#loading」の文字列を「#load_contents」に変更したいという依頼があった場合、効率の悪い修正方法だと「#loading」の記述箇所を全て変更する必要があります。
一方、以下の画像はまず「#loading」を変数「Loading」として定義し、該当箇所は全て「Loading」として記述しています。こうすれば定義部分の文字列を変更するだけなので、非常に効率がいい修正方法になります。
変数が便利なのは上で記述した「bottomPos」や今回の「UFO」の変数宣言のように、毎回計算を行わなくてもあらかじめ計算した結果を入れることができることや、変数宣言したものをいろいろな箇所で使いまわせることです。
UFOがアニメーション動作を行っているかどうか(真偽)の判定を行う必要があるので「UFOflag」と名前を書いた収納ボックスに入れる。
アニメーションを行う場合、「動作する前」「動作した後」の状態のフラグを立て、
不適切な状態での誤作動を防止する必要があります。
上に記述した以下のコードでは「動作したかどうか」を判断基準に、
まずは「動作していない」初期状態として「false(否)」を代入しています。
var UFOflag = false; // true or false
当然、動作すれば「true(正)」を代入し、動作が重複して起きないようにする必要があります。
アニメーション動作したタイミングで代入処理を行うわけですね。
ページがスクロールされた時の設定「$(window).on(‘scroll’, function() {〜});」
今回は「スクロールアニメーション」の実装ですので、
スクロールして特定の場所に到達したらアニメーションを実行するという設定が必要になります。
とにかく記述してみましょう。
$(window).on(‘scroll’, function() {〜});
先ほど記述した「var UFOflag = false;」の下を改行し、
ハイライトされている5行目・7・8行目・10行目のコードを記述しましょう。
js/anime.js
/*-- 〜上部省略〜 --*/
var UFOflag = false;
// ページがスクロールされた時の設定 ここから
$(window).on('scroll', function() {
var scroll = $(window).scrollTop(); // 現在のスクロール位置を計算。
var windowHeight = $(window).height(); // 画面の高さを計算。
}); // ページがスクロールされた時の設定 ここまで
}); // 一番外のfunction()
7行目はjQueryメソッド(命令文)「.scrollTop()」により現在スクロールされた高さ(スクロール量:◯◯px)が逐次計算され、変数「scroll」に代入されています。
8行目は上にも出てきたjQueryメソッド「 .height()」によりブラウザの表示領域の高さ(◯◯px)が取得され、変数「windowHeight 」に代入されています。
まとめると、5行目〜10行目の記述は、ページがスクロールされたタイミング「$(window).on(‘scroll’, function() {〜});」で、7行目でスクロール量を逐次計算し、同時に8行目でブラウザの表示領域の高さを取得するという2つの処理が実行されます。
雲に対する動きの処理
スクロールして雲が移動するアニメーションを実装する処理です。
先ほど記述した「var windowHeight = $(window).height(); 」の下を改行し、ハイライトされている9〜17行目のコードを記述しましょう。
js/anime.js
/*-- 〜上部省略〜 --*/
$(window).on('scroll', function() {
var scroll = $(window).scrollTop();
var windowHeight = $(window).height();
// #cloudの子要素のdiv(雲)に一つずつ処理を行う。
$("#cloud div").each(function(){
var imgPos = $(this).offset().top; // div(雲)の画面上端からの距離を計算。
// スクロール位置 > divの画面上端からの距離 - 画面の高さ + 200px
if (scroll > imgPos - windowHeight + 200){
$(".anime",this).addClass('stop'); // 雲画像に「anime」のclassを追加。
} else { // そうでない場合。
$(".anime",this).removeClass('stop'); // 雲画像から「anime」のclassを削除。
}
});
});
}); // 一番外のfunction()
「$(“#cloud div”).each(function(){〜});」は「<div id=”cloud”>の中にある<div></div>」に繰り返し処理を行う関数です。この記述によって6つの雲それぞれに、内側に記述している処理を行うことができます。
コメントに書いていますが、「imgPos」はコンテンツ上端から雲の画像までの高さ、「scroll」は現在スクロールされたpxです。「windowHeight 」は画面の高さで、画面の高さを求めるには「 $(window).height();」で計算するようになります。
これらの数値を使い、ページがスクロールされたら、現在どこまでスクロールされているか?を割り出し、
「if文(もし〜なら)」を使ってスクロール位置が特定の座標を超えたら「anime」というclassを追加する、という流れでアニメーションを実現しています。
UFOに対する動きの処理
ページの一番下までスクロールするとUFOが現れますね。
このアニメーションを実装する処理を記述しましょう。
先ほど記述した「 $(“#cloud div”).each(function(){〜});」の下を改行し、ハイライトされている18〜28行目のコードを記述しましょう。
js/anime.js
/*-- 〜上部省略〜 --*/
$(window).on('scroll', function() {
var scroll = $(window).scrollTop();
var windowHeight = $(window).height();
$("#cloud div").each(function(){
var imgPos = $(this).offset().top;
if (scroll > imgPos - windowHeight + 200){
$(".anime",this).addClass('stop');
} else {
$(".anime",this).removeClass('stop');
}
});
// スクロール位置がスクロールできる上限の高さから-200pxした座標に到達した場合の条件分岐。
if (scroll >= bottomPos - 200) {
if (UFOflag == false) { // UFOflagが偽(UFOは動いていない)の場合。
UFOflag = true; // UFOflagを真(UFOは動いている)に変更。
UFO.addClass('stop'); // UFOに「stop」というclassを追加する。
}
} else { // そうでない場合。
if (UFOflag) { // UFOflagが真(UFOは動いている)の場合。
UFOflag = false; // UFOflagを偽(UFOは動いていない)に変更。
UFO.removeClass('stop'); // UFOから「stop」というclassを削除する。
}
}
});
}); // 一番外のfunction()
コメントに「スクロール位置がスクロールできる上限の高さから-200pxした座標に到達した場合の条件分岐。」という説明を書いています。スクロール量で判別するのは雲の画像と同じですが、ここで最初に変数定義した「bottomPos」や「UFO」「UFOflag」を使っています。
以上です。 記述が終わったら、index.htmlをブラウザで開いて、 動画が表示されているかどうか確認してみてください。
今回のコード内の各数値を調整してみたり、アイテムを増やしたり減らしたりと部分的に変更してみたり、自分なりに色々と応用してみるとしだいにスクロールアニメーションに慣れてきて面白い仕組みをどんどん考えられるようになりますよ!
課題の提出
今回のスクロールアニメーションも課題として提出を行います。
「html_anime」フォルダのデータを提出しましょう。
提出用に「html_anime」フォルダをまるごとzip形式で圧縮してください。
「html_anime」フォルダをzip形式で圧縮
まず、「html_anime」フォルダ圧縮の手順は以下。
- 「html_anime」フォルダを右クリックして、「送る」→「圧縮(zip形式フォルダー)」を選択してzipファイルを作る。
- ファイル名を「自分の学籍番号_anime」に変更する。
以上です。
zip圧縮したファイルをフォームから送信
なお、こちらのフォームに提出できるのは「zip形式で圧縮したファイルのみ」です。zip形式ではないファイルだと送信の際にエラーが出て送信ができませんので、必ず「html_anime」フォルダをまるごと圧縮してzip形式で提出してください。
課題の提出ができたら今回の講義は終了です。