動画を使ったスライドショーをslickで実装
動画を使ったスライドショーを実装する機会がありまして、slickのイベントを組み合わせる方法が便利だったので備忘録的に書き残しておきます。
この記事の目次
スライドショーの仕様
スライドショーの仕様は以下のとおりです
- 再生時間がバラバラの動画を使ったスライドショー
- 動画の数は3つ
- ドットインジケーターを用意してクリックすると別の動画に移動する
- 移動した際は最初から動画を再生する
サンプルを用意したので、一度見て触ってもらうのが一番かと思います
スライドショーのHTML
HTMLはシンプルに作っています
スライドショーはslickを使うので全体を囲むようにdiv要素を作り、中にはvideo要素を使って表示したい動画を読み込みました。
動画の再生は、JavaScriptから制御する形を取るのではautoplayは付けずにmutedとplaysinlineだけにしておきます
動画の再生時間を調べる必要があるので、それぞれクラスを付けておくと後々の処理が楽になります
slickを使う上で必要なファイル類の読み込みもお忘れなく
1 2 3 4 5 |
<div class="slider"> <video src="video/video1.mp4" muted playsinline class="video1"></video> <video src="video/video2.mp4" muted playsinline class="video2"></video> <video src="video/video3.mp4" muted playsinline class="video3"></video> </div> |
スライドショーのjs(jQuery)
slickで予め用意されているafterChangeイベントを使って処理をしていきます
色々と準備が必要になるので順ををって書いていきます
処理に使う変数の準備
まずは、処理をするvideo要素を変数に入れていきます。 video要素に関してはそのままjQueryオブジェクトにしてもうまく操作ができないので「getメソッド」を使っていきます
1 2 3 4 5 |
$(function() { var $video1 = $('.video1').get(0), $video2 = $('.video2').get(0), $video3 = $('.video3').get(0); }); |
動画の再生時間を取得
次に今回の処理をする時に重要になってくるのが再生時間の取得をしていきます。
予めわかっていれば直接数値を入れてもいいとは思いますが今回は差し替えたときでも簡単に対応できるようにこういった仕様にしてみました。
「duration」を使うと単位が秒の形で取得できるのですが、今回の処理でハマった点でもありまして、「loadedmetadata」イベントが起きたあとでないとうまく取得できないのでイベントと組み合わせていきます。
最後に記述したvideo要素のメタデータが読み込まれた時に実行するようにセレクタは「 $(‘.video3’)」としています
slickでは再生時間をミリ秒で指定する必要がありますので、取得したものを1000倍して小数点以下を切り捨てする形にしてみました
1 2 3 4 5 6 7 8 9 |
$(function() { $('.video3').on('loadedmetadata', function() { var $video1 = $('.video1').get(0), $video2 = $('.video2').get(0), $video3 = $('.video3').get(0), videoTime1 = Math.floor($video1.duration * 1000), videoTime2 = Math.floor($video2.duration * 1000), videoTime3 = Math.floor($video3.duration * 1000); }); |
jsから1つ目の動画を再生させる
動画を再生させる処理を実行していきます。
操作方法は以下のとおりですので確認しておくといいと思います。
1 2 3 |
video.play() // ビデオを再生 video.pause() // ビデオを停止 video.currentTime = 10 // 再生から10秒のところに移動する |
最初に表示するvideo要素に対して「.play()」を使っていきましょう。
1 2 3 4 5 6 7 8 9 10 |
$(function() { $('.video3').on('loadedmetadata', function() { var $video1 = $('.video1').get(0), $video2 = $('.video2').get(0), $video3 = $('.video3').get(0), videoTime1 = Math.floor($video1.duration * 1000), videoTime2 = Math.floor($video2.duration * 1000), videoTime3 = Math.floor($video3.duration * 1000); $video1.play(); }); |
slickを初期化させスライドショー開始
処理で使うものの準備ができたのでslickを初期化していきます。
ユーザーからの操作はドットインジケーターだけに絞りたいので各種操作を無効化していきます
スライドの表示時間はオプションの『autoplaySpeed』を使うと設定できます。
最初に表示するvideo要素の再生時間は変数に格納済みなので、こちらの変数を値に指定すると、動画の再生が終わったと同時に次の動画に切り替わるような動きを出すことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$(function() { $('.video3').on('loadedmetadata', function() { var $video1 = $('.video1').get(0), $video2 = $('.video2').get(0), $video3 = $('.video3').get(0), videoTime1 = Math.floor($video1.duration * 1000), videoTime2 = Math.floor($video2.duration * 1000), videoTime3 = Math.floor($video3.duration * 1000); $video1.play(); $('.slider').slick({ autoplay: true, arrows: false, fade: true, autoplaySpeed: videoTime1, swipe: false, pauseOnHover: false, pauseOnFocus: false, dots: true, dotsClass: 'video_dots', }); }); }); |
afterChangeイベントと条件分岐を使って再生時間を変更する
最後にslickで予め用意されている「afterChangeイベント」を使っていきます。
「afterChangeイベント」はスライドが切り替わった直後に処理を実行させるために使うslick独自のイベントです
詳しくは以下のリンク先でまとめているのでご覧ください
「afterChangeイベント」で使用する引数の「currentSlide」には表示中のvedeo要素のINDEXが入っていますので、そちらを使いつつ条件分岐をさせていきます
ここではswitch文を使っていますが、もちろんif分でもOK
スライドの表示時間の変更はslickSetOptionメソッド
スライドの表示時間はslickを初期化する際に、1つ目のvideo要素の再生時間を使って『autoplaySpeed』で設定しています。
条件分岐は表示中のvideo要素によってスライドの表示時間を変えるために使っています。
slick独自のslickSetOptionメソッドを使えば、オプションの変更ができるので条件分岐と合わせて、スライドの表示時間を変更させてあげれば完成になります。
slick独自のメソッドについては以下のリンク先でまとめていますのでご確認ください
条件分岐の中では表示中のvideo要素を再生させる処理や、表示していないvideo要素の再生を止め、最初に巻き戻す処理もしています。
最終的に以下のようなコードになりました
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
$(function() { $('.video3').on('loadedmetadata', function() { var $video1 = $('.video1').get(0), $video2 = $('.video2').get(0), $video3 = $('.video3').get(0), videoTime1 = Math.floor($video1.duration * 1000), videoTime2 = Math.floor($video2.duration * 1000), videoTime3 = Math.floor($video3.duration * 1000); $video1.play(); $('.slider').slick({ autoplay: true, arrows: false, fade: true, autoplaySpeed: videoTime1, swipe: false, pauseOnHover: false, pauseOnFocus: false, dots: true, dotsClass: 'video_dots', }).on('afterChange', function(event, slick, currentSlide, nextSlide) { switch (currentSlide) { case 0: $(this).slick('slickSetOption', 'autoplaySpeed', videoTime1); $video1.play(); $video2.pause(); $video2.currentTime = 0; $video3.pause(); $video3.currentTime = 0; break; case 1: $(this).slick('slickSetOption', 'autoplaySpeed', videoTime2); $video2.play(); $video1.pause(); $video1.currentTime = 0; $video3.pause(); $video3.currentTime = 0; break; case 2: $(this).slick('slickSetOption', 'autoplaySpeed', videoTime3); $video3.play(); $video1.pause(); $video1.currentTime = 0; $video2.pause(); $video2.currentTime = 0; break; } }); }); }); |
スライドショーのCSS
今回のケースでは特別なcssを書く必要はありませんが、ドットインジケーター用のものを書いています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
.video_dots{ list-style-type: none; padding: 0; display: flex; justify-content: center; } .video_dots li{ margin: 0 10px; } .video_dots button{ outline: none; border: none; background-color: #bfbdbd; width: 30px; height: 30px; display: flex; justify-content: center; align-items: center; border-radius: 15px; overflow: hidden; text-indent: -10000px; cursor: pointer; } .slick-active button{ background-color: #000; color: #fff; } |