iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 28
0
Modern Web

寫JS30天系列 第 28

JS30 - 28 - Click and Drag

目標

拖曳滑鼠,使items移動
我們來看看html吧

<div class="items">
    <div class="item item1">01</div>
    <div class="item item2">02</div>
    <div class="item item3">03</div>
    ...
</div>

打開html會發現
items就是一個放了25個item的容器
由於item過多,所以使用了overflow: scroll讓超出範圍的item隱藏起來
並可以使用捲軸來把隱藏的內容捲出來

想一下我們需要「拖曳」這件事,
拖曳就是「在滑鼠按下」的情況下,「移動滑鼠」
所以我們命名一個變數isDown來紀錄滑鼠是否被按著

同時我們要監聽mousedownmousemovemouseupmouseleave四個事件
mousedown時,設定isDowntrue,並添加.active
(.active有縮放效果,是用來確認是否有被點擊)
mouseupmouseleave時,設定isDownfalse,並移除.active

而在mousemove事件,我們要先判別isDown
如果isDown是false才會繼續執行
不然就直接return

const items = document.querySelector('.items');
let isDown = false;

function pressRightButton(e) {
  isDown = true;
  this.classList.add('active');
}
function releaseRightButton() {
  isDown = false;
  this.classList.remove('active');
}
function moveMouse(e) {
  if(!isDown) return;
}
function moveLeave() {
  isDown = false;
  this.classList.remove('active');
}
items.addEventListener('mousedown', pressRightButton);
items.addEventListener('mouseup', releaseRightButton);
items.addEventListener('mousemove', moveMouse);
items.addEventListener('mouseleave', moveLeave);

這樣基本上我們已經完成所有的前置作業了
接下來就是處理「.items要移動多少」
這時候我們要「確立座標系」
由於上面使用了overflow: scroll
所以我們就是要讓items.scrollLeft跟著我們的mousemove隨時更新
首先我們要取得我們mousedown時的x座標

  1. 先用e.pageX取得點擊位置到document左側邊緣的距離
  2. 再扣掉.items到父層(body)左側邊緣的距離
  3. 將這個初始X座標儲存在變數originX

接著我們也存一下items.scrollLeft的初始位置在變數scrollLeft

let originX; //用來紀錄`mousedown`時的初始X座標,用來計算滑鼠「移動多少」
let scrollLeft; //用來紀錄`mousedown`時的捲軸X座標

function pressRightButton(e) {
    isDown = true;
    this.classList.add('active');
    originX = e.pageX - items.scrollLeft;
    scrollLeft = items.scrollLeft;
}

mousemove事件觸發條件

  1. isDowntrue
  2. 滑鼠移動

也就是拖曳時就會一直觸發
首先我們用一樣的方法取得新座標newX(會隨拖曳一直改變)
接著計算移動變量move = newX - originX
然後設定.items.scrollLeft = scrollLeft - move即可

依照物理的末位置 = 初位置 + 位移
但是在網頁上:往右拉(正位移量)這件事,scrollLeft是在減少的
所以要改成減號

function moveMouse(e) {
    if(!isDown) return;
    let newX = e.pageX - items.scrollLeft;
    let move = (newX - originX);
    items.scrollLeft = scrollLeft - move;
}

Demo
完整程式碼


上一篇
JS30 - 27 - Stripe Follow Along Nav
下一篇
JS30 - 29 - Video Speed Controller
系列文
寫JS30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言