分享和讨论Javascript相关的话题
回复
头像
ejsoon
一枝独秀一枝独秀
帖子: 6681
注册时间: 2022年 11月 18日 17:36
联系:

Pointer Events

帖子 ejsoon »

在js中,現代手機觸控事件除了touch,外,是否還有一種叫point的事件?二者是取代關係嗎?

gemini

代码: 全选

在 JavaScript 中,你提到的事件稱為 **Pointer Events(指標事件)**,事件名稱以 `pointer` 開頭(如 `pointerdown`、`pointermove`、`pointerup` 等),而不是 `point`。

它與 Touch Events(觸控事件)**並非完全的直接取代關係,而是更現代的抽象與替代方案**。

---

### Pointer Events 與 Touch Events 的差異

* **Touch Events (`touchstart`, `touchmove`, `touchend`)**
專門為「觸控螢幕」設計,無法統一處理滑鼠或電磁筆。
* **Pointer Events (`pointerdown`, `pointermove`, `pointerup`)**
將**滑鼠 (Mouse)、觸控 (Touch) 與觸控筆 (Pen/Stylus)** 統一抽象為「指標 (Pointer)」。撰寫一套程式碼即可同時支援多種輸入設備。

---

### 二者關係:指標事件是「現代標準」,但非強行廢除

| 比較項目 | Touch Events | Pointer Events |
| --- | --- | --- |
| **輸入支援** | 僅限觸控裝置 | 滑鼠、觸控、觸控筆 |
| **瀏覽器支援** | 廣泛支援(傳統標準) | 現代瀏覽器皆已全面支援 |
| **硬體資訊** | 觸控點位置、目標 | 含壓力 (`pressure`)、接觸面積 (`width`/`height`)、傾斜角 (`tiltX`/`tiltY`) 等 |
| **開發體驗** | 需分別處理 `mousedown` 與 `touchstart` | 寫一套 `pointerdown` 即可涵蓋兩者 |

---

### 開發建議

1. **優先使用 Pointer Events**:在開發現代 Web 應用(特別是需要同時支援手機與電腦,或包含繪圖、拖曳功能的介面)時,推薦使用 Pointer Events。
2. **相容性考量**:現今所有現代手機瀏覽器(iOS Safari、Android Chrome 等)均已完全支援 Pointer Events。Touch Events 依然保留在標準中以維持向下相容,但新專案建議轉用 Pointer Events。
蘋果手機觸控事件跟安卓還有哪些不一樣的地方,需要特別兼顧特別留意?

代码: 全选

在前端開發中,雖然 iOS (Safari/WebKit) 與 Android (Chrome/Blink) 都遵循現代 Web 標準,但在實際的手機觸控行為與事件處理上,iOS 有不少特殊的「獨有機制」或「硬性限制」。

以下是開發手機版網頁或 H5 時,**蘋果手機(iOS)與安卓(Android)在觸控事件上最需要特別留意與兼顧的差異點**:

---

### 1. 頁面彈性橡皮筋效果(Bounce / Elastic Scroll)

* **iOS 特點**:當頁面滾動到最頂部或最底部時,iOS Safari 預設會有「拉動彈回(Bounce Effect)」的橡皮筋動畫。如果頁面上存在手勢互動(如拖拉元件、自訂 Canvas 繪圖),這會導致整個網頁被一起拉動。
* **因應做法**:
* 在需要固定、禁用的容器上設定 CSS CSS 屬性:`overscroll-behavior: none;`
* 或者在手勢容器上攔截事件並呼叫 `e.preventDefault()`(但需注意 iOS 的被動事件限制,詳見下方)。



---

### 2. 被動事件監聽器(Passive Event Listeners)

* **iOS 特點**:iOS Safari 對於 `touchmove` 與 `wheel` 事件,預設會將監聽器設為被動(`passive: true`)。這意味著如果你在 `touchmove` 中直接執行 `e.preventDefault()` 來阻擋頁面滾動,**iOS 會直接忽略該指令並在控制台報錯**。
* **因應做法**:如果你的觸控組件(例如拖拽滑塊、自動繪圖)需要阻止預設滾動,必須明確指定 `passive: false`:
```javascript
element.addEventListener('touchmove', handleMove, { passive: false });

```



---

### 3. iOS 專屬的手勢事件(Gesture Events)

* **iOS 特點**:iOS WebKit 額外提供了一套獨有的多點觸控雙指縮放/旋轉事件(`gesturestart`、`gesturechange`、`gestureend`)。
* **影響**:在 iOS 上,雙指縮放會觸發 `gesture*` 事件;而在 Android 上則只會觸發含有兩個觸控點(`touches.length === 2`)的 `touchmove` 或 `pointermove`。
* **因應做法**:若要防止使用者在 iOS 網頁上雙指放大頁面,需要額外為 `gesturestart` 阻止預設行為:
```javascript
document.addEventListener('gesturestart', function(e) {
  e.preventDefault();
});

```



---

### 4. 點擊延遲與 300ms 透明遮罩雙擊問題

* **iOS 特點**:iOS Safari 為了判斷使用者是「單擊」還是「雙擊放大頁面」,在某些情況下會保留歷史遺留的 300ms 點擊延遲。此外,如果快速連點,iOS 有時會將其視為選取文字或強制放大頁面。
* **因應做法**:
* 確保 HTML `<meta name="viewport">` 包含 `width=device-width, initial-scale=1.0, user-scalable=no`(或使用 `touch-action` 屬性)。
* 為可點擊元素加上 CSS:`touch-action: manipulation;` 以消除 300ms 點擊延遲。



---

### 5. 虛擬鍵盤觸發時的 Viewport 高度變化

* **iOS vs Android**:
* **Android**:跳出虛擬鍵盤時,通常會直接縮小瀏覽器視窗的內部高度(`window.innerHeight`),觸發 `resize` 事件。
* **iOS**:跳出虛擬鍵盤時,**不會改變 `window.innerHeight**`,而是把整個網頁視圖「向上推動」,這極易造成定型在底部的元素(如 `position: fixed` 的輸入框或按鈕)位置錯位或被遮擋。


* **因應做法**:
* 避免在輸入框聚焦時依賴 `position: fixed` 作為底部導覽。
* 善用現代 CSS 的 `dvh`(Dynamic Viewport Height)與 `svh` 單位,並監聽 `visualViewport` API(`window.visualViewport.addEventListener('resize', ...)`)來動態計算可視區域。



---

### 6. 長按選取文字與系統選單

* **iOS 特點**:在 iOS 上長按任何元素,系統都會自動觸發文字選取(Text Selection)或跳出 Safari 的放大鏡與快顯功能表,這會中斷 `touchmove` / `pointermove` 事件流。
* **因應做法**:在需要手勢操作的區域加上 CSS 屬性,禁掉長按選取與高亮:
```css
.touch-area {
  -webkit-touch-callout: none; /* 禁用長按選單 (iOS 獨有) */
  -webkit-user-select: none;   /* 禁用文字選取 */
  user-select: none;
  -webkit-tap-highlight-color: transparent; /* 移除點擊時的灰透明高亮框 */
}

```



---

### 摘要對照清單

| 留意情境 | iOS (Safari) | Android (Chrome) | 最佳解法 |
| --- | --- | --- | --- |
| **頂底端滑動** | 會出現橡皮筋彈跳動畫 | 顯示頂部/底部發光邊框 | 設定 CSS `overscroll-behavior: none;` |
| **阻止預設滾動** | `touchmove` 預設為被動 | 視情況而定 | 註冊事件時加 `{ passive: false }` |
| **雙指縮放** | 支援獨有 `gesture*` 事件 | 僅標準 `touch` / `pointer` | 攔截 `gesturestart` 預設行為 |
| **鍵盤跳出** | 推擠 Viewport,不改變 `innerHeight` | 直接壓縮 Viewport 高度 | 搭配 `window.visualViewport` API 處理 |
| **長按選單** | 自動觸發 iOS 選單與放大鏡 | 觸發選取或選單 | 設定 `-webkit-touch-callout: none;` |
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀一枝独秀
帖子: 6681
注册时间: 2022年 11月 18日 17:36
联系:

Re: Pointer Events

帖子 ejsoon »

gemini現在寫代碼是不太行了,但是作為百科全書還是行的。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 41 访客