问题
I have multiple SVG elements that are in separate groups. They overlap each other. Example:
<svg id="board" width="100%" height="80%">
<g id="terrain" class="layer">
<path d="M-32,-32L32,-32 32,32 -32,32Z" transform="translate(0, 0)" class="mote terrain hill"></path>
</g>
<g id="guy" class="layer">
<path d="M-21...Z" transform="translate(192, 448)" class="mote guy"></path>
</g>
</svg>
When an x, y position that matches both is clicked, I want to know all that both were clicked. If I bind each to the 'click' event, only the event handlers for one on top gets called. Which is reasonable, although not what I want here.
I'm thinking of creating a topmost layer and having that catch all clicks, then figure out which elements in the other layers should be notified. That's a lot of tracking that I'd like to avoid, if possible. Are there simpler approaches to this?
回答1:
From The SVG spec
"By default, pointer-events must not be dispatched on the clipped (non-visible) regions of a shape. For example, a circle with a radius of 10 which is clipped to a circle with a radius of 5 will not receive 'click' events outside the smaller radius. Later versions of SVG may define new properties to enable fine-grained control over the interactions between hit testing and clipping."
However, there is a way of getting a list of svg shapes that intersect at a particular point. The "getIntersectionList" function returns a list of items.
I've created one of those jsfiddle things jsfiddle.net/uKVVg/1/ Click on the intersection of the circles to get a list of ID's. Manually send events to that list.
Javascript follows:
function s$(a) {
return document.getElementById(a);
}
var list
function hoverElement(evt) {
var root = s$("canvas");
var disp = s$("pointer");
disp.setAttribute("x",evt.clientX);
disp.setAttribute("y",evt.clientY);
rpos = root.createSVGRect();
rpos.x = evt.clientX;
rpos.y = evt.clientY;
rpos.width = rpos.height = 1;
list = root.getIntersectionList(rpos, null);
s = "clicked: "
$.each(list,function(item,val){
if (val.id != "pointer") {
s = s + (val.id) + " ";
}
})
alert(s);
}
var root = s$("canvas");
root.addEventListener("click", hoverElement, false);
There's some javascript that could probably be tidied up, but hopefully it answers your question.
来源:https://stackoverflow.com/questions/20252207/how-can-i-map-click-events-to-elements-in-multiple-layers