こんにちは。フロントエンドエンジニアのオオクボです。
日頃ネットサーフィンを楽しんでいると、ポートフォリオサイトやコーポレートサイトでお洒落なスライドショーを目にする事があるかと思います。
移ろいゆく画像が素敵なWebデザインにおける代表的なパーツの一つですね。我が社のCMS「BiNDup」 にも「SHiFT」の名称で作成機能が搭載されています。
今回は jQuery で実現できるフェードアニメーションとシンプルな画像API「Unsplash Source」を用い、スライドショー実装の考え方について最小限のコードで紐解いていきたいと思います。
コードと表示結果
See the Pen スライド(フェード) by dsOokubo (@dsOokubo) on CodePen.
利用するサービス
CodePen
HTML, CSS, JavaScript 等、主にフロントエンドの言語をコーディングできるオンラインエディター。
コードの実行結果がリアルタイムで表示される為、Webデザインの勉強やスニペットにお誂え向きなサービスです。
こちらからエディター画面に直飛びできますので、今回のコードを複製の上動作をお試しください。
CodePen で jQuery を使う方法については、記事最後にある「備考:CodePen で jQuery を使う」をご覧ください。
Unsplash Source
フリー写真素材サイト「Unsplash」にアップロードされている写真を参照できるサービス。
スライドショーに用いる画像はこちらで取得します。
解説
手法は様々ありますが、今回のフェードアニメーション・スライドショーを実現するための基本的なプロセスは下記の3つです。
以降、スライドショーにおいて今現在目に映っている画像を「画像A」、画像Aの次に表示される画像を「画像B」と表記します。
- 画像Aを表示する
- 画像Bを画像Aの後ろに用意する
- アニメーションを効かせながら画像Aを削除し、画像Bを表示する
紙芝居をイメージすると良いかもしれません。観客に現在見せている絵が画像A(1)、その後ろに重なり控えている絵が画像B(2)、そして、見せ終わった画像Aを横に引き抜いて裏に回す動作が CSS や jQuery で実現するアニメーション(3)に当たります。
それではコードを追いながら、一体どこが何の役割を果たしているのか見ていきましょう。
HTML
<div id="root"></div>
器となるdiv
要素を用意しておきます。このdiv
要素の中にスライドショーの実体となるimg
要素をjQueryで追加し、jQuery アニメーションで見せたり消したりしていきます。
CSS や jQuery から識別・参照しやすいように「root」というidを振っておきます。
CSS
#root > img { width: 450px; height: 300px; object-fit: cover; position: absolute; };
セレクタ#root > img { ... }
で、id「root」が割り振られたdiv
要素の直下に来るimg
要素(スライドショーの実体)に限定し、波括弧内の CSS を適用していきます。
スライドショーの幅は 450px、高さは 300px とし、これに合わせてobject-fit: cover;
で画像の中央部分をトリミング、position: absolute;
で画像Aと画像Bを同じ場所に配置し、重ね合わせます。
トリミングは Unsplash Source で取得する画像の幅・高さがまちまちであるため必要となります
(実際には画像取得時、幅・高さを指定することもできますが、取得に時間を要するせいかスライドショーのページ送りが乱れてしまうため、今回は採用しません)。
またposition: absolute;
が無い場合、画像Aと画像Bが横並びとなってしまい、スライドショーの体を成しません。
しかしこれを削除した上でコードを動かしてみると画像A, Bそれぞれの状態変化が同時に分かり、理解の助けとなるかもしれません。
JavaScript(jQuery)
スライドショーの肝となるJavaScript(jQuery)を紐解いていきます。
画像表示時間とアニメーションの速度を定義
const imgDisplayTime = 4000; const animationSpeed = 3000;
スライドショーの画像を表示する時間と、その時間を経たのち次の画像に遷移する際にかかるフェードアニメーションの速度を定義しておきます。
後々これらを利用するメソッドの仕様上、単位はミリ秒(ms)となります。今回は画像表示時間(imgDisplayTime)を 4000ms(4秒)、フェードアニメーション速度(animationSpeed)を 3000ms(3秒)とします。
尚、画像表示時間がフェードアニメーション速度よりも短い場合(imgDisplayTime < animationSpeed)、フェード効果が走り切るのを待たずして次の画像に切り替わってしまう為、実際にはこれを防ぐ考慮が必要となる点に注意してください。
スライドショー処理本体を定義
const replaceImg = () => { ... };
スライドショー処理の本体「replaceImg」を定義します。
「replaceImg」は「表示中の画像Aをフェードアウトさせた後、削除する」と「画像Bを Unsplash から取得し、スライドショーにセットする」の2つの処理から成り立っており、これらを一定時間おきに実行する事によってスライドショーが作り上げられます。
それぞれに分けて中身を見ていきましょう。
① 画像Aをフェードアウトさせた後、削除
const fadeOutImg = $('#root').children(); fadeOutImg.css('z-index', 1).fadeOut(animationSpeed).queue(() => { fadeOutImg.remove(); });
const fadeOutImg = $('#root').children();
で「root」を id に持つdiv
要素直下にある要素(=画像A)を取得、これに「fadeOutImg」と命名。
fadeOutImg.css('z-index', 1)
で画像Aが画像Bより手前に表示されるよう重なり順序を指定し、.fadeOut(animationSpeed).queue(() => { fadeOutImg.remove(); });
で 画像Aを「animationSpeed」に代入した時間をかけてフェードアウトさせたのち削除しています。
用意する順序の都合上、新たに取得した画像Bが既存の画像Aより上に表示されてしまうので、CSS のz-index
プロパティで重なり順序を逆転させています。
フェードアウト効果は jQuery のfadeOut
メソッドで実現しています。
jQuery は他にも要素にアニメーションをかけるメソッドを複数持っており、一例としてfadeOut
をslideUp
に置き換えると、画像がスライドアップして切り替わるスライドショーに変化します。是非お手元で試してみてください。
尚この処理ですが、初回実行時はdiv
要素直下に要素が存在しない(ターゲットに当たる画像Aが未取得)である為、効果はありません。
② 画像Bを取得し、スライドショーにセット
const fadeInImg = new Image(); fetch('https://source.unsplash.com/random') .then(res => { fadeInImg.src = res.url; $('#root').append(fadeInImg); }
const fadeInImg = new Image();
で新たなimg
要素(=画像B)を生成、これに「fadeInImg」と命名。
fetch('https://source.unsplash.com/random') { ... }
でスライドショー用の画像を取得、これに成功した場合(.then(res => { ... }
)、生成したimg
要素のsrc
属性に画像の URL をセットし(fadeInImg.src = res.url;
)、「root」をidに持つdiv
要素直下にそのimg
要素を追加しています($('#root').append(fadeInImg);
)。
ここで Unsplash Source の登場です。こちらを用い、今回はランダムに Unsplash 上の画像を取得しています。
画像取得においては「https://source.unsplash.com/」以降にオプションを追記する事で条件が指定でき、キーワードでジャンルを絞ったり、特定のユーザーがアップロードした画像を取得する事も可能です。
以下にいくつか形式を示します。URL 中の { 条件 } を任意のワードに置き換えた上でブラウザのアドレスバーに入力し、動作を試してみてください。
・サイズを指定してランダムに画像を取得
https://source.unsplash.com/random/{数字(幅)}x{数字(高さ)}
・キーワードでジャンルを絞って取得
https://source.unsplash.com/featured/?{キーワード},{キーワード}
・特定ユーザーがアップロードした写真を取得
https://source.unsplash.com/user/{ユーザー名}
・特定ユーザーのいいねからランダムに取得
https://source.unsplash.com/user/{ユーザー名}/likes
余談ですが、画像にブラー効果(ぼやけたエフェクト)をかけたり、写真についての詳細情報を参照したり等、高度なカスタマイズをした上でアプリケーションに組み込みたい場合は、Unsplash API (無料・アカウント作成要・リクエスト数制限あり)が便利です。
スライドショー処理を定期間隔で実行
setInterval(replaceImg, imgDisplayTime);
仕上げです。指定した時間おきに処理を呼び出す JavaScript のメソッドsetInterval
で、画像のフェードアウトと取得を行う「replaceImg」関数を、設定した画像表示時間(imgDisplayTime)間隔で実行します。
これで簡易的なフェードアニメーション・スライドショーの完成です。
まとめ
実際にWebサイトに配置する場合は、スタイリングの兼ね合いや画像取得に失敗した時のフォールバック、ページ送り機能が欲しい等々無数に考慮が要されるかと思います。
またスライドショーのバリエーションも、今回取り上げたシンプルなフェードの他、水平に画像がスライドするものから幾何学模様のエフェクトが掛かりながら画像が遷移するもの等々様々で、アニメーションの種類に応じた手法が問われます。
しかし「画像を移り変わり見せるもの」という本質的な機能はいずれも変わりませんから、これを見失わずに着想を加え、実装を進めていけば、オリジナリティのあるスライドショーを作成する事ができるのではないでしょうか。
Web制作入門の題材選びにおいて、スライドショーを候補に加えるきっかけとなれれば幸いです。
備考:CodePen で jQuery を使う
今回ご紹介した CodePen ですが、初期状態では jQuery が使えません。 CodePen のエディター画面から以下の操作が必要となります。
①「Settings」をクリック
②「JS」タブを選択
③ 検索バーに「jquery」を入力し、候補から選択
④「Save & Close」をクリック
以上で、jQuery が CodePen で利用可能となります。
jQuery の他 React, Vue, Angular といった Webアプリケーションフレームワークや、TypeScript 等も有効にできるので、ご活用ください。