Bootstrap 4 旋轉木馬用滑鼠左右滑動切換圖片

Bootstrap 4 Carousel (旋轉木馬)一直都是很常用到也很好用的套件,前幾天因為收到了需要左右滑動網頁區塊的需求,因此思考了一下,用了旋轉木馬為基礎的滑動區塊。



於是我上網搜尋了一下,發現了 這個提問 下面的回答,決定拿來改成我要的樣子。

首先我想關掉自動切換圖片的功能,於是在程式碼中加了 data-interval="false",
<div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel"  data-interval="false">
...
</div>

再來我想把旋轉木馬的既定印象進一步挪掉,於是把左右切換子區塊的按鈕拿掉,

<div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel"  data-interval="false">
...
<!--   <a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="sr-only">Previous</span>
  </a>
  <a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a> -->
</div>

接下來就是把上面的程式碼copy到我的js檔裡面。

$('.carousel').on('touchstart', function(event){
    const xClick = event.originalEvent.touches[0].pageX;
    $(this).one('touchmove', function(event){
        const xMove = event.originalEvent.touches[0].pageX;
        const sensitivityInPx = 5;

        if( Math.floor(xClick - xMove) > sensitivityInPx ){
            $(this).carousel('next');
        }
        else if( Math.floor(xClick - xMove) < -sensitivityInPx ){
            $(this).carousel('prev');
        }
    });
    $(this).on('touchend', function(){
        $(this).off('touchmove');
    });
});

然而這並沒有達到我想要的效果,如果你仔細看的話會發現上面只有支援觸控滑動,沒有支援滑鼠滑動,因此我必須再改改。

jquery的on事件是支援多個事件觸發的,只需要在多個事件中間加空格就可以,詳細可以去看這裡

touchmove 對應 mousedown
touchmove 對應 mousemove
touchend 對應 mouseover

$('.carousel').on('touchstart mousedown', function(event){
    const xClick = event.originalEvent.touches[0].pageX;
    $(this).one('touchmove mousemove', function(event){
        const xMove = event.originalEvent.touches[0].pageX;
        const sensitivityInPx = 5;

        if( Math.floor(xClick - xMove) > sensitivityInPx ){
            $(this).carousel('next');
        }
        else if( Math.floor(xClick - xMove) < -sensitivityInPx ){
            $(this).carousel('prev');
        }
    });
    $(this).on('touchend mouseover', function(){
        $(this).off('touchmove mousemove');
    });
});

但是在我用滑鼠滑動的時候出現找不到xClick的錯誤,原因是我們參考的程式碼宣告的常數xClick跟xMove是抓touch的xPosition,所以當我們偵測到滑鼠事件時就會出錯。

關於常數const的介紹請看這裡

在這樣的情況下我先確認在mousesdown事件下的event.originalEvent它的pageX在哪裡,

$('.carousel').on('touchstart mousedown', function(event){
    console.log(event.originalEvent);
    /*const xClick = event.originalEvent.touches[0].pageX;
    $(this).one('touchmove mousemove', function(event){
        const xMove = event.originalEvent.touches[0].pageX;
        const sensitivityInPx = 5;

        if( Math.floor(xClick - xMove) > sensitivityInPx ){
            $(this).carousel('next');
        }
        else if( Math.floor(xClick - xMove) < -sensitivityInPx ){
            $(this).carousel('prev');
        }
    });
    $(this).on('touchend mouseover', function(){
        $(this).off('touchmove mousemove');
    });*/
});

經由console之後,我們可以得知touch跟mouse差的就是多點觸控跟單點觸控,因此一個是touch[0]一個沒有touch。

接下來就可以進一步的改寫我們的程式碼:

$('.carousel').on('touchstart mousedown', function(event){
    var xClick;
    if (event.type == 'touchstart') {
      xClick = event.originalEvent.touches[0].pageX;
    } else {
      xClick = event.originalEvent.pageX;
    }
    $(this).one('touchmove mousemove', function(event){
        var xMove;
        if (event.type == 'touchmove') {
          xMove = event.originalEvent.touches[0].pageX;
        } else {
          xMove = event.originalEvent.pageX;
        }
        const sensitivityInPx = 5;

        if( Math.floor(xClick - xMove) > sensitivityInPx ){
            $(this).carousel('next');
        }
        else if( Math.floor(xClick - xMove) < -sensitivityInPx ){
            $(this).carousel('prev');
        }
    });
    $(this).on('touchend mouseover', function(){
        $(this).off('touchmove mousemove');
    });
});

這樣一來錯誤就沒了,但是滑鼠移動的幅度如果不夠,就偵測不到切換下一個item,所以後來我又調整了靈敏度的部分。

$('.carousel').on('touchstart mousedown', function(event){
	...
        const sensitivityInPx = .5;
	...
});

這樣一來功能就完成了!美中不足的就是滑鼠鼠標不會移到區域就換掉,最後再加個css吧!

<style>
 .grab {
    cursor: grab;
 }
</style>
<div id="carouselExampleIndicators" class="carousel slide grab" data-ride="carousel"  data-interval="false">
...
</div>
<script>
$('.carousel').on('touchstart mousedown', function(event){
	...

});
</script>

文章的最後附上我整理的codepen給大家參考~希望這次的紀錄可以幫助到來看文章的你們。

Written by 樂水

留言

這個網誌中的熱門文章

網頁自定義進度條動畫(Process Bar Animate)【一】

網頁自定義進度條動畫(Process Bar Animate)【二】