iT邦幫忙

0

JS30 Day 27 - Click and Drag學習筆記

https://ithelp.ithome.com.tw/upload/images/20210204/201261828bqvjoyfDm.png
這次的功能主要是做畫面的一個點擊拖曳,當點擊後往左拖曳畫面會往右跑,反之。

主要之架構。

  <div class="items">
    <!-- 放一個a來做測試,當我們拖曳時,放開不想觸發a -->
    <a
      href="http://www.google.com/"
      class="item item1"
    >01 </a>
    <div class="item item2">02</div>
    <div class="item item3">03</div>
    <div class="item item4">04</div>
    <div class="item item5">05</div>
    <div class="item item6">06</div>
    <div class="item item7">07</div>
    <div class="item item8">08</div>
    <div class="item item9">09</div>
    <div class="item item10">10</div>
    <div class="item item11">11</div>
    <div class="item item12">12</div>
    <div class="item item13">13</div>
    <div class="item item14">14</div>
    <div class="item item15">15</div>
    <div class="item item16">16</div>
    <div class="item item17">17</div>
    <div class="item item18">18</div>
    <div class="item item19">19</div>
    <div class="item item20">20</div>
    <div class="item item21">21</div>
    <div class="item item22">22</div>
    <div class="item item23">23</div>
    <div class="item item24">24</div>
    <div class="item item25">25</div>
  </div>

先理解拖曳的觀念
1.開始 => mousedown開始
2.ing => mousemove正在拖(mousedown依然沒放開)
3.結束 => mouseup(放開)、mouseleave(離開拖曳元素之範圍)

獲取元素目標並增聽所需之事件。

const list = document.querySelector('.items');
    // 判斷在a上的鼠標是否有拖曳
    let moved = false;
    list.addEventListener('mousedown', startDragHandler); // 手機事件改用  touchstart
    list.addEventListener('mousemove', DragingHandler); // 手機事件改用  touchmove
    list.addEventListener('mouseup', stopDragHandler); // 手機事件改用  touchend
    list.addEventListener('mouseleave', stopDragHandler);
    
    對所有a都綁定點擊事件。
    document.querySelectorAll('.items a').forEach(dom => {
    dom.addEventListener('click', function (e) {
        // 假如動了就防止觸發預設功能
        if (moved) {
          e.preventDefault();
        }
      })
    })

設置拖曳的起始點,並在mousedown事件函數處理,當按下去,會觸發樣式active來反饋說已經按下鼠標,而由於我們的目標會一直切換,故無法使用offsetX,改用pageX,當點下去時,就獲取起始點。

    // 起始點
    let startX = 0;
    // 開始拖曳
    const startDragHandler = function (e) {
      list.classList.add('active');
      // 在拖曳時,發現e.target會一直切換
      // 原本想使用offsetX(從該元素開始計算)來計算距離,但由於我們元素內的目標有好幾個,item1,item2...
      // 改使用pageX(從全頁面)開始計算距離
      // <div class="item item2">02</div>  ,  0 , 13 
      console.log(e.target, e.offsetX, e.pageX);
      // 獲取起始點
      startX = e.pageX;
      沒移動故false
      moved = false;
    }

拖曳中(需按下鼠標後),拖曳會有很多東西(如連結、文字、圖片),都會被觸發在移動上,所以要做preventDefault但當拖曳時,原本a的click就會被觸發,所以要額外去preventDefault a標籤
先判斷是否有active樣式,以判斷是否按下鼠標,並開始拖曳,獲取拖曳的距離(拖曳後位置-當前起始點),並且在算完距離後,要改變起始點,並且在最後要將畫面呈現拖曳效果,也就是使用scrollLeft滾動離左邊的距離,但由於移動方向跟拖曳方向是反的,故用減法

    const DragingHandler = function (e) {
      e.preventDefault();
      // 移動為true
      moved = true;
      // 先判斷是否mousedown
      if (list.classList.contains('active')) {
        // 移動的距離(當前鼠標位置-前起始點)
        let move = e.pageX - startX;
        // 每次拖曳改變起始點
        startX = e.pageX;
        // 元素移動
        list.scrollLeft -= move; 
        // list.scrollLeft -= move * 5;  // 如想拖曳速度增加可乘以倍數 
      }
    }

最後,結束拖曳。

    // 結束拖曳
    const stopDragHandler = function (e) {
      list.classList.remove('active');
    }

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言