为什么Firefox中会出现这种情况?

为什么Firefox中会出现这种情况?,firefox,events,svg,Firefox,Events,Svg,正如我在Chrome和MSIE中所期望的那样。出于某种原因,事件在内部rect元素和SVG元素(我认为)上触发。这是调味汁(这是整页): svg=document.getElementById('mySVG'); rect=document.getElementById('myRect'); svg.onmousemove=函数(e) { 如果(例如,currentTarget.toString().indexOf('SVGSVGElement')>=0){ var x=e.offsetX,

正如我在Chrome和MSIE中所期望的那样。出于某种原因,事件在内部rect元素和SVG元素(我认为)上触发。这是调味汁(这是整页):


svg=document.getElementById('mySVG');
rect=document.getElementById('myRect');
svg.onmousemove=函数(e)
{
如果(例如,currentTarget.toString().indexOf('SVGSVGElement')>=0){
var x=e.offsetX,
y=e.offsetY;
if(x&y){
console.log(x)
rect.setAttribute('x',x-50);
rect.setAttribute('y',y-50);
}
}
};

Firefox和Chrome以不同的方式实现事件。如果您
console.log(e.target.id,x)
,则可以观察到这一点。Firefox日志如下所示:

mySVG 394
myRect 35
mySVG 372
myRect 36
mySVG 354
mySVG 353
myRect 48
如果矩形不在鼠标下方,则相对于
svg
元素计算
offsetX
。然后,将矩形移动到鼠标下方,然后将下一个事件之一(取决于它们触发的速度)分派到
rect
元素,并相对于该元素计算
offsetX
。由于侦听器相对于
svg
移动矩形,因此它会跳到左上角,在下一个事件中,它不再位于鼠标下方,并且事件会再次调度到
svg

铬原木

mySVG 400
myRect 392
myRect 383
myRect 375
myRect 368
myRect 363
当第一个事件被分派到
svg
元素时,以下所有事件都被分派到
rect
。原因是无论鼠标是否在
rect
上,总是相对于
svg
元素计算
offsetX

考虑到
offsetX
的定义

返回事件发生位置相对于目标节点填充边原点的x坐标

我认为Firefox的实现更有意义

找到相对坐标的最佳解决方案可能是

// matrix contains offset relative to browser window
// as properties e and f
var ctm = svg.getScreenCTM();
// mouse positions relative to browser window
var x = e.clientX - ctm.e,
    y = e.clientY - ctm.f;

跨SVG和HTML元素工作的通用解决方案是库。

但是事件处理程序绑定到SVG元素-因此当鼠标在SVG元素周围移动时它会触发-所以offsetX和offsetY不应该是鼠标相对于该元素的坐标-就像在Chrome和MSIE中一样(11)?即使鼠标在矩形上,也能得到相对于整个画布的偏移量吗?这是一个通过offsetParents并添加X和Y坐标的问题吗?事件处理程序绑定到
svg
,但是发生在
rect
上的事件会冒泡到
svg
e.target
为您提供事件分派到的原始元素,
e.currentTarget
处理程序附加到的元素。将其更改为使用offsetParent/offsetLeft和offsetTop:由于目标元素是SVGElements,而不是Htmlements,因此您只需获取这些元素的
undefined
。您实际上返回的是pageX/pageY。只要给svg一个100px的边距,“rect”就永远不会在光标下了。太好了-很好用-谢谢。FWIW我将我的选项移动到一个新页面,它停止工作…:-(
// matrix contains offset relative to browser window
// as properties e and f
var ctm = svg.getScreenCTM();
// mouse positions relative to browser window
var x = e.clientX - ctm.e,
    y = e.clientY - ctm.f;