首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >svg元素能触发svg元素的点击事件吗?

svg元素能触发svg元素的点击事件吗?
EN

Stack Overflow用户
提问于 2020-06-08 19:36:07
回答 2查看 970关注 0票数 1

这里有个问题。

我想知道是否有可能触发元素的“单击”事件(路径、圆圈、.)如果他们覆盖鼠标坐标的话?最好在打字稿和使用d3.js库。

例如,考虑有两个圆圈(z位置上的一个小圆圈),这两个圆圈在点击时都会显示一个消息。我想如果我点击里面的小圆圈,它的信息出现,然后更大的圆圈的信息也出现。

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

代码语言:javascript
复制
<!DOCTYPE html>
<style>
  circle { fill: lightgreen; stroke: #000; }
</style>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>

下面是相关的javascript:

代码语言:javascript
复制
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();
  };
}

使用此代码,单击大圆圈将显示、外部SVG消息。单击这个小圆圈显示内部SVG消息,但是我想要序列内部外部SVGE 217

编辑:纠正了单词“传播”的误用

我将元素的‘指针-事件’属性放置到'all‘。我知道这使他们“不通过”,但我希望能够触发他们的事件,也触发他们下的元素事件。

或者,是否有任何很好的方法来获得覆盖给定坐标X,Y的svg元素列表,以便可以手动触发它们各自的单击事件?

谢谢你的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-08 23:20:16

首先,该解决方案使用的是D3 v5,而不是您在HTML中引用的D3 v2 (已有9年历史)。

回到你的问题,你说:

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

这不是传播的意思。冒泡意味着上升到DOM树中,但是这些圆圈并不是父/子,它们只是兄弟姐妹。因此,您想要的与传播无关,所以我们需要一种不同的方法。

这里我建议的方法使用elementFromPoint,将所有元素都放在您单击的坐标下,并结合d3.dispatch来分配单击(我找到了getAllElements函数here,并对其进行了修改以用于D3)。最后,我需要clicked标志,因为指针事件设置为none的元素被elementFromPoint忽略(顺便说一句,它是pointer-events,而不是pointer-event)。

下面是演示:

代码语言:javascript
复制
let clicked;

var svg = d3.select("body").append("svg")
  .style("float", "left")
  .attr("width", 480)
  .attr("height", 480)
  .attr('pointer-event', 'all');

svg.append("circle")
  .attr('pointer-event', 'all')
  .attr("cx", 240)
  .attr("cy", 240)
  .attr("r", 200)
  .on("click", function() {
    if (!clicked) return;
    log("OUTER")
  });

svg.append("circle")
  .attr('pointer-event', 'all')
  .attr("cx", 240)
  .attr("cy", 240)
  .attr("r", 100)
  .on("click", function() {
    if (!clicked) return;
    log("INNER")
  });

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


function log(message) {
  div.append("p")
    .text(message)
    .style("background", "#ff0")
    .transition()
    .duration(2500)
    .style("opacity", 1e-6)
    .remove();
}

d3.select("svg").on("click", function() {
  clicked = true;
  getAllElements(...d3.mouse(this));
  log("SVG")
  clicked = false;

  function getAllElements(x, y) {
    const elements = [];
    let thisElement = document.elementFromPoint(x, y);
    while (thisElement && thisElement.nearestViewportElement) {
      elements.push(thisElement);
      d3.select(thisElement).style("display", "none");
      thisElement = document.elementFromPoint(x, y);
    }
    elements.forEach(function(elm) {
      d3.select(elm).style("display", null)
        .dispatch("click");
    });
  };
})
代码语言:javascript
复制
<!DOCTYPE html>
<style>
  circle {
    fill: lightgreen;
    stroke: #000;
  }
</style>

<body>
  <script src="https://d3js.org/d3.v5.min.js"></script>

票数 0
EN

Stack Overflow用户

发布于 2020-06-08 20:06:37

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

可以优化并将以下代码插入到任何d3函数块中:

((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 &let;shape.y &let;maxY;//.)根据isOver }

的值做一些事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62269927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档