最近メインで使ってるスライダーやカルーセルを作れる「keen-slider.js」でバグ(?)仕様でつまったのでメモしておきます。
タイトルの通りaddEventListenerでmouseUpとtouchStartのイベントの中でmoveToIdx関数でカルーセルを移動させようとした時に発生しました。
目次
発生するコードに行き着いた経緯
slider.moveToIdx(1)のように指定すると1番目のスライドに移動する関数をスライドをクリックしたときに移動させたかったので以下のようなコードを書きました。
...
const plugin = slider => {
slider.slide.forEach( (slide,i) => {
slide.addEventListener('click', ()=>{
slider.moveToIdx(i);
});
});
}
このコードはうまくいきました。
ただ、このコードはスライドをスワイプしたときも発動してしまって、想定外の移動をしてしまいます。
そこでクリックを押したときと離したときにスライダー全体が移動したかどうかを判別しようと思いました。
実際にmoveToIdxが効かないコード
以下のコードを作成しました。
...
const plugin = slider => {
let distanceOfProgress = 0;
slider.slide.forEach( (slide,i) => {
slide.addEventListener('mousedown', ()=>{
distanceOfProgress = slider.track.details.progress;
});
slide.addEventListener('mouseup', ()=>{
if( distanceOfProgress === slider.track.details.progress )
{
slider.moveToIdx(i);
}
});
});
}
mousedownでdistanceOfProgress変数に相対距離の初期値を保存して、mouseupでdistanceOfProgressと今の相対距離が一致した時、すなわちスライダーが変化していない時にクリックと判定してそのクリックしたスライドを中心に移動させるというプログラムですね。
このコードでスライドをスワイプしたときは発動せずに、クリックした時だけ、そのスライドに移動するプラグインが書けたはずでした。
しかし移動がなぜか発動しませんでした。
解決法
検査として以下のコードを確認してみました。
...
const plugin = slider => {
slider.slide.forEach( (slide,i) => {
slide.addEventListener('mouseup', ()=>{
slider.moveToIdx(i);
});
});
}
このコードは最初のクリックした時に移動させたプログラムのイベント部分をclickからmouseupに変えただけのコードです。
あーーはん。
マウスアップはクリックと変わらないと考えられますが、このコードではやはりmoveToIdxは発動しませんでした。
まあまあまあ
そもそも最初のコードでクリック時にmoveToIdxが発動できることは確認していたので、mousedownイベントで距離の初期値を保存して、mouseupではなくてclickで距離の移動を判断する形にしました。
書くまでもないですが実際のコードは以下です。
...
const plugin = slider => {
let distanceOfProgress = 0;
slider.slide.forEach( (slide,i) => {
slide.addEventListener('mousedown', ()=>{
distanceOfProgress = slider.track.details.progress;
});
slide.addEventListener('click', ()=>{
if( distanceOfProgress === slider.track.details.progress )
{
slider.moveToIdx(i);
}
});
});
}
これでスワイプしたときはmoveToIdxが発動しないクリックしたスライドに移動するプラグインが完成しました。
結論
もしかしたらmouseupとtouchendのイベントはスクロールをした時うまくスワイプとスクロールを判断するために既に予約されているため、その機能と競合しているのかもしれないですね。
おわり