【bxSlider】コールバック関数を使って2つのスライダーを連動させてみた
弊社ではトップページのメイン画像をスライダーにすることが多く、jQueryプラグインのbxSliderをよく利用しています。
最近このbxSliderのコールバック関数を勉強する機会があったので、より理解度を深めるため実際の提案でもあった2つのスライダーの連動を実装してみたいと思います。
弊社ブログのbxSlider関連の記事は下記からご確認ください。
- jQueryプラグイン「bxSlider」の使い方とオプションとカスタマイズまとめ(導入編)
- jQueryプラグイン「bxSlider」の使い方とオプションとカスタマイズまとめ(実践編)
- jQueryプラグイン「bxSlider」の使い方とオプションとカスタマイズまとめ(コールバック関数編)
- jQueryプラグイン「bxSlider」の使い方とオプションとカスタマイズまとめ(パブリックメソッド編)
仕様の設定
2つのスライダーを連動させるというのは具体的にどういう挙動なのか、細かく見ていきましょう。
まず見かけ上のスライダーは2つ。
ページャーとコントローラーはスライダー1の操作に紐づいています。
初期の状態でスライダー1にはスライド1が、スライダー2にはスライド2が表示されています。
スライダー1がスライド2を表示すると同時にスライダー2はスライド3を、スライダー1がスライド3を表示するとスライダー2はスライド4を表示、というようにスライダー2にはスライダー1の次の画像を表示します。
そしてこれは自動再生であってもページャーやコントローラー操作であっても同様の表示結果とします。
次に逆順に切り替わる場合、つまりコントローラーでスライダー1を戻したとき。スライダー2にはスライダー1に表示していたスライドを表示します。
ページャー操作についても同様に、スライダー2は常にスライダー1の次のスライドを表示します。
そして、スライドの切り替え方法は左右とします。これは進んだり戻ったりしている向きをわかりやすくするためです。
以上が今回実装する2つのスライダーの連動についての仕様となります。
スライダーを2つ作る
それでは実際に実装していきます。
スライダー1は既にでき上がっている状態からスタートします。id=”mainvisual”がスライダーになり、それを囲む2つのラッパーで構成されています。
<div class="mainvisual__wrap">
<div class="mainvisual-area">
<ul id="mainvisual">
<li><img src="./common/image/main-ph001.jpg" alt="IMAGE" /></li>
<li><img src="./common/image/main-ph002.jpg" alt="IMAGE" /></li>
<li><img src="./common/image/main-ph003.jpg" alt="IMAGE" /></li>
</ul>
</div>
</div>
$(document).ready(function(){
let sImage = $('#mainvisual li').length;
if(sImage > 1){
let slider001 = $('#mainvisual').bxSlider({
pager: true,
controls: true,
mode: 'horizontal',
auto: true,
speed: 500,
pause: 2000,
touchEnabled: true
});
}
});
このスライダーをもう一つ作ります。
単純に同じHTMLを書くという方法もありますが、内容が同じHTMLを二か所に書くというのは保守の面でコストがかかります。 そのため今回はスライダー1をjQueryでコピーします。
まず単純にスライダー1のHTMLをコピーしスライダー1のあとに記述してみます。コピーには.clone()を、記述には.appendTo()を使用します。
$(document).ready(function(){
const mainClone = $(".mainvisual-area").clone();/*スライダー1をコピー*/
const mainWrap = $(".mainvisual__wrap");/*一番外側のラッパーを定義*/
$(mainClone).appendTo(mainWrap);/*スライダー1のコピーを一番外側のラッパーの最後に記述*/
/*以下省略*/
無事にコピーできました。
ただ全く同じ記述なので、このままでは同じidが二つ存在してしまいます。
また、スライダー2として扱いたいので、idとclassを置き換えます。
$(document).ready(function(){
const mainClone = $(".mainvisual-area").clone();
const mainWrap = $(".mainvisual__wrap");
const mva002 = $(mainClone).appendTo(mainWrap).attr('class',"mainvisual-area002");/*コピーを記述すると同時にclassを変更*/
const mv002 = $(mva002).children("ul").attr('id',"mainvisual002");/*記述したコピーのulのidを変更*/
/*以下省略*/
これでコピーしたスライダーのclassとidが変更されました。
このコピーした記述にbxSliderを適用させればスライダー2ができ上がります。
$(document).ready(function(){
/*スライダーをコピーする記述省略*/
let sImage = $('#mainvisual li').length;
if(sImage > 1){
/*スライダー1の設定記述省略*/
let slider002 = $('#mainvisual002').bxSlider({/*スライダー2の設定記述*/
pager: false,
controls: false,
mode: 'horizontal',
speed: 500,
pause: 2000,
touchEnabled: true
});
}
});
スライダー2ができました。
初期状態ではスライダー2にはスライド2が表示されていてほしいので、スライダー2のスライドの順番を変更します。
$(document).ready(function(){
const mainClone = $(".mainvisual-area").clone();
const mainWrap = $(".mainvisual__wrap");
const mva002 = $(mainClone).appendTo(mainWrap).attr('class',"mainvisual-area002");
const mv002 = $(mva002).children("ul").attr('id',"mainvisual002");
const mv002FirstList = $(mv002).children().first();/*1つめのスライドを定義する*/
$(mv002FirstList).appendTo(mv002);/*1つめのスライドを一番最後に移動する*/
/*以下省略*/
スライド2が初期状態で表示されました。
これでスライダー2の設置は完了になります。
次はこのスライダーをスライダー1に連動させてみましょう。
2つのスライダーを連動させる
スライダーを連動させるためにbxSliderのコールバック関数を使用します。
コールバック関数に関してはこちらの記事を参考にしてください。
jQueryプラグイン「bxSlider」の使い方とオプションとカスタマイズまとめ(コールバック関数編)
スライダー1が次のスライドに移動するタイミングで、スライダー2も移動してほしいので、スライダー1にコールバック関数onSlideBeforeを追加します。
$(document).ready(function(){
/*スライダーをコピーする記述省略*/
let sImage = $('#mainvisual li').length;
if(sImage > 1){
let slider001 = $('#mainvisual').bxSlider({
pager: true,
controls: true,
mode: 'horizontal',
auto: true,
speed: 500,
pause: 2000,
touchEnabled: true,
onSlideBefore: function($slideElement, oldIndex, newIndex) {/*コールバック関数でスライダー2を連動*/
slider002.goToSlide(newIndex);
},
});
/*以下省略*/
スライダー1に合わせてスライダー2が動くようになりました。
しかしよく見ると、一番最後のスライドから一番最初のスライドに進むときと、一番最初のスライドから一番最後のスライドに戻るとき、スライダー2の挙動がおかしくなっていることが確認できます。
これはbxSliderがスライドをループさせる際、一番最初のスライドの前と一番最後のスライドの後にアイテムをクローンして、スライドする挙動をあたかも進んでいるようにもしくは戻っているように見せる仕様になっているためです。
スライダー1にはその仕様が適用されているのに対し、コールバックで動かしているスライダー2には適用されていないため、チグハグな挙動になっています。つまりスライダー2にもスライダー1と同じ条件の時に、進み、戻るように調整すれば挙動は一致するはずです。
ここで、スライダーがスライドする条件を考えてみましょう。次の3パターンが考えられます。
- 自動再生で次のスライドに移動する
- コントローラを押して次もしくは前のスライドに移動する
- ページャーを押して、任意のスライドに移動する
この中で一番最後のスライドから一番最初のスライドに進む挙動をする必要があるのは1と2になります。(一番最初から一番最後に戻る場合も同じです。)
ページャーを使って一番最後から一番最初にスライドする場合の挙動は、進むのではなく一番最初の画像に戻る挙動となります。すなわちページャーが押されているかどうかを判断し、押されている場合といない場合でスライダー2の挙動を調整すれば問題は解決します。
ページャークリックのフラグを設定する
ではページャーがクリックされたときのフラグを作成します。
まずはbxSliderの記述の外側にフラグの変数を宣言します。
そしてコールバック関数のonSliderLoadを用いてクリックされた判定を、onSlideAfterを用いて判定の解除を行います。
$(document).ready(function(){
/*スライダーをコピーする記述省略*/
let pagerFlag = false;/*フラグの宣言(デフォルトはfalse)*/
let sImage = $('#mainvisual li').length;
if(sImage > 1){
let slider001 = $('#mainvisual').bxSlider({
pager: true,
controls: true,
mode: 'horizontal',
auto: true,
speed: 500,
pause: 2000,
touchEnabled: true,
onSliderLoad: function(currentIndex) {
$('.bx-pager-item a').on('click', function(){
pagerFlag = true;/*ページャーがクリックされたらフラグをtrueに*/
});
},
onSlideBefore: function($slideElement, oldIndex, newIndex) {
slider002.goToSlide(newIndex);
},
onSlideAfter: function($slideElement, oldIndex, newIndex) {
pagerFlag = false;/*スライドし終わったらフラグをfalseに戻す*/
}
});
/*以下省略*/
これでページャーをクリックしたかどうかの判定が可能になります。
スライドしたらフラグがなくなるので、再度スライドするときにページャーを押したかどうか判定することができます。
条件によってスライダー2の挙動を調整する
それでは条件によってスライダー2の挙動を調整します。
その前にスライドを移動させるパブリックメソッドについて、知っておきましょう。
bxSliderのパブリックメソッドについてさらに詳しく知りたい方は下記の記事を参考にしてください。
jQueryプラグイン「bxSlider」の使い方とオプションとカスタマイズまとめ(パブリックメソッド編)
スライドを移動させるには下記の3つの手段があります。
- goToSlide 指定したスライドに移動
- goToNextSlide 次のスライドに移動
- goToPrevSlide 前のスライドに移動
挙動としてはgoToNextSlideが進む、goToPrevSlideが戻るとなります。
先ほどのテストで見たように、一番最後のスライドから一番最初のスライドに進むとき、一番最初のスライドから一番最後のスライドに戻るとき、かつそれぞれページャーがクリックされていないときを条件に、スライダー2の挙動を調整します。
$(document).ready(function(){
const mainClone = $(".mainvisual-area").clone();
const mainWrap = $(".mainvisual__wrap");
const mva002 = $(mainClone).appendTo(mainWrap).attr('class',"mainvisual-area002");
const mv002 = $(mva002).children("ul").attr('id',"mainvisual002");
const mv002FirstList = $(mv002).children().first();
$(mv002FirstList).appendTo(mv002);
let pagerFlag = false;
let sImage = $('#mainvisual li').length;
if(sImage > 1){
let slider001 = $('#mainvisual').bxSlider({
pager: true,
controls: true,
mode: 'horizontal',
auto: true,
speed: 500,
pause: 2000,
touchEnabled: true,
onSliderLoad: function(currentIndex) {
$('.bx-pager-item a').on('click', function(){
pagerFlag = true;
});
},
onSlideBefore: function($slideElement, oldIndex, newIndex) {
if(pagerFlag === false && newIndex === 0 && oldIndex === (sImage - 1)) {/*ページャーをクリックしていない、かつ一番最後から一番最初に進むとき*/
slider002.goToNextSlide();
} else if (pagerFlag === false && newIndex === (sImage - 1) && oldIndex === 0) {/*ページャーをクリックしていない、かつ一番最初から一番最後に戻るとき*/
slider002.goToPrevSlide();
} else {
slider002.goToSlide(newIndex);
}
},
onSlideAfter: function($slideElement, oldIndex, newIndex) {
pagerFlag = false;
}
});
let slider002 = $('#mainvisual002').bxSlider({
pager: false,
controls: false,
mode: 'horizontal',
speed: 500,
pause: 2000,
touchEnabled: true,
});
}
});
最後のスライドから最初のスライドに進む挙動も、最初のスライドから最後のスライドに戻る挙動も問題なく実装できました。
また、ページャーをクリックした際の挙動も想定通りの挙動となっていますので、実装完了となります。
さいごに
いかがでしたでしょうか。
bxSliderのコールバック関数を使うと、スライダーの細かい挙動やスライド時に応じて様々なことが可能になります。
工夫次第でより複雑な実装もできるので、今後も積極的に使用していきたいと思います。
この記事を書いた人
- アーティスへ入社後、webデザイナーとして大学サイトや病院サイト、企業サイト等のデザイン・コーディングに携わる。資格:Photoshopクリエイター能力認定試験スタンダード、illustratorクリエイター能力認定試験エキスパート、Webクリエイター能力認定試験初級
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー