Photo by Pandhuya Niking on Unsplash
前言:iOS 之坑、再次襲來
既上篇的「【學習筆記】 關於 iOS Safari 的那些坑:禁止選取 & 縮放設定」之後,因為 Web APP 開發需同時支援 Android 和 iOS 裝置,在過程中仍不時被新的隕石砸中,只好再挖新的坑來填補。
這次要探討的主題比較瑣碎,大致如下:
- Wait!! Do you know where’s my console?
- Resize fires multiple times
- Web API: Fullscreen & Vibration
Wait!! Do you know where’s my console?
- Reference:Console.log not displaying on iPad Pro Safari 16.4 when using dev tools on my mac - Stack Overflow
- 預期結果:透過開啟 Safari 開發者模式,詳細操作可參考這篇:[30- 相關工具] 手機遠程測試 - iT 邦幫忙
- 實際操作:裝置升級至 iOS 16.4 版本後,需注意可能發生無法 Debug 的情況,尤其在需要測試行動裝置時,發現 console 畫面無法顯示任何資訊
儘管仍可查看元件樣式,但主控台呈現一片空白:
白天不懂夜的黑,Console 不懂我的悲QQ
How to resolve?
以下提供幾種解決方案:
- 最土法煉鋼的方法:透過
console.log
大法直接印到 webview 上,但若需要動態更新頁面,例如多國語系功能(i18n),則需要抓取 DOM 的 innerHTML 一個一個置換更新,但非常麻煩且耗費效能- 因為習慣使用 Angular 框架提供的 NGX-Translate,支援快速切換多國語系功能,詳細可參考這篇:i18n 多國語系- Ngx-Translate - iT 邦幫忙
- 如果是原生 JavaScript 專案,可參考這份套件 https://github.com/fnando/i18n-js 來實作
- 或建立一個 div 容器在頁面上,把需要的 Debug 資訊放在這裡,像是監聽事件等,這做法同樣是透過更新 DOM 元素
- 或更新 mac 上的 Safari 版本至 16.4,但需注意 Safari 16.4 僅支援 macOS Big Sur 和 macOS Monterey 較新的 macOS 版本,目前手上的 mac 因為版本較舊還沒嘗試此解法
- 2023.8 將 macOS 更新至 Monterey 12.6.6 版本以後,即可將 Safari 版本升級到 16.4,Console 又回來了,可喜可賀^_^
Resize fires multiple times
- Reference:
- javascript - window.onresize fires twice - Stack Overflow
- Window resize fires twice in Chrome and FireFox, but only one in Safari - Stack Overflow
- 預期結果:當畫面進行縮放或旋轉時,預期會觸發一次 resize event 來進行後續動作,像是重新生成 UI 元件到相對或絕對位置
- 實際操作:但在不同瀏覽器上,這段期間卻有可能不只觸發一次 resize,導致畫面更新不如預期,例如萬惡的 Safari 或是熟悉的 Chrome,在實測時是發生在行動裝置的 Chrome 上
How to resolve?
這時可透過設定 setTimeout,避免短時間內重複觸發 resize event,範例如下:
let resizeTimer;
window.addEventListener("resize", (e) => {
if (resizeTimer) clearTimeout(resizeTimer); // 判斷是否已發生 resize
resizeTimer = setTimeout(() => {
// Do something...
}, 100);
}, false);
Web API: Fullscreen & Vibration
接著要探討的,是 Web API 提供的全螢幕顯示(Fullscreen)以及控制裝置震動(Vibration)功能。不論是在使用什麼 API 之前,都應該先查詢是否支援所需裝置,否則即使實作完成,到最後才發現原來不支援,反而要花更多時間去找別種工具,因此事前評估尤其重要。
Fullscreen API 顯示全螢幕
- Reference:
- Fullscreen API - MDN Web Docs
- [iOS Safari] Fullscreen API on a non-video element | Apple Developer Forums
以下是不同裝置上的瀏覽器對 Fullscreen API 支援度:
可以看到 Safari 雖然在行動裝置僅支援到 iOS 12,在 PC 上還是能支援到 16.4。但需注意的是,不像其他瀏覽器,Fullscreen API 只能套用在 video 元素上,若用在其他像是 div 元素時一概沒有反應,這點真的很不友善。
但如果因為功能需求,必須套用在 div 元素上的話,還是有方法可以繞過這個限制,例如透過 PWA 來實現全螢幕效果,外觀就像 Native APP 一樣。
What is PWA?
Ref: https://www.evertop.pl/en/progressive-web-app-pwa/
以下是 MDN 關於 PWA 的介紹:
Progressive Web Apps (PWAs) are web apps that use service workers, manifests, and other web-platform features in combination with progressive enhancement to give users an experience on par with native apps.
漸進式網路應用程式(PWAs)是透過 service workers、manifests 技術,並以漸進增強策略,建立跨平台 web 應用程式,提供用戶體驗近似於原生程式的功能。
這裡簡單介紹上述提到的 Service Worker 與 Manifest 兩項技術:
- Service Worker:可想像是位於 Web APP 與網路連接之間的代理人,讓網頁擁夠像 Native APP 一樣支援離線和訊息推播功能
- Manifest:藉由設定 manifest.json 檔的參數,可自訂啟動畫面、安裝在主畫面顯示的名稱與 icon 等
透過 PWA 建立的 Web APP,使用者只需將網頁加到主畫面,開啟時就不會顯示網址列,外表就和 Native APP 一樣是全螢幕,能夠有更好的沉浸式體驗。
除此之外,使用 PWA 還有其他好處,像是安裝快速、定義快取、離線瀏覽、可被搜尋等優點,藉此提升使用者體驗。詳細可參考這篇文章:PWA 實戰經驗分享 - Huli’s blog,有提到如何實作 PWA 以及不同平台可能遇到的問題等等。
Vibration API 使裝置震動
- Reference:Vibration API - MDN Web Docs
Safari 沒有懸念不支援 Vibration API,但令人感到意外的是 Firefox 也僅支援較低版本。
此外,需注意在 Safari 瀏覽器下呼叫 vibrate() 時,有可能因出現 error 導致無法進行後續動作,最保險的做法還是加上防呆驗證,確定裝置有支援才執行功能。
const userAgent = window.navigator.userAgent;
if(!userAgent.includes('iOS') && !userAgent.includes('Mac OS')) navigator.vibrate();
小記
接續上篇筆記,陸續來回在 Safari 和 Android 裝置進行測試,發現一旦接受「只要遇上 Safari 大多支援度不高」這個事實以後,開發起來就快樂多了,畢竟這也不是工程師煩惱就有用的問題;反而要煩惱不同瀏覽器之間對事件觸發、Web API 支援程度的差異性。
簡言之,該如何從現有的技術去實作近似於目標的功能,先熟悉擁有哪些工具再去談可行性,才是更需要學習的地方。