Carousel関数内にいろいろと追記しました。初めにもろもろの処理を行いやすくするために、各HTML要素を変数に格納します。次にinitializeでviewportの幅と画像の数からcontentsの幅を指定します。これで画像ファイルを横一列に並べることができます。
HTML側に以下のJavaScriptを記述してカルーセルプラグインを呼び出してみましょう。
$(window).on('load', function() { $('.carousel').carousel(); });
Webブラウザで確認すると画像もviewportにピッタリ収まっているのが分かるかと思います。
では次にスライド機能の実装です。戻るボタンと進むボタンをそれぞれクリックすることで画像が入れ替わるようにします。
Carousel関数内に以下のようにコードを追記します。
function Carousel(root, options) { var self = this, ... forward = true; var setEvents = function() { btnPrev.click(function(){ current = current - 1 === -1 ? steps : current; self.move(-1); return false; }); btnNext.click(function(){ current = current +1 === steps ? -1 : current; self.move(1); return false; }); } this.move = function (direction) { current += direction; if(current > -1 && current < steps) { content.animate({ 'left': -(current * pageSize) }, 1000); } }; var initialize = function() { pages.width(viewport.width()); pageSize = $(pages[0]).outerWidth(true); steps = pages.length; content.css('width', (pageSize * pages.length)); setEvents(); return self; } return initialize(); }
moveという関数を定義しました。画像の切り替え方向をdirectionというパラメータで受け取り、jQueryのアニメーション関数でcontentsのleft値を更新しています。このmove 関数を戻るボタンと進むボタンのクリックイベントから呼び出すわけです。そのためのクリックイベントハンドラをsetEvents関数内で定義します。
ここまででもう一度Webブラウザ上で確認してみましょう。どうですか? ボタンクリックで画像が入れ替わったでしょうか?
最後の要件である『画像の表示は一定時間ごとに自動的に切り替わり、循環して表示される』を実装します。
Carousel関数内に以下のようにコードを追記します。
function Carousel(root, options) { var self = this, ... forward = true; var setTimer = function() { clearTimeout(timer); timer = setTimeout(function(){ current = current +1 === steps ? -1 : current; forward = current +1 === steps ? false : current === 0 ? true : forward; self.move(forward ? 1 : -1); }, 3000); } ... this.move = function (direction) { current += direction; if(current > -1 && current < steps) { contents.animate({ 'left': -(current * pageSize) }, options.duration, function() { if(typeof options.callback === 'function') { options.callback.call(this, pages[current], current); } }); setTimer(); } }; … }
setTimerという関数を定義しました。やっている内容としては、初めにclearTimeout を呼び出してイベントハンドラをリセットし、あらためてsetTimeoutをセットしてその中でmove関数を呼び出しています。呼び出す間隔はひとまず3秒間隔にしておきました。ここは最後にオプションから変更できるようにします。
最後にオプションを渡せるようにします。今回渡せるパラメータとしては
以上の4つにするとします。これらを反映した完成版が以下になります。
;(function ($) { $.fn.carousel = function(options) { var elements = this; var opts = $.extend({}, $.fn.carousel.defaults, options); elements.each(function () { $(this).data('carousel', new Carousel($(this), opts)); }); return this; }; $.fn.carousel.defaults = { interval: false, intervalTime: 3000, duration: 1000, callback: null }; function Carousel(root, options) { var self = this, viewport = root.find('.viewport:first'), contents = root.find('.contents:first'), pages = contents.children(), btnNext = root.find('.next:first'), btnPrev = root.find('.prev:first'), pageSize = 0, steps = 0, current = 0, timer = undefined, forward = true; var setTimer = function() { if(options.interval) { clearTimeout(timer); timer = setTimeout(function(){ current = current +1 === steps ? -1 : current; forward = current +1 === steps ? false : current === 0 ? true : forward; self.move(forward ? 1 : -1); }, options.intervalTime); } } var setEvents = function() { btnPrev.click(function(){ current = current - 1 === -1 ? steps : current; self.move(-1); return false; }); btnNext.click(function(){ current = current +1 === steps ? -1 : current; self.move(1); return false; }); } this.move = function (direction) { current += direction; if(current > -1 && current < steps) { contents.animate({ 'left': -(current * pageSize) }, options.duration, function() { if(typeof options.callback === 'function') { options.callback.call(this, pages[current], current); } }); setTimer(); } }; var initialize = function() { pages.width(viewport.width()); pageSize = $(pages[0]).outerWidth(true); steps = pages.length; contents.css('width', (pageSize * pages.length)); self.move(0); setEvents(); return self; } return initialize(); } })(jQuery);
これでプラグインが完成しました。以下のように呼び出せばOKです。
$(window).on('load', function() { $('.carousel').carousel({ interval: true, intervalTime: 3000, duration: 'fast', callback: function() { console.log('Image changed.'); } }); });
既存のjQueryプラグインを探してみたけど、自分がホントにほしい機能とは微妙に違っているものしか見つからないといったシチュエーションは良くあります。ちなみにjQueryは$.fnを使って自作関数をjQueryに組み込むことでprototype拡張を実現するというポリシーで成り立っています。世の中にはとんでもないような高機能のプラグインが無数にありますが、基本的な構造はこれまでに挙げたサンプルコードとそこまでの違いはありません。足りない機能、欲しい機能はプラグインを自作するという習慣を少しずつ積み重ねていけば、やがては大規模で高性能なプラグインを作れるだけのスキルが身に付いてきます。
小さなことからコツコツと。
著者プロフィール
山田直樹(やまだ なおき)
クラスメソッドではたらくフロントエンド・エンジニア。JavaScript・HTML・CSSによる開発を主な生業とする一方、スタイリッシュかつクールなデザインを何よりも愛していることから、UIデザインを担当することもしばしば。実はプログラムよりも洋服を自作するのが一番得意だったりする。
Copyright © ITmedia, Inc. All Rights Reserved.