成品連結:Click and Drag、操作前程式碼、完成後程式碼
今天要做的是拖拉的功能。從成品可以看到當按下滑鼠拖拉時元素的 X 軸會被拉著滾動,其實在實作後發現並不難,反而是覺得做處扇子狀的 CSS 很厲害啊...希望大家也可以花一些時間看一下 CSS 是怎麼寫的;作者用了許多我認為新奇且厲害的方法,像是呈現出立體視角的 perspective
。
首先要先分析需要什麼監聽事件以及要做什麼事
div.items
加入 class active
div.items
:移除 class active
div.items
的 X 軸從待辦事項可以看出我們需要要事件分別是
mousedown
mouseup
、mouseleave
mousedown
+mousemove
那就先設定監聽吧!
const items = document.querySelector('.items');
items.addEventListener('mousedown', focus);
items.addEventListener('mousemove', drag);
items.addEventListener('mouseup', unfocus);
items.addEventListener('mouseleave', unfocus);
isDown
flagflag 意思是旗幟,也就是用於標示是否已按下滑鼠,若 isDown === true
則執行 mousedown
的 callback focus
,反之若 isDown === false
則執行 callback unfocus
。預設是 false
,當按下滑鼠時才會變成 true
。
let isDown = false;
function focus() {
isDown = true;
items.classList.add('active'); // 加入 class `active`
}
function unfocus() {
isDown = false;
items.classList.remove('active'); // 移除 class `active`
}
從上面程式碼可以看到當按下滑鼠時一併加入 class active
到 items
;當滑鼠移出 items
或鬆開滑鼠時移除該 class
至於要拖曳就要先確保滑鼠已按下,這也是為何要設定 flag isDown
作為提示,而在 callback drag
中當 isDown !== true
時要立即退出 funciton 執行,反之才繼續執行
function drag(e) {
if (!isDown) return;
items.scrollLeft += -(e.movementX * 2);
}
這裡我觀察了一下 mousemove
中 event
的屬性與方法(也就是在 drag
中 console.log(e)
),赫然發現有 MouseEvent.movementX
這個屬性。根據 MDN 所定義,這個屬性提供了拖曳起點到當前位置(X 軸)的距離,這正是我需要的!
另外看了一下 items
的屬性及方法(console.dir(items)
),發現有個屬性 scrollLeft
正是用來設定(或顯示) X 滾軸當前位置。
綜合以上兩個資訊,我得知我將 MouseEvent.movementX
的值加到當前 X 滾軸位置就可以拖曳了!
function drag(e) {
if (!isDown) return;
// code here
}
至於為什麼要將 e.movementX * 2
設定正負相反是因為當向右拖曳時 e.movementX
會是負數,但我希望向右拖曳時可以向右滾動,所以將 e.movementX
的值正負相反過來
而 e.movementX * 2
則是因為我希望拖曳的距離可以拉長,所以乘以 2,如果你覺得不夠也可以乘以更大的數字。
總之今天的作品就完成了!