目錄
- TL;DR
- 1 基礎概念
- 1.1 鼠標、觸控板
- 1.2 點擊和手勢
- 2 觸控板獨有功能以及推薦用法
- 2.1 觸控板三指拖移
- 3 鼠標觸控板開發
- 3.1 wheel 小實驗
- 3.2 實驗結論
- 3.2.1 觸控板
- 3.2.2 鼠標
- 3.3 禁用觸控板雙指輕掃返回、智能縮放
- 3.4 註意點
- 參考連接
開發白板過程中,畫佈平移縮放操作是使用很頻繁且最基礎的交互功能。由於需求排期一直未實現該功能,導致白板開發使用過程中體驗差點意思,有一天我終於忍不瞭瞭,花瞭一個晚上研究瞭一下相關的內容。所以有瞭以下實踐。
一、在白板類繪圖產品中,平移縮放大部分都是依靠鼠標/觸控板操作完成的。這裡不可避免的要處理鼠標事件相關的代碼邏輯。針對不同設備需要兼容處理不同的邏輯,尤其在使用 mac 觸控板時左滑返回上一頁的操作很幹擾畫圖,會導致瀏覽器頁面後退,需要禁用該操作。
二、在我們日常工作生活中,幾乎每天都需要用鼠標或者觸控板。但是發現周圍大部分用 mac 的同事使用觸控板的方式都不太高效,還是使用普通鼠標那一套操作。不願更新自己的使用習慣。
針對以上原因,我要提問瞭:我們真的會運用鼠標和觸控板嗎?
這個問題包含兩層含義:
- 作為 mac 用戶:觸控板我們使用習慣是否高效。
- 作為前端開發者:觸控板相關的需求我們能否實現。
接下來我們帶著問題來尋找答案。
TL;DR
看好多國外的文章,太長瞭都會有 TL;DR(Too Long; Didn't Read.),我認為那不是 Too Long;Didn't Read,而是 Too Lazy; Didn't Read. 所以我也先把結論寫在這裡。
通過本文能學到的知識:
- 鼠標模式
- 鼠標滾輪縮放畫佈
- 右鍵長按拖拽平移畫佈
- 觸控板模式
- 雙指移動平移畫佈
- 雙指捏合縮放畫佈
- 禁用雙指輕掃在頁面間切換
- 禁用智能縮放
- 觸控板的高級用法
下面開始正文:
對 mac 操作很溜的選手可以忽略“觸控板使用”這節。但是我發現身邊大部分使用 mac 的同事都不怎麼會熟練使用觸控板的高級功能,還僅僅停留在能用的階段。我個人推薦你閱讀下升級自己的使用習慣。
—>>> 忽略開始 <<<—
1 基礎概念
1.1 鼠標、觸控板
如下圖所示分別是:Magic Trackpad 妙控板(文中統稱觸控板)、Magic Mouse 妙控鼠標、 普通鼠標。
Magic Trackpad 妙控板 / Magic Mouse 妙控鼠標 / 普通鼠標
本節所說的區別特指Apple 觸控設備和普通鼠標的交互區別。因為妙控板和妙控鼠標交互形式是一致的,都是單指、雙指點擊或者滑動以及多指滑動,而普通鼠標則是按鍵點擊與滾輪滾動與 Apple 觸控設備有著明顯的區別。
1.2 點擊和手勢
相信現在工作的大傢對鼠標的的操作習慣,都來源於 Windows 時代的人機交互。
而 Apple 設備改進瞭這一交互習慣。主要還是得益於硬件設備支持瞭多點觸控。有瞭多點觸控就可以增加更多的手勢交互。當年在鼠標時代就用過很多瀏覽器插件,支持鼠標手勢,通過鼠標畫一個預先設置好的圖形,就可以執行某些具體的操作,但是用鼠標畫圖還是有些難以操作。
我們直接來看 Apple 的手勢操作。
觸控板常用到的手勢操作有:
滾動縮放類:
- 放大縮小
- 智能縮放
這裡提出一個問題:明明是縮放,為什麼他們的設置項要叫滾動縮放?
更多手勢類:
- 常規點擊操作
- 在頁面之間輕掃
- 在全屏幕 App 之間輕掃
- 調度中心
- App Exposé
- 啟動臺
- 顯示桌面
2 觸控板獨有功能以及推薦用法
這點是我要重點推薦的,觀察到大傢平時操作觸控板拖拽窗口,或者拖拽文件基本都是以下步驟:
- 觸控板移動光標到指定位置;
- 單指使勁按下觸控板;
- 開始拖動文件,此時還的一直使勁按著觸控板;
- 拖到指定位置松手。
到第 2、3 步的時候體驗太糟糕瞭。手指既要向下用力,又要向左右用力滑動,一不小心松勁瞭,拖著的文件又跑回原來的地方瞭,或者壓根拖到瞭不該去的地方。真是難受。
使用瞭下面推薦的方法之後,你就可以隨意拖動文件,而且毫不費力,
2.1 觸控板三指拖移
設置方法如下:
- 設置 > 輔助功能 > 指針控制 > 鼠標與觸控板 > 觸控板選項
(觸控板三指拖移設置)
- 如果懶得找那麼深的設置,也可以直接搜索:“拖移”。可以看到 Apple 給他的定位描述 “讓鼠標和觸控板更易於使用”
提醒:由於三指被占用,原來觸控板裡的“更多手勢”裡凡是用到三指的都要改成四指,避免沖突。接下來幾天你的操作可能會特別難受,但是習慣的升級總是要經歷一個過程的。
以上就是觸控板的最便於使用的方法。
—>>> 忽略結束 <<<—
接下來就是代碼部分瞭。
————————–我是分割線————————–
3 鼠標觸控板開發
文章開頭提出的第二個問題:我們要實現觸控板/鼠標的平移縮放功能該如何實現呢?相信大部分前端開發者第一反應想到監聽鼠標滾輪事件。沒錯,就是運用鼠標滾輪事件。
此時我又要提問瞭:
- 觸控板的雙指捏合縮放頁面怎麼實現呢?
- 觸控板的雙指任意方向滑動平移頁面該怎麼實現呢?
- 觸控板又該如何禁用雙指輕掃在頁面間切換?
這些如果你還不太清楚,那就的接著往下看瞭。
下面我們繼續帶著問題來找答案。以下是我找答案的過程:
- 本著面向 Google 編程的思想,在最開始我先 Google 瞭一通 “觸控板 禁用 雙指 後退 返回 trackpad disable“ 等等關鍵詞,搜索結果都是移動端頁面觸控手勢,觸控板的文章少得可憐,基本都是介紹觸控板的使用,代碼相關的一無所獲。
- 後來我在想會不會觸控板有我不知道的雙指事件,我又去
developer.apple.com
一通搜索也是隻有 Mouse and Trackpad 的功能介紹,在深入就到 Appkit 瞭顯然這條路也不對。 - 一籌莫展之下
stack overflow
永遠不會讓你失望。在這裡找到瞭一個問題:Detect touchpad vs mouse in Javascript,心想反正也要判斷觸控板和鼠標,那就抄一下這個答案吧。抄答案時候發現基本用到的都是mousewheel
事件。 - 所以 mdn 接著找
mousewheel
資料,發現mousewheel: This feature is no longer recommended.
推薦用wheel
,似乎我們已經找到瞭解決問題的方法。
用到的對象主要是 WheelEvent
。除他之外還有幾個關聯的事件對象要熟悉:MouseEvent
,UIEvent
,Event
。這些事件對象都是依次繼承下來的。
到這裡答案基本出來瞭解決上面的問題主要運用的就是:wheel
鼠標滾輪事件。到這裡也回答瞭上面的問題:為何雙指縮放等設置項會歸類到滾動縮放下,因為他們的實現都是使用瞭 wheel
事件。
那我們就細細研究一下 wheel
事件,先看他的幾個對我們來說有用的屬性:
WheelEvent.deltaX
隻讀:返回 double 值,該值表示滾輪的橫向滾動量。WheelEvent.deltaY
隻讀:返回 double 值,該值表示滾輪的縱向滾動量。
從事件屬性可以看出該事件主要用來監聽鼠標滾輪的滾動,並可以拿到滾動量。為瞭搞的更清楚這幾個屬性所代表的意義,接下來我做瞭個小實驗,來探究 delta
的變化規律。
3.1 wheel 小實驗
實驗說明:頁面有兩個 div
,內部 div
比外部的大,通過監聽滾輪事件滾動尋找 deltaX、deltaY
的規律。同時將 scrollTop、scrollLeft
打印出來進行參照看 div
的滾動方向。
<!-- 代碼直接新建個 html 全部 copy 進去即可看效果。 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>你不知道的 Trackpad</title>
<style>
body {
background-color: #25252580;
overflow: hidden;
}
#root {
position: fixed;
top: calc(50% - 150px);
left: calc(50% - 150px);
width: 300px;
height: 300px;
/* 任意方向滾動 */
overflow: scroll;
/* 縱向滾動效果 */
/*overflow-x: hidden;*/
/*overflow-y: scroll;*/
/* 橫向滾動效果 */
/*overflow-x: scroll;*/
/*overflow-y: hidden;*/
}
h1 {
position: absolute;
top: 0;
left: 0;
}
#container {
width: 1000px;
height: 1000px;
/* 背景色漸變 */
background: linear-gradient(
217deg,
rgba(255, 0, 0, 0.8),
rgba(255, 0, 0, 0) 70.71%
), linear-gradient(
127deg,
rgba(0, 255, 0, 0.8),
rgba(0, 255, 0, 0) 70.71%
), linear-gradient(336deg, rgba(0, 0, 255, 0.8), rgba(0, 0, 255, 0) 70.71%);
}
</style>
</head>
<body>
灰色的都是body
<div id="root">
<h1>你不知道的 Trackpad</h1>
<div id="container"></div>
</div>
<script>
document.addEventListener(
"wheel",
function (e) {
e.stopPropagation();
e.preventDefault();
return false;
},
{ passive: false }
);
document.getElementById("root").addEventListener(
"wheel",
function (e) {
e.stopPropagation();
logInfo(e, "root");
isTrackpadOrMouse(e);
},
{ passive: false }
);
let hnum = 1;
let vnum = 1;
// 臨時存放日志,方便以表格展示方便對比結果
let temp = [];
// 是否一直打印日志
let always = false;
/**
* 重點看這幾個屬性:deltaX、deltaY、ctrlKey
*/
function logInfo(e, name) {
let info = {
name: name,
button: e.button,
ctrlKey: e.ctrlKey,
// altKey: e.altKey,
// metaKey: e.metaKey,
shiftKey: e.shiftKey,
// which: e.which,
// clientX: e.clientX,
// clientY: e.clientY,
deltaMode: e.deltaMode,
deltaX: e.deltaX,
deltaY: e.deltaY,
// deltaZ: e.deltaZ,
// layerX: e.layerX,
// layerY: e.layerY,
// offsetX: e.offsetX,
// offsetY: e.offsetY,
// wheelDelta: e.wheelDelta,
wheelDeltaX: e.wheelDeltaX,
wheelDeltaY: e.wheelDeltaY,
scrollTop: document.getElementById(name).scrollTop,
scrollLeft: document.getElementById(name).scrollLeft,
// x: e.x,
// y: e.y,
};
if (always || hnum % 10 === 0 || vnum % 10 === 0) {
temp.push(info);
}
// 垂直滾動時
if (e.deltaY > 0) {
vnum += 1;
} else if (e.deltaY < 0) {
vnum -= 1;
}
// 水平滾動時
if (e.deltaX > 0) {
hnum += 1;
} else if (e.deltaX < 0) {
hnum -= 1;
}
if (always || hnum === 0 || vnum === 0) {
console.table(always ? [info] : temp);
}
}
/**
* 判斷是鼠標或者觸控板
* @param e
* @return {boolean}
*/
function isTrackpadOrMouse(e) {
let isTrackpad = false;
if (e.wheelDeltaY) {
if (e.wheelDeltaY === e.deltaY * -3) {
isTrackpad = true;
}
} else if (e.deltaMode === 0) {
isTrackpad = true;
}
console.log(isTrackpad ? "Trackpad detected" : "Mousewheel detected");
return isTrackpad;
}
</script>
</body>
</html>
-
扫码下载安卓APP
-
微信扫一扫关注我们微信扫一扫打开小程序手Q扫一扫打开小程序
-
返回顶部