網頁的外觀和操作本質上還是和原生的有差異但可以透過配置來讓體驗更接近。
- 全螢幕模式
- 視覺設計
- 事件操作
全螢幕模式
全螢幕模式有兩種方式,Progressive Web App 尚未安裝前可以透過程式觸發,安裝後可以透過 display 配置安裝後的執行顯示模式。
- 程式觸發全螢幕
document.body.requestFullscreen();
- Progressive Web App 可以透過 manifest 的 display 設定
- fullscreen
- standalone
- minimal-ui
視覺設計
Progressive Web App 主視覺、字形、操作上若配合系統會讓用戶能有較好且更一致的操作體驗。
- 使用系統字形
- 配合系統主題
- 網址列顏色
- 樣式處理
使用系統字形
字形的選用上非常容易影響到使用者的觀感,CSS 上可以透過 system-ui
來使用系統原生的字型。
1 | font-family: system-ui; |
配合系統主題
當系統開啟暗黑模式後,PWA 也可以透過程式上的撰寫配合更改顯示設定,另外對於 AMOLED 的螢幕來說,暗黑模式也可以更省電。
程式上主要透過 Media Queries Level 5 支援的 prefers-color-scheme 可以判斷出使用者目前使用的系統主題。
- light: 明亮模式 (深色字體、淺色背景).
- dark: 暗黑模式 (淺色字體、深色背景).
1 | if (window.matchMedia("(prefers-color-scheme)").media !== "not all") { |
1 | @media (prefers-color-scheme: dark) { |
Google 有推出了一個 dark-mode-toggle 的模組,主要是靠 Window.matchMedia()
在實作相關邏輯
1 | const PREFERS_COLOR_SCHEME = "prefers-color-scheme"; |
有興趣的大大也可以參考看看:
https://github.com/GoogleChromeLabs/dark-mode-toggle
動畫來源: https://github.com/GoogleChromeLabs/dark-mode-toggle >
網址列顏色
PWA 中 manifest 的 theme_color 設定,可以客製化 Android Chrome 的網址列的顏色,注意要和 meta 中的顏色相同。
<meta name="theme-color" content="#3c553c" />
樣式處理
針對操作上的 UI 優化,可以針對常見三個狀態做樣式設定
:hover
:focus
:active
按鈕上也建議把預設的樣式拿掉。
1 | .btn:focus { |
事件操作
- 文字選取
- contextmenu
- Touch 效果
- Touch 事件
文字選取
對於有觸控功能原生 APP 跟網頁最大的差別在很多文字是不能選取的,這時候我們也可以透過 CSS 針對這個部分進行設定。
1 | /* 不給選 */ |
contextmenu
避免長按跳出瀏覽器的 menu
- iOS
1 | webkit-touch-callout: none; |
- Android
1 | window.addEventListener("contextmenu", (e) => { |
Touch 效果
如果想要自訂義,就要把瀏覽器預設的樣式行為停用,要注意一但設為 none 變成要將很多細節去用 JS 執行
1 | touch-action: none; |
Touch 事件
越來越多裝置支援 touch 的行為,工程師在實作上其實就是針對觸控、手勢去實作相關事件。
- touches: 所有有按到手指的陣列
- force 壓力
- 座標
- 半徑座標
- targetTouches: 有按到 touch 事件的才會傳回來
- changedTouches: 產生變化的觸碰點資訊,當離開時
touches
、targetTouches
為空,所以只能透過changedTouches
來理解最後發生的事情
針對不同的事件去做相關的事件綁定,注意一下 touchMove 不等於 mouseMove,User Agent 會分派順序如下:
- touchstart
- touchmove: 觸發的次數很多,要注意是否影響原來的效能
- touchend
- mousemove: cursor 移動
- mousedown
- mouseup
- click
要注意的細節如下
- 減少在 touchstart 就做事件處理,因為這個階段也抓不到其他手指的事件
- 如果 touchStart 就
preventDefault()
會讓滑鼠事件 click 消失,但不preventDefault()
又會同時觸發 touch 跟 click,這時候就需要看情境特別處理,像是preventDefault()
後在 touch 事件的 callback 中決定是否要用程式去觸發 click - 觸控至少要設計間距要超過
5px
比較不會誤觸,可以用增加 padding 的方式 - 300ms 延遲是怎麼來的,原因是因為 UA 要去判斷是否現在是在做更進階的動作,像是長按、點兩下等,如果直接監聽 touch 事件去做 click 事件就不會有這個延遲時間。或是透過 meta 設定不給縮放 (
user-scalable=no
) 就不會發生。
<meta name="viewport" content="width=device-width,user-scalable=no">
1 | // 判斷是否支援 |
喜歡這篇文章,請幫忙拍拍手喔 🤣