觸控遊戲的細節:從 Pointer Events 到消除觸控延遲
在平板上做互動遊戲,觸控體驗有幾個坑幾乎一定會踩:300ms 延遲、長按彈出選單、手指稍微滑動就變成頁面捲動。這篇記錄玩樂學遊戲裡的實際做法。
在平板和手機上做互動教材,不能只想著「遊戲邏輯跑起來就好」。觸控體驗有幾個地方如果沒處理,孩子實際操作時會明顯感覺「這個遊戲有點卡」。
玩樂學的每個遊戲都是純 HTML + Vanilla JS,沒有框架幫你處理這些細節,所以要自己來。
用 Pointer Events,不用 Touch Events
遊戲裡的互動(拖曳、點擊、放置)一開始可能想用 touchstart / touchend,但我們選擇了 Pointer Events API:
el.addEventListener('pointerdown', e => { /* 開始拖曳 */ });
window.addEventListener('pointermove', onPointerMove);
window.addEventListener('pointerup', onPointerUp);
Pointer Events 同時支援手指觸控、滑鼠、觸控筆,寫一套邏輯就能在所有裝置上運作。桌機測試時可以用滑鼠操作,上了平板自動切成觸控,不需要分開處理。
數學塔防戰的拖曳邏輯就是這樣實作的:按住卡片開始追蹤(pointerdown),移動時顯示拖曳預覽(pointermove),放開時執行放置或交換(pointerup)。
touch-action: none — 讓遊戲區不被頁面捲動搶走事件
遊戲最常遇到的問題:玩家在遊戲區域滑動,瀏覽器把這個動作解讀成「捲動頁面」,遊戲區沒收到事件。
解法是在遊戲容器加上:
body {
touch-action: none;
}
這告訉瀏覽器:這個區域不做縮放和捲動,所有觸控事件直接交給 JavaScript 處理。湊十派對和數學塔防戰的遊戲本體都有這行。
消除長按干擾
孩子在觸控螢幕長按時,瀏覽器預設會彈出選單(複製、貼上、選取文字),在遊戲進行中非常干擾。兩行搞定:
body {
user-select: none;
-webkit-tap-highlight-color: transparent;
}
user-select: none:禁止選取文字,長按不會觸發文字選取模式-webkit-tap-highlight-color: transparent:去掉 iOS/Android 點擊時的藍色/灰色閃光,讓遊戲視覺更乾淨
數學塔防戰的 body 樣式就包含這兩個宣告。
即時視覺回饋
觸控螢幕上的元素,按下去要有立刻的視覺反應——孩子才知道「我點到了」。不需要等 JavaScript 回應,純 CSS 就能做到:
.card {
transition: all 0.1s;
}
搭配 :active 偽類或在 pointerdown 時加 class,手指按下的瞬間就看到變化。0.1s 的過渡夠快,讓人感覺即時,又有一點滑順感。
全螢幕縮放:固定邏輯尺寸
遊戲在不同大小的平板上要看起來一致,解法是固定邏輯尺寸,用 CSS transform 縮放到填滿螢幕:
function resizeGame() {
const scale = Math.min(window.innerWidth / 400, window.innerHeight / 720);
document.getElementById('app').style.transform = `scale(${scale})`;
}
window.addEventListener('resize', resizeGame);
document.addEventListener('fullscreenchange', resizeGame);
resizeGame();
邏輯尺寸固定 400×720px,JavaScript 算出對應的縮放比例,不管裝置實際尺寸是多少,遊戲元素的相對位置都保持一致。數學塔防戰就是用這個做法。
快速清單
下次做行動互動教材,這幾件事優先處理:
- 互動邏輯用 Pointer Events(
pointerdown/move/up),不用 Touch Events - 遊戲容器加
touch-action: none,阻止瀏覽器搶觸控事件 -
body加user-select: none和-webkit-tap-highlight-color: transparent - 互動元素加
transition做即時視覺回饋 - 固定邏輯尺寸 + CSS transform 縮放,處理各種螢幕大小
- 在真實平板上測試,Chrome DevTools 的觸控模擬抓不到所有問題