どうにか出来そうなのでメモとして。
レスポンシブでの切り替え時に停止と再開を行う動作に関しては、より良い方法があるかもしれませんが今のところこの程度という感じです。
前提
- Keen-Slider使用(v6.3.1)
- Reactなどに組み込んでbuildするような使い方ではなく、他のライブラリのようにJSを読み込ませ、設定をテンプレート側に記載する方法で行う
Keen-Slider
上記が公式のドキュメントですが検索で解説記事は複数見つかると思いますので、当記事ではKeen-Sliderに関する基本的な説明は省きます。
Reactなどを使わずに利用する
基本的には上記記事を参考にすれば動作可能ですが、バージョン違いなのか記事掲載のコードではエラーが出て動かない部分があります。
そのため以下のようにupdateClasses()を一部書き換える必要があります。
/**
* 各要素のCSSクラスを更新
* @param instance
*/
function updateClasses(instance) {
// 現在表示しているスライドの列番号を取得
const slide = instance.track.absToRel( instance.track.details.abs );
// 前後にスライドする矢印ボタンの状態を更新
const arrowLeft = document.getElementById("arrow-left");
const arrowRight = document.getElementById("arrow-right");
slide === 0 // 最初のスライドの場合
? arrowLeft.classList.add("arrow--disabled")
: arrowLeft.classList.remove("arrow--disabled");
slide === instance.slides.length -1 // 最後のスライドの場合
? arrowRight.classList.add("arrow--disabled")
: arrowRight.classList.remove("arrow--disabled");
// 生成されたドットインジケーターの要素を取得し状態を更新
const dots = document.querySelectorAll(".dot");
dots.forEach((dot, idx) => {
idx === slide
? dot.classList.add("dot--active")
: dot.classList.remove("dot--active");
})
}
書き換えた箇所は以下の2点。
relativeSlideの書き換え
const slide = instance.details().relativeSlide;
// ↓以下に変更
const slide = instance.track.absToRel( instance.track.details.abs );
現在はrelativeSlideというオブジェクトはないので、trackオブジェクトからdetailsを経由してabsで現在表示中のスライドの絶対的インデックス番号を取得します。
このabsはloop:tureの場合は数がどんどん増えていくので、同じくtrackオブジェクトのabsToRelを使って、absの絶対インデックス番号から相対的インデックス番号に変換し、現在のスライドを特定するためのインデックス番号を取得しています。
なお、loop:falseの場合はabsのみで問題ありません。
details().sizeの書き換え
newでKeen-Sliderのインスタンスを作成した部分でも以下の書き変えが必要になりました。
dot.addEventListener("click", () => {
instance.moveToSlide(idx);
});
↓ 以下に書き換え
dot.addEventListener("click", () => {
instance.moveToIdx(idx);
});
slide === instance.details().size - 1
// ↓以下に変更
slide === instance.slides.length -1
同じく現在はdetails().sizeという記述は使えないので、設置されているスライドのHMTLがセットされている配列のslidesを用いて、その要素数をlengthで取得する必要があります。
moveToSlideの書き換え
v6.6.8(それ以前かもしれませんが)では、newでKeen-Sliderのインスタンスを作成した部分でも以下の書き変えが必要になりました。
instance.moveToSlide(idx);
// ↓以下に変更
instance.moveToIdx(idx);
ライブラリのアップデートの影響
前出の記事は2021.9公開で、当記事は2021.12公開です。
つまり3ヶ月で前述の変化があったと思われるため、今後もアップデートで変化する可能性は非常に高く、当記事の方法も現バージョンのみに有効と考えた方が良いと思います。
なお公式以外の記事を参考にしてエラーが出ても、当記事のようにエラーを手掛かりに公式のドキュメントを読めば概ね解決できるはずです。
画面サイズによって動作の停止と再開を行う
以下のようにupdateプロパティを利用し、optionで設定可能なdisabledオブジェクトの真偽値を切り替えることで実現できました。
document.addEventListener('DOMContentLoaded', function () {
const keenSlider = new KeenSlider('.keen-slider');
window.onresize = function () {
if(window.matchMedia('(min-width: 1000px)').matches){
keenSlider.update({disabled:false});
} else {
keenSlider.update({disabled:true});
}
}
})
上記は1000pxを基準に、ブラウザリサイズ時に基準以下なら停止させ、基準以上なら再開するという動作を意図しています。
なお、サンプルは全体の一部を抜き出しいろいろ省略もしている状態のため、実際に使用しているコードそのものではありません。
updateプロパティ実行時の留意点
updateプロパティは指定した値のみを更新するのではなく、optionsの全項目を更新してしまうようです。
例えば下記のようにloop:trueを設定していた場合。
const keenSlider = new KeenSlider(".keen-slider", {
loop: true,
//省略
};
上記に対して前述のサンプルコードを実行しdisabled:falseを設定すると、元々設定していたloop:trueが消えてループしなくなります。
そのため初期化時にoptionsに指定していたキーと値も再度設定する必要があります。
keenSlider.update({disabled:false,loop:true});
disabledによる再開時のイベント
`disabled`: boolean
If this option is set to true, the slider is disabled. No styles or events will be applied. The default is false.
上記に書かれているとおり、disabledを使った場合イベントが削除されますが、disabledをfalseにして動作を再開させてもイベントは復活せず削除されたままとなります。
そのため、仮に初期化時にslideChangedなどのイベントフックで動作する仕組みを作っていた場合には動作しなくなります。
対応策としては以下のように、onを使ってイベントと動作内容を再登録する方法が検討できると思います。
keenSlider.update( { disabled: false } );
keenSlider.on( 'slideChanged', ( instance ) => {
hoge( instance );
} );
breakpointsを使うサンプル(動作しない?)
上記最下部の投稿を見ると、breakpointsでもdisableが設定できるとありましたので、以下のように書けば動作を停止させられるはずなのですが、停止を確認できず。
記載方法が違うのかもしれません。
const keenSlider = new KeenSlider(".keen-slider", {
breakpoints: {
'(max-width: 1000px)': {
disable: true,
},
},
}
よくない別案サンプル
よりバッドノウハウな方法ですが、以下のようにdestroyとnewの再設定を行う方法でも一応エラーなく動きはしました。
document.addEventListener('DOMContentLoaded', function () {
let keenSlider = new KeenSlider('.keen-slider');
window.onresize = function () {
if(window.matchMedia('(min-width: 1000px)').matches){
keenSlider = new KeenSlider('.keen-slider');
} else {
keenSlider.destroy();
}
}
})
結び
updateを使う方法も適切であるという自信はあまりないのですが、少なくともdestroyとnewよりは良いだろうと考えています。
他に正規の方法があるならそちらを使うべきなので、当記事を参照される場合はその点留意ください。
5人がこの記事を評価
役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。
連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。