Javascript svg元素能否触发自身下svg元素的点击事件?

Javascript svg元素能否触发自身下svg元素的点击事件?,javascript,typescript,d3.js,Javascript,Typescript,D3.js,这里没有问题 我想知道如果它们覆盖了鼠标坐标,是否可能触发它下面的元素(路径、圆等)的“点击”事件? 最好使用typescript和d3.js库 作为一个例子,考虑有两个圆圈(一个小的在Z位置大一个),这两个都在点击时显示一个消息。 我想,如果我在小圆圈内单击,它的消息会出现,然后大圆圈的消息也会出现 下面是我的示例的HTML代码[编辑:D3的更改版本]: <!DOCTYPE html> <style> circle { fill: lightgreen; strok

这里没有问题

我想知道如果它们覆盖了鼠标坐标,是否可能触发它下面的元素(路径、圆等)的“点击”事件? 最好使用typescript和d3.js库

作为一个例子,考虑有两个圆圈(一个小的在Z位置大一个),这两个都在点击时显示一个消息。 我想,如果我在小圆圈内单击,它的消息会出现,然后大圆圈的消息也会出现

下面是我的示例的HTML代码[编辑:D3的更改版本]

<!DOCTYPE html>
<style>
  circle { fill: lightgreen; stroke: #000; }
</style>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
使用此代码,单击大圆圈显示外部SVG消息。点击小圆圈显示内部SVG消息,但我希望序列为内部外部SVG

[编辑:纠正“传播”一词的误用]

我将元素的“指针事件”属性设置为“全部”。 我知道这使它们“无法通过”,但我希望能够触发它们的事件,也能触发它们下面元素的事件

或者,有没有什么好方法可以获得一个svg元素列表,这些元素覆盖给定的坐标[X,Y](可以通过
d3.鼠标
获得),这样就可以手动触发它们各自的单击事件


感谢您的帮助。

解决方案将取决于控制svg元素大小的形状类型和参数。如果需要非最佳但通用的解决方案,可以使用图元的边界框。使用边界框,您可以通过针对[x,y]目标测试x和y范围来确定是否有任何对象位于[x,y]上方

您可以优化以下代码并将其插入任何d3功能块:

((形状)=>{
设bbox=this.getBBox();
设minX=bbox.x;
设maxX=minX+bbox.width;
设minY=bbox.y;
设maxY=minY+bbox.width;
设isOver=shape.x>minX&&shape.xminY&&shape.y

解决方案将取决于形状类型和控制svg元素大小的参数。如果需要非最佳但通用的解决方案,可以使用图元的边界框。使用边界框,您可以通过针对[x,y]目标测试x和y范围来确定是否有任何对象位于[x,y]上方

您可以优化以下代码并将其插入任何d3功能块:

((形状)=>{
设bbox=this.getBBox();
设minX=bbox.x;
设maxX=minX+bbox.width;
设minY=bbox.y;
设maxY=minY+bbox.width;
设isOver=shape.x>minX&&shape.xminY&&shape.y

首先,此解决方案使用的是D3V5,而不是您在HTML中引用的D3V2(已经9年了)

回到你的问题,你说:

我希望能够触发它们的事件并传播到它们下面的元素,直到SVG本身被触发

这不是传播的意思。冒泡表示在DOM树中向上,但这些圆不是父/子,它们只是兄弟。因此,您想要的与传播无关,因此我们需要一种不同的方法

我在这里建议的方法使用
elementFromPoint
,以获取您单击的坐标下的所有元素,并结合
d3.dispatch
来调度单击(我找到了
getAllegements
函数,并对其进行了修改,以便与d3一起使用)。最后,我需要点击
标记,因为
elementFromPoint
会忽略指针事件设置为
none
的元素(顺便说一下,它是
指针事件
,而不是
指针事件

以下是演示:

let clicked;
var svg=d3.选择(“正文”).追加(“svg”)
.style(“浮动”、“左”)
.attr(“宽度”,480)
.attr(“高度”,480)
.attr('pointer-event','all');
svg.append(“圆”)
.attr('pointer-event','all')
.attr(“cx”,240)
.attr(“cy”,240)
.attr(“r”,200)
.on(“单击”,函数(){
如果(!单击)返回;
日志(“外部”)
});
svg.append(“圆”)
.attr('pointer-event','all')
.attr(“cx”,240)
.attr(“cy”,240)
.attr(“r”,100)
.on(“单击”,函数(){
如果(!单击)返回;
日志(“内部”)
});
var div=d3.选择(“主体”).追加(“div”)
.样式(“浮动”、“左”);
功能日志(消息){
附加部分(“p”)
.文本(信息)
.style(“背景”,“#ff0”)
.transition()
.持续时间(2500)
.样式(“不透明度”,1e-6)
.remove();
}
d3.选择(“svg”)。单击(“单击”,函数(){
单击=真;
获取等位基因(…d3.mouse(this));
日志(“SVG”)
单击=假;
函数(x,y){
常量元素=[];
让thisElement=document.elementFromPoint(x,y);
while(thisElement&&thisElement.nearestViewportElement){
元素。推(this元素);
d3.选择(此元素)。样式(“显示”、“无”);
thisElement=document.elementFromPoint(x,y);
}
元素。forEach(函数(elm){
d3.选择(elm).style(“显示”,null)
.发送(“点击”);
});
};
})

圈{
填充物:浅绿色;
行程:#000;
}

首先,此解决方案使用的是D3 v5,而不是您在HTML中引用的D3 v2(已经9年了)

回到你的问题,你说:

我希望能够触发它们的事件并传播到它们下面的元素,直到SVG本身被触发

这不是传播的意思。冒泡表示在DOM树中向上,但这些圆不是父/子,它们只是兄弟。因此,您想要的与传播无关,因此我们需要一种不同的方法

我的建议
var svg = d3.select("body").append("svg")
    .style("float", "left")
    .attr("width", 480)
    .attr("height", 480)
    .attr('pointer-events', 'all')
    .on("click", log("SVG"));

svg.append("circle")
    .attr('pointer-events', 'all')
    .attr("cx", 240)
    .attr("cy", 240)
    .attr("r", 200)
    .on("click", log("OUTER"));

svg.append("circle")
    .attr('pointer-event', 'all')
    .attr("cx", 240)
    .attr("cy", 240)
    .attr("r", 100)
    .on("click", log("INNER"));

var div = d3.select("body").append("div")
    .style("float", "left");


function log(message) {
  return function() {
    div.append("p")
        .text(message)
        .style("background", "#ff0")
      .transition()
        .duration(2500)
        .style("opacity", 1e-6)
        .remove();
  };
}
<d3 function block>((shape)=>{
let bbox = this.getBBox(); 
let minX=bbox.x;
let maxX=minX+bbox.width; 
let minY=bbox.y; 
let maxY=minY+bbox.width; 
let isOver=shape.x>minX && shape.x < maxX && shape.y > minY && shape.y < maxY;
//..do something depending on the value of isOver
})