chrome彈窗在雙屏狀況下left居中定位異常分析

背景

使用 window.open 進行彈窗顯示,實現微信二維碼彈窗功能 在雙屏狀況下,chrome瀏覽器位於副屏彈窗時,會存在彈窗位置異常問題。目前網上相關解析及解決方案几乎沒有,故寫此文章以做分享。 html

圖片

文章重點

雙屏狀況下,chrome瀏覽器彈窗位置問題

  • 多屏幕時,chrome瀏覽器位於非主屏進行彈窗顯示時,設置彈窗的left,top將會異常
  • 本文將分析其顯示異常的緣由,並給出解決方案

解決該問題的分析過程

  • 這是本文分享的另外一個重點
  • 除了解決方案,但願能經過本文和你們分享筆者解決該問題時的思路和方法。
  • 這些方法可能不是最優的,但但願能給你們帶來一點觸動或者啓示。在解決到其餘問題的時候也用得上。
    圖片

window.open的第三個參數及其兼容性介紹

  • window.open方法相信你們都不會陌生,一般用於傳遞一個地址參數,新建一個瀏覽器tab頁面。
  • 但除了第一個地址參數,window.open還另外接收兩個參數,分別是「strWindowName(新窗口的名稱)」,「strWindowFeatures(新窗口特性)」
  • 這強調的是第三個參數,當設置了第三個參數後,新開的彈窗將會在原頁面的基礎上,已非tab頁面的形式進行顯示,有如下幾個特色
    • 在原頁面上進行彈窗顯示,而不是新起瀏覽器tab頁面進行跳轉。其顯示方式相似alert彈窗,屬於原頁面的一個功能模塊,而不是跳轉至新頁面。
    • 非tab頁面,這意味着它不像其餘tab頁面那樣能夠放在瀏覽器tab欄中,它是摺疊不進去了,是以彈窗的形式呈現。
  • 第三個參數「strWindowFeatures」能夠設置新窗口特性,例如寬度,高度,距頂,距左,是否顯示滾動條等等。本文不作詳細介紹,參數詳情能夠參考這篇文章
  • 須要注意的是,strWindowFeatures裏的特效並非每一個瀏覽器都支持的,不一樣於「dom」,這屬於「bom(borwser Object Model)」的內容。具體兼容性這裏也不講了,網上也有相關文章
    圖片

chrome的兼容性與坑(重點一)

異常的顯示

  • 即便看完上面的兼容性文章,當你使用chrome瀏覽器,位於非主屏進行彈窗時,依然會存在位置設置異常的問題。
  • 實現居中顯示彈窗,通常代碼會這樣寫
    const windowWidth = window.screen.width // 屏幕寬度
    const windowHeight = window.screen.height  // 屏幕高度
    const pageWidth = 600 // 彈出窗口的寬度
    const pageHeight = 550 // 彈出窗口的高度
    let pageTop = (windowHeight - pageHeight) / 2 // 窗口的垂直位置
    let pageLeft = (windowWidth - pageWidth) / 2 // 窗口的水平位置;
    window.open('xxx', 'xxx', `width=${pageWidth},height=${pageHeight},top=${pageTop},left=${pageLeft}`) // 實現居中彈窗
    複製代碼
  • 這段代碼在主屏幕顯示沒有問題,能夠居中顯示,但若是將頁面移換到副屏幕進行彈窗時。你會發現,不管參數怎麼設置,彈窗都會在屏幕最左側或屏幕最右側進行顯示,並非水平居中。點擊這裏查看示例

異常的緣由及其解決方案

  • 緣由可能不少同窗都難以想到,這是由於彈窗的left和top參數,並非基於當前頁面做爲原點進行計算的,而是以主屏幕做爲原點進行計算前端

  • 因此進行位置設置時,須要計算其基於主屏幕的偏移值。chrome

  • 那怎麼知道當前是否處於主屏幕上呢?能夠經過window.screen.availLeft參數來解決,該參數返回瀏覽器可用空間左邊距離屏幕(系統桌面)左邊界的距離。編程

  • 經過該參數,甚至不須要知道目前處於哪一個屏幕上,直接加上該參數便可基於當前屏幕進行定位。修改後的代碼以下segmentfault

    const {
      availLeft, // 返回瀏覽器可用空間左邊距離屏幕(系統桌面)左邊界的距離。
      availHeight, // 瀏覽器在顯示屏上的可用高度,即當前屏幕高度
      availWidth, // 瀏覽器在顯示屏上的可用寬度,即當前屏幕寬度
    } = window.screen
    const pageWidth = 600 // 彈出窗口的寬度
    const pageHeight = 550 // 彈出窗口的高度
    let pageTop = (availHeight - pageHeight) / 2 // 窗口的垂直位置
    let pageLeft = (availWidth - pageWidth) / 2 // 窗口的水平位置;
    left += availLeft // 加上屏幕偏移值
    window.open('xxx', 'xxx', `width=${pageWidth},height=${pageHeight},top=${pageTop},left=${pageLeft}`) // 實現居中彈窗
    複製代碼
  • 「top」參數的設置一樣存在這個問題瀏覽器

  • 若是主屏幕和副屏幕並非處於相同的高度,「top」值的設置一樣會因爲距系統主屏幕定位,而發生定位異常的顯示。看下面這張圖可能更好地理解 bash

    圖片

  • 另外目前筆者發現,這個兼容性問題,僅會在chrome內核的瀏覽器存在,safari上運行是不存在該問題的。綜上所述,得出最終的解決方案爲微信

    const {
      availTop, // 返回瀏覽器可用空間左邊距離屏幕(系統桌面)左邊界的距離。
      availLeft, // 返回瀏覽器可用空間左邊距離屏幕(系統桌面)左邊界的距離。
      availHeight, // 瀏覽器在顯示屏上的可用高度,即當前屏幕高度
      availWidth, // 瀏覽器在顯示屏上的可用寬度,即當前屏幕寬度
    } = window.screen
    const pageWidth = 600 // 彈出窗口的寬度
    const pageHeight = 550 // 彈出窗口的高度
    let pageTop = (availHeight - pageHeight) / 2 // 窗口的垂直位置
    let pageLeft = (availWidth - pageWidth) / 2 // 窗口的水平位置;
    if (navigator.userAgent.indexOf('Chrome') !== -1) { // 兼容chrome的bug
      top += availTop // 距頂偏移值
      left += availLeft // 距左偏移值
    }
    window.open('xxx', 'xxx', `width=${pageWidth},height=${pageHeight},top=${pageTop},left=${pageLeft}`) // 實現居中彈窗
    複製代碼

問題解決過程(重點二)

筆者遇到該問題是經過以下方式一一尋找解決方案網絡

百度

最基礎,成本最低的一步,筆者進行過如下關鍵字的搜索(這裏主要突出關鍵字提取)dom

  • window.open 居中顯示
  • window.open left chrome
  • window.open left 異常
  • window.open 定位 異常
  • window.open chrome 兼容性
  • window.open 雙屏顯示異常
  • 搜索結果,找到了相關的問題,但未能找到真正有效的解決方案。

問答論壇

  • stackoverflow,國外著名的編程問答網站,純英文,內容全。
  • segmentfault,國內的stackoverflow,內容也不錯。

MDN官網

維基百科:MDN Web Docs(舊稱Mozilla Developer Network、Mozilla Developer Center,簡稱MDN)是一個聚集衆多Mozilla基金會產品和網絡技術開發文檔的免費網站。

  • 通常能夠看做前端基礎函數的官方說明文檔,具備必定的權威性,固然必定程度上會更爲難懂

其餘頁面代碼分析

尋找網上實現了該功能的網站,下載其頁面代碼進行分析。 網上的代碼都是加密過的,雖然不直觀,但能推測或猜出一些端倪

  • 各關鍵詞搜索
    • 首先,經過chrome調試工具,找到觸發彈窗的按鈕
    • ctrl+s,下載整個頁面,
    • 經過IDE全局搜索整個頁面中關於該按鈕的信息,如class,id,及其餘屬性值,能定位到該按鈕的屬性都全局搜索一遍
    • 逐文件查看,有無相關配置
  • window.open 函數名搜索
    • 打開彈窗確定須要經過該語句,全局搜索,若是window沒被覆蓋的話應該能找到
  • 第三個參數搜索
    • 根據 strWindowFeatures 可配置項目進行全局搜索,
    • 提取其特色,如「scrollbars」,「titlebar」這些變量
    • 以及其字符串形式傳參的特色,搜索「,left=」「,height=」
  • 重置函數
    • 終極大招,函數重置,及經過在chrome控制檯重置該函數,來觀察其傳參狀況
    • 打開chrome控制檯,找到Console欄,拷貝以下代碼
      window.open = function () {
        console.log(arguments)
      }
      複製代碼
    • 再此進行登陸彈窗操做,觸發函數執行

筆者是在前三個方法都失敗的狀況下,經過第四個方法找到的問題所在。

  • 發現其left值傳參爲負數,
  • 在本身項目中設置爲負數也能實現居中效果
  • 從而推測出緣由

感謝閱讀,祝好

圖片
相關文章
相關標籤/搜索