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');
    }

<<:  NIST SDLC和RMF(续)

>>:  【C#、Regex】像 #if DEBUG and #endif 删除指定内容

成为 Scrum Master

前言 今天来部份自我介绍,聊聊身为 Scrum Master 的一些经历。一如系列文章的初衷,希望能...

Leetcode 挑战 Day 11 [242. Valid Anagram]

242. Valid Anagram 今天我们一起挑战leetcode第242题Valid Anag...

[Angular] Day10. Property binding and Event binding

本篇中将介绍 Angular 的 property binding 与 event binding,...

难搞的字串符

字符串编码转换 在 python3.x 中,默认采用编码格式为UTF-8 在 python 中,有两...

Day29_ISO27037数位证据处理程序国际标准-2021/10/12

Day21_控制项(A16资讯安全事故管理)有稍微提到的数位监识~继续作功课呀~ ▉ISO 2703...