指针相对于动态DOM元素的位置

Pointer Position relative to Element with Dynamic DOM

本文关键字:位置 元素 DOM 相对于 动态 指针      更新时间:2023-09-26

这是brainjam找到相对于元素的指针位置的解决方案的后续内容。

作为参考,以下是他的解决方案:

function mouseMoveHandler(e)
{
    var style = getComputedStyle(c,null) ;
    var borderTop = style.getPropertyValue("border-top-width") ;
    var borderLeft = style.getPropertyValue("border-left-width") ;
    var paddingTop = style.getPropertyValue("padding-top") ;
    var paddingLeft = style.getPropertyValue("padding-left") ;
    var offsetX = e.offsetX || e.layerX || 0 ;
    var offsetY = e.offsetY || e.layerY || 0; 
    var x = offsetX ;
    var y = offsetY ;
    if(window.navigator.userAgent.indexOf("Opera") === -1){ 
        x -= parseInt(paddingLeft,10) ;
        y -= parseInt(paddingTop,10) ;
        if(window.navigator.userAgent.indexOf("MSIE") === -1){
            x -= parseInt(borderLeft,10)  ;
            y -= parseInt(borderTop,10)  ;    
        }
    }
    // do something with x, y
}

现在我对这段代码有一些关注:

  1. 这段代码使用了offsetX/offsetY。据我所知,DOM级别2的事件规范仅为MouseEvent指定了属性clientX/clientY和screenX/screenY。据我所知,DOM级别3的事件规范草案只为MouseEvent指定了两个相同的属性。offsetX/offsetY在技术上是"非标准的",还是我在这里遗漏了什么?假设它会一直存在是否安全?

  2. 我有一些像这样的文档:

我可以通过修改viewport的变换来移动场景周围的矩形。

我如何更新视口的变换:

// matrix is the updated transformation of the viewport
var transform = svg_base.createSVGTransformFromMatrix(matrix);
viewport.transform.baseVal.initialize(transform);

在Chrome和Firefox中,这工作得很好。然而,在IE10和Opera 12中,有一些问题,偏移值一直"跳来跳去"。请注意,据我所知,这只发生在涉及到转换更新过程时。把它注释出来,看起来offsetX/offsetY值表现得很好。

下面是IE10中offsetx/offsetY值的简短日志,如果我选择左下角并向上拖动它:

<>之前64年,128年65年,127年66年,128年67年,125年64年,127年67年,122年64年,127年67年,119年64年,128年67年,118年64年,126年67年,115年64年,126年67年,112年64年,126年67年,109年64年,126年67年,106年之前

请注意,当我稳定地向上移动鼠标时,坐标是如何跳跃的(并且非常轻微地向右移动,尽管这不是故意的)。这将导致闪烁效果,并且最终视口将与预期的移动操作不同步。我的问题是为什么这种情况发生在IE10/Opera而不是Firefox/Chrome?是否有更好的方法来获取鼠标指针相对于svg_base元素的位置?或者是否有更好的方法来更新视口变换矩阵?

在FireFox, Chrome, IE10和Opera(大多数使用现代桌面浏览器,由于无法访问而取消了Safari)进行了一些测试后,我基于quirksmode.org的解决方案开发了一个替代方案。

我不确定这在所有情况下有多健壮,或者它在旧浏览器上的表现如何。据我所知,绝大多数代码都是"符合标准的",只有一个例外,即使用pageX/pageY来支持旧浏览器(不确定这适用于哪些浏览器,这是quirksmode.org实现的一部分)。

// params:
//  - elem: the element to get pointer coords relative to
//  - e: MouseEvent object
function mousePosRelElement(elem, e)
{
    var x = 0;
    var y = 0;
    var bounds = elem.getBoundingClientRect();
    // not actually sure which browsers use pageX/pageY, just left in from quirksmode implementation
    if(e.pageX !== undefined && e.pageY !== undefined)
    {
        x = e.pageX - bounds.left - document.body.scrollLeft - document.documentElement.scrollLeft;
        y = e.pageY - bounds.top - document.body.scrollTop - document.documentElement.scrollTop;
    }
    else if(e.clientX !== undefined && e.clientY !== undefined)
    {
        x = e.clientX - bounds.left;
        y = e.clientY - bounds.top;
    }
    return {x: x, y: y};
}

欢迎提出意见和建议