大部分的情況下,我們設計網頁只需關心可見元素在網頁文件(document.body)上的座標就好,不需要知道它在電腦螢幕的絕對座標,但有一種情況例外 - window.open(),傳入的 top 及 left 參數會以電腦螢幕為基準。

我有個冷門需求,想在指定元素下方用 window.open() 開個小型新視窗,示範如下,不管瀏覽器拖到哪裡,新視窗會永遠開在按鈕下方。

為了達到這個目標,我們必須知道按鈕相對電腦螢幕的絕對座標,原理是依序取得 1) 瀏覽器左上角的絕對座標,2) 瀏覽器上緣加上頁籤、地址列區塊高度,也就是 ViewPort 左上角座標,3) ViewPort 左上角加按鈕 top、left 算出按鈕左上角座標 4) 加上按鈕高度算出新視窗左上角座標。

瀏覽器視窗左上角座標可用 window.screenX、screenY 取得 參考,頁籤及地址列區塊高度則用 window.outerHeight 減去 window.innerHeight 取約略值(差額還包含底部厚度,若在下方開啟 F12 工具會嚴重偏差),至於按鈕到 ViewPort 左上角則可用 Element.getBoundingClientRect() 取得 top 及 left (參考下圖)。

依據以上原理,我們便能算出 window.open() 的 top 及 left 要給多少才會剛好出現在按鈕正下方,程式範例如下:

<!DOCTYPE html>
<html>
    <body>
        <button id="btn" onclick="openWinHere()">Test</button>
        <script>
            function openWinHere() {
                var btn = document.getElementById('btn');
                var btnRect = btn.getBoundingClientRect();
                var x = btnRect.left + window.screenX ;
                var y = btnRect.top + btnRect.height + window.screenY + (window.outerHeight - window.innerHeight);
                var win = window.open('about:blank', '_blank', 
                    `popup=yes,width=100,height=100,left=${x},top=${y}`);
            }
        </script>
    </body>
</html>

除了將新視窗開在指定元素位置,還有一種應用情景是建立一個大小相同的新視窗覆蓋在原視窗正上方,靠上面學到的知識,用 screenX、screenY、innerWidth、innerHeight 便能輕鬆搞定。
註:新視窗因為沒有頁籤區上方較短,innerHeight + 20 補差額。

<!DOCTYPE html>
<html>
    <body>
        <button id="btn" onclick="openWinOverlay()">Test</button>
        <script>
            function openWinOverlay() {
                var win = window.open('https://blog.darkthread.net', '_blank', 
                    `popup=yes,width=${window.innerWidth},height=${window.innerHeight+20},left=${window.screenX},top=${window.screenY}`);
            }
        </script>

    </body>
</html>

實測網頁以 Edge/Chrome/Firefox 在多螢幕環境執行均能正確定位,收入工具箱。

Example to find absolute position to computer screen of web page element.


Comments

Be the first to post a comment

Post a comment