我有一个带有mousemove事件的SVG元素,显示指针的坐标。当鼠标移动到遮挡元素上时,将阻止mousemove事件。我需要将事件传播到原始元素。
我尝试更改pointer-events
属性,但这会影响所有鼠标事件,我需要遮挡元素来响应其他事件。有什么建议。
答案 0 :(得分:1)
也许解决这个问题的方法是将你的所有事件绑定到你的svg和遮挡元素所在的容器/ parentNode中 - 将'mouse'元素记录在'{{}}'的''外部'元素中其中子元素的属性。
如果没有问题中的代码示例,很难确切地知道需要什么,但原则可能遵循这些原则......
<!-- HTML sample -->
<div id="container">
<div id="elem1" class="occluded">Element #1</div>
<div id="elem2" class="occluded">Element #2</div>
<div class="fullWidthHeightOverlay"></div>
</div>
<div id="eventLog"></div>
假设#container
具有宽度和高度,.occluded
元素在该图层中浮动,但位于.fullWidthHeightOverly
元素下方(如果我理解了您的问题正确起作用)你的SVG)。 #eventLog
可以将行为附加到以后。
我们还假设我们想要相对于外部#container
图层记录鼠标位置,以便在鼠标位于.occluded
元素之一时使“点击”行为可用。 (我希望这很清楚?)
首先,我们需要将一些事件附加到#container
- 在这种情况下,一个用于鼠标位置,一个用于点击。
/* SIMPLE SELECTOR - '#id' */
function $(a){
$.b = $.b || {};
if (void 0 === $.b[a]) $.b[a] = document.getElementById(a.slice(1));
return $.b[a];
}
var elem1, elem2;
/* ! */
function addEvents() {
$('#container').addEventListener('mousemove', logMousePos, false);
$('#container').addEventListener('click', occludedClick, false);
}
您会看到我还创建了一些我们可以将.occluded
元素分配给的变量。
接下来,我们需要logMousePos()
和occludedClick()
函数来记录相对于.occluded
图层上鼠标位置的两个.fullWidthHeightOverly
元素的位置属性在他们之上,然后发起一些简单的行为,EG ..
function logMousePos(e) {
var e1 = elem1.getBoundingClientRect(),
e2 = elem2.getBoundingClientRect(),
e1CL = elem1.classList,
e2CL = elem2.classList;
/* is mouse inside #elem1 ? */
if (check.X(e.clientX, e1) && check.Y(e.clientY, e1)) {
/* if no 'over' class add it... */
if (!e1CL.contains('over')) e1CL.add('over');
} else {
/* ...if 'over' class remove it */
if (e1CL.contains('over')) e1CL.remove('over');
}
/* is mouse inside #elem2 ? */
if (check.X(e.clientX, e2) && check.Y(e.clientY, e2)) {
if (!e2CL.contains('over')) e2CL.add('over');
} else {
if (e2CL.contains('over')) e2CL.remove('over');
}
}
function occludedClick(e) {
var e1 = elem1.getBoundingClientRect(),
e2 = elem2.getBoundingClientRect(),
e1CL = elem1.classList,
e2CL = elem2.classList;
/* was mouse clicked inside #elem1 or #elem2 or not ? */
if (check.X(e.clientX, e1) && check.Y(e.clientY, e1)) {
$('#eventLog').textContent = 'Element #1 pseudo-Clicked';
} else if (check.X(e.clientX, e2) && check.Y(e.clientY, e2)) {
$('#eventLog').textContent = 'Element #2 pseudo-Clicked';
} else {
$('#eventLog').textContent = '';
}
}
..在那里你会注意到我指的是一些check()
对象方法,嗯,检查鼠标是否在.occluded
元素的'boundingClientRect'内。
var check = {
X: function(x, el) {
return (x > el.left && x < el.right);
},
Y: function(y, el) {
return (y > el.top && y < el.bottom);
}
};
然后只需初始化变量并添加事件监听器......
(function init() {
addEvents();
elem1 = $('#elem1');
elem2 = $('#elem2');
}());
您可以找到整个事件bounding Client Rectangles的JSFIDDLE。
我希望这足以让你能够在你的特定情况下应用这个原则。
:)
答案 1 :(得分:0)
总结Brian Peacock的优秀和详细建议的主要观点: 似乎问题是svg元素的图形顺序(背后的内容)不遵循DOM层次结构,因此不能直接使用正常的事件冒泡。因此,必须在共同的高点捕获事件并实际搜索该点下的元素。
作为一般性的讨论点(请原谅我这里),应该注意到在许多情况下这不是最佳解决方案。例如,当捕获快速发生的事件时,例如mousemove
,当SVG中存在许多元素时,并且当平滑GUI需要快速响应时,该策略可能计算成本太高。如果更好的事件处理系统包含在SVG规范中并包含在浏览器中,那么一切都可以由引擎完成,这将是很棒的。这将显着提高具有纯SVG GUI的能力。