2017-06-13 123 views
0

它可以像Chrome和MSIE中预期的那样工作。出于某种原因,事件触发内部矩形元素以及SVG元素(我认为)。这里是酱(这是整个页面):为什么在Firefox中闪烁?

<html> 
<body> 

    <svg width="400" height="400" style="overflow: hidden; border: 1px solid gray" id="mySVG"> 
     <rect x="10" y="10" width="100" height="100" fill="red" id="myRect"></rect> 
    </svg> 

    <script> 
     svg = document.getElementById('mySVG'); 
     rect = document.getElementById('myRect'); 

     svg.onmousemove = function (e) 
     { 
      if (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); 
       } 
      } 
     }; 
    </script> 

</body> 
</html> 

回答

0

Firefox和Chrome以不同的方式实现事件。如果你console.log(e.target.id, x)可以被观察到。 Firefox的日志是这样的:

mySVG 394 
myRect 35 
mySVG 372 
myRect 36 
mySVG 354 
mySVG 353 
myRect 48 

如果矩形不是鼠标下,offsetX相对于svg元计算。然后,矩形在鼠标下移动,并且下一个事件之一(取决于它们发射的快速度)被分派到rect元素,并且相对于此计算offsetX。由于侦听器将矩形相对于svg移动,它将跳转到左上角,并且在下一个事件中,它不再位于鼠标下方,并且该事件再次被分派到svg

铬日志

mySVG 400 
myRect 392 
myRect 383 
myRect 375 
myRect 368 
myRect 363 

当第一个事件被调度到svg元素,所有后续事件被派往rect。原因是offsetX总是相对于svg元素进行计算,无论鼠标是否在rect之上。

Considerung的CSSOM定义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元素是d3this internal function的一般解。

+0

但事件处理程序绑定到SVG元素 - 所以它会在鼠标围绕SVG元素移动时触发 - 所以不应该将offsetX和offsetY作为鼠标相对于坐标的坐标 - 就像它们在Chrome中一样MSIE(11)?即使鼠标超过了矩形,是否可以获得与整个画布相关的偏移量?这是通过offsetParents并添加X和Y坐标的问题吗? – Richard

+0

事件处理程序被绑定到'svg',但是在'rect'上发生的事件一直冒泡到'svg'。 'e.target'为你提供事件发送的原始元素,'e.currentTarget'是处理程序所连接的元素。 – ccprog

+0

改为使用offsetParent/offsetLeft和offsetTop代替:https://www.rgraph.net/tests/svg-getmousexy.html – Richard