从Firefox扩展中获取DOM元素的绝对屏幕边界

Get absolute screen bounds of a DOM element from a Firefox extension

本文关键字:屏幕 边界 元素 DOM Firefox 扩展 获取      更新时间:2023-09-26

我有一个firefox扩展,它需要获得DOM元素的确切屏幕坐标,并通过js/c-types将其传递给本地DLL。

现在我已经涵盖了大部分内容:

var gDomWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(nsIDOMWindowUtils);
function getScreenRect(oElem)
{
    var rc =
    {
        x : 0,
        y : 0,
        w : 0,
        h : 0
    };
    var o = oElement;
    while(o != null)
    {
        rc.y += o.offsetTop;
        rc.x += o.offsetLeft;
        o = o.offsetParent;
    }
    var x = {}, y = {};
    gDomWindowUtils.getScrollXY(false, x, y);
    rc.x -= x.value;
    rc.y -= y.value;
    var scale = gDomWindowUtils.screenPixelsPerCSSPixel;
    rc.x *= scale;
    rc.y *= scale;
    rc.w *= scale;
    rc.h *= scale;
    return rc;
};

这可以处理滚动和缩放,但我得到的值是相对于浏览器窗口的,而不是相对于屏幕的。

如何检测浏览器实际渲染区域的客户端区域偏移?我甚至可以通过js/ctypes使用本机代码(Win32),所以我试着看看是否可以使用FindWindow()/GetWindowRect()来获得它,但整个firefox是一个HWND,控件都不是本机窗口。

因此,我的一个想法是,由于firefox的UI是一个XUL文档,我应该能够获得菜单栏、选项卡栏等,并找到浏览器区域的绝对偏移量。但是,我不知道如何访问定义浏览器UI的XUL树。

有人能给我一个指针吗?

[编辑]忽略上面代码中未定义的rc.w和rc.h,这与问题无关。

您基本上已经得到了它,但我建议使用getBoundingClientRect()而不是offsetLeft/offsetTop:

var rect = oElement.getBoundingClientRect();
var rc = {
  x: rect.left,
  y: rect.top,
  w: rect.width,
  h: rect.height
};

getBoundingClientRect()考虑滚动,这样您就不需要添加它了。您可以使用window.mozInnerScreenXwindow.mozInnerScreenY:获得相对于屏幕的坐标

rc.x += window.mozInnerScreenX;
rc.y += window.mozInnerScreenY;

然后将这些值与screenPixelsPerCSSPixel相乘。这应该会给你合适的屏幕坐标。

我将再添加一个帮助我解决类似问题的"技巧"。

每当我的代码接收到mousemove事件时,我都会捕捉该事件提供的所有坐标中的鼠标光标位置,其中至少包括"screen"、"client"answers"pageXY"坐标。然后,对于任何其他目的,我可以通过减去其中适当的两个来计算这些坐标之间的差。

在你的情况下,你可能会计算这样的偏移:

deltaX = event.screenX - event.clientX;
deltaY = event.screenY - event.clientY;

offsetX = event.screenX - event.pageX;
offsetY = event.screenY - event.pageY;

然后只需将deltaX和deltaY或offsetX和offsetY添加到这些坐标中即可获得屏幕坐标。