2024年12月16日

JS 能否判斷全螢幕狀態?有什麼絕佳應用情境?

JS 能否判斷全螢幕狀態?有什麼絕佳應用情境?

Wayne Fu 0 A+
現在市面上的扁平螢幕讓網頁可視範圍越來越小,以前 4:3、16:10 等適合看網頁的尺寸已經很難看到,主流比例成為 16:9、21:9、32:9 等適合看電影或多工的用途。 為了增加網頁的可視高度,按 F11 進入全螢幕模式是常見作法。這陣子在研究如何寫自動化程式,構想是偵測到全螢幕時,將頁面上無用區塊進一步隱藏,讓可閱讀範圍增加。 原以為這是件極簡單的事,多年前寫「線上看電視」就用 Javascript 操作進入全螢幕、以及檢測當下是否為全螢幕狀態。但這次研究才發現,按 F11 進入全螢幕後,JS 是偵測不到的!如果要用 JS 繞別的路來判斷是否為全螢幕狀態,網路上幾乎找不到有效的作法。 對於這件意料之外的艱鉅任務,還好最後有找到答案,請見本篇的研究心得,以及運用這個技術,我想改善的情境為何。 (圖片出處: chatgpt.com)

一、JS 能作到的事

開始研究之前,有必要先了解 Javascript 能作到、不能作到的事。 1. 全螢幕相關操作 可參考官方文件「使用全螢幕模式」:
  • 可進入全螢幕模式:例如執行 document.body.requestFullscreen()
  • 可離開全螢幕模式:例如執行 document.exitFullscreen()
可參考這個討論串「How to detect browser has gone to full screen」:
  • 可偵測全螢幕狀態:例如執行 document.addEventListener("fullscreenChange", ...) 詳細語法參考官方文件「Document: fullscreenchange event
  • 對於使用者按 F11 產生的全螢幕,無法偵測或離開全螢幕狀態
2. 可取得螢幕、瀏覽器、網頁尺寸 可參考這篇「用JavaScript取得取得各種尺寸資訊」:
  • 螢幕尺寸:執行 screen.width、screen.height
  • 瀏覽器尺寸(包含網址列、書籤列..等等):執行 window.outerWidth、window.outerHeight
  • 網頁可視尺寸:window.innerWidth、window.innerHeight
3. 不可取得螢幕解析度 因為硬體資訊為作業系統層級,所以網頁層級的 JS 沒有權限可取得「螢幕解析度」,來判斷全螢幕狀態(因為全螢幕時「網頁可視尺寸」長寬值能算出「螢幕解析度」的數值)。

二、以往判斷全螢幕模式的思路

1. 網路資訊 「判斷全螢幕模式」這件事並不稀罕,所以查一下網路上都是如何解決的:
  • 大部分網頁提到的都是使用 JS 操作前面提過的 fullscreenchange 來偵測全螢幕狀態,但會這樣寫的人應該都不知道按 F11 的全螢幕是偵測不到的。
  • 另一派的解法如同前面 stackoverflow 討論串「How to detect browser has gone to full screen」,認為 "screen.width === window.innerWidth" 的狀態就是全螢幕
2. 實測效果 然而經我實測:
  • window.innerWidth 怎麼樣都不會等於 screen.width
  • 瀏覽器最大化時,screen.width 等於 window.outerWidth,但兩者數值都遠低於螢幕寬度 px 值
  • window.innerWidth 有時會比 window.outerWidth 還大
怎麼會如此不合邏輯呢?前面的 stackoverflow 討論串有一樓提到,全螢幕時的數值應是這樣: window.innerWidth * window.devicePixelRatio 大約等於 screen.width 這才了解 devicePixelRatio 是瀏覽器根據縮放比例而產生的數值,此數字乘上 window.innerWidth 才會是接近螢幕的寬度。 既然瀏覽器縮放會讓 devicePixelRatio 數值變動,那麼同理 window.innerWidth 也會隨之不斷變動,這也能解釋為何 innerWidth 會大於 outerWidth 了。 只不過 window.innerWidth * window.devicePixelRatio 回答了我的困惑,然而以下狀況依然得不到解答:
  • screen.width 的數值不是螢幕寬度
  • screen.width 與 window.outerWidth 兩者數值都遠低於螢幕寬度

三、觀察作業系統縮放比例

做完一連串實驗後,我的疑惑得到了解答: 1. 1920*1200 螢幕 為了讓螢幕文字更清楚,我的 Win10 無論是縮放比例、文字大小都經過調整,以下全螢幕狀態的測試數據來自 16:10 螢幕、1920*1200 解析度。
  • 縮放比例 200%、字體縮放 125%(等同於 2*1.25 = 250%)
    • window.outerWidth=758、window.outerHeight=470
    • screen.width=768、screen.height=480
  • 縮放比例 200%、字體縮放無
    • window.outerWidth=948、window.outerHeight=588
    • screen.width=960、screen.height=600
  • 縮放比例 150%、字體縮放無
    • window.outerWidth=1264、window.outerHeight=783
    • screen.width=1280、screen.height=800
  • 縮放比例 100%、字體縮放無
    • window.outerWidth=1894、window.outerHeight=1174
    • screen.width=1920、screen.height=1200
2. 作業系統縮放比例的影響 現在謎底揭曉了,原來是這樣子:
  • 作業系統的縮放比例會影響 screen.width 的值,當完全沒有縮放時,screen 長寬值就能顯示原始的 1920*1200
  • 瀏覽器 outerWidth 與 outerHeight 在全螢幕下,不知為何總是比 screen 小一些,而且呈現等比例狀態
  • 在作業系統無縮放時,outerWidth 與 outerHeight 減少的數值為 26*26,似乎 Chrome 瀏覽器會自動扣除 26*26 px,不知是否此數值為視窗標題高度與捲軸寬度?
3. 1920*1080 螢幕 於是我再拿 16:9 螢幕、1920*1080 解析度進行測試。
  • 縮放比例 100%、字體縮放無
  • window.outerWidth=1896、window.outerHeight=1056
  • screen.width=1920、screen.height=1080
可觀察到 outerWidth 與 outerHeight 減少的數值為 24*24,這下算是了解 Chrome 全螢幕的運作邏輯了,會根據螢幕高度來調整「視窗標題高度」、「捲軸寬度」,大約是 2.2% 的比例。 4. 歸納判斷公式 從實驗結果來看,如果要寫 JS 操作的話,大致可以歸納出 Chrome 判斷全螢幕的公式:
  • 當 screen 的寬高等於 window 的 outer 寬高時,一定不是全螢幕狀態
  • 當 screen 的寬高大於 window 的 outer 寬高,且兩者高度差距約等於 screen 的 2.2% 時,此時有 99% 的可能性是全螢幕狀態
  • 1% 的可能性是使用者自己手動拉螢幕大小,拉到接近螢幕大小,誤入此區段時,導致 JS 判斷錯誤
這樣的程式邏輯相信前端工程師都寫得出來,而且其實也不算是個完美的判斷邏輯,就不列出程式碼了。 其實沒列程式碼還有另一個主要原因:最後終於找到完美解決方法了!雖然 JS 無法很好的解決這個問題,但沒想到可以利用 CSS 來解決。

四、利用 CSS 判斷全螢幕狀態

可參考這個討論串「Detect fullscreen mode」,被標注正解的方法一點用也沒有,前面已經提過,但我仔細看過每個回覆後,卻發現了寶藏。 1. CSS 判斷全螢幕 其中有一樓不到 10 個推薦,卻隱藏了完美又優雅的解法,讓我十分拜服並立刻幫按推薦。 原來 CSS 的 @media 語法包含了全螢幕狀態,可參考官網文件「display-mode」,語法如下: @media all and (display-mode: fullscreen) { /*全螢幕下的CSS樣式*/ } 如果非全螢幕狀態,則將語法改為以下: @media not all and (display-mode: fullscreen) { /*非全螢幕下的CSS樣式*/ } 2. JS 監控 CSS 的語法 有了 CSS 解法後,如何用 JS 來讀取 CSS 的狀態呢?可參考官網文件「matchMedia() method」,參考語法如下: var isFullScreen = window.matchMedia("(display-mode: fullscreen)").matches; if (isFullScreen){ // 全螢幕執行的語法 } else { // 非全螢幕執行的語法 } 至此,優雅又簡潔的語法終於找到了!無論是否按 F11 的全螢幕狀態都能偵測出來了~

六、應用情境

那麼,我大費周章找出偵測全螢幕狀態的方法,究竟用途為何呢?簡單舉兩個目前想到的作法: 1. Google 試算表 Google 試算表的工作表區塊,在長寬比很窄的螢幕下,能看到的資料行數少的可憐,網頁超過一半的高度被這些區塊佔據了:
  • 瀏覽器網址列、書籤列
  • 試算表標題、選單、工具圖示
  • 公式列、底部工作表頁籤
進入全螢幕狀態後可隱藏一部分區塊,但還是不夠多。為了讓看到的資料行數最大化,我預計寫自動化程式,偵測到全螢幕時,隱藏所有我不需要看到的區塊,作業時看了也比較舒服、清爽。 詳細作法請參考這篇說明「Google 試算表隱藏選單+工具列+公式列﹍讓工作表區塊最大化」。 2. 網頁閱讀模式 Chrome 有個套件「Reader Mode」(閱讀模式),用熱鍵啟動後,會將網頁的無用區塊移除,例如側邊欄、標頭、底部、廣告等等,只留下「主要文章區塊」,閱讀起來很舒服。 但這個套件並非萬能,不是所有網頁都能將「主要文章區塊」判斷正確,有些類型的網站不容易將主要內容正確顯示出來,例如論壇、購物網站...,可以說是「Reader Mode」主要對部落格型態的網站有效。 同時這個套件並非以全螢幕來閱讀,需要另外手動進入全螢幕狀態。所以我的構想是,自行將網頁切換為全螢幕時,看看能否將「閱讀模式」這個功能,做出符合我自己需求的版本。 如果真能做出來的話,也許再另外寫一篇分享吧~
更多 Javascript 相關技巧:
0 0
如這篇文章對你有幫助,歡迎「分享」到 FB、「追蹤」粉絲團、「訂閱」最新文章

沒有留言:

張貼留言注意事項:

◎ 勾選「通知我」可收到後續回覆的mail!
◎ 請在相關文章留言,與文章無關的主題可至「Blogger 社團」提問。
◎ 請避免使用 Safari 瀏覽器,否則無法登入 Google 帳號留言(只能匿名留言)!
◎ 提問若無法提供足夠的資訊供判斷,可能會被無視。建議先參考這篇「Blogger 提問技巧及注意事項」。
◎ CSS 相關問題非免費諮詢,建議使用「Chrome 開發人員工具」尋找答案。
◎ 手機版相關問題請參考「Blogger 行動版範本的特質」→「三、行動版範本不一定能執行網頁版工具」;或參考「Blogger 行動版範本修改技巧 」,或本站 Blogger 行動版標籤相關文章。
◎ 非官方範本問題、或貴站為商業網站,請參考「Blogger 免費諮詢 + 付費諮詢
◎ 若是使用官方 RWD 範本,請參考「Blogger 推出全新自適應 RWD 官方範本及佈景主題」→ 不建議對範本進行修改!
◎ 若留言要輸入語法,"<"、">"這兩個符號請用其他符號代替,否則語法會消失!
◎ 為了過濾垃圾留言,所有留言不會即時發佈,請稍待片刻。
◎ 本站「已關閉自刪留言功能」。

TOP