【问题标题】:d3 count overlapping shapes at pointd3 计算点的重叠形状
【发布时间】:2019-01-07 03:08:50
【问题描述】:

我有这个基本的椭圆图:https://codepen.io/almn22/pen/zJrWrd

我正在尝试这样做,以便当您将鼠标悬停在某个区域上时,下方会显示文本输出,显示该点有多少个形状。因此在下面的示例中,当您将鼠标悬停在最深的灰色区域上时,应该会显示“3”的文本。

对于我的实际用例,形状是随机的,没有可预测的形式,所以我不能指望它们是椭圆或圆形。我正在使用 d3js 将它们绘制为 svg 多边形。我拥有的多边形数据只是“点”属性。

任何帮助将不胜感激!

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
    ellipse {
  stroke: white;
  fill: lightgray;
  mix-blend-mode: multiply;
}
  </style>
</head>

<body>
  <script>
    const svgContainer = d3.select("body")
  		.append("svg")
  		.attr("width","560")
  		.attr("height","900").attr("translate", "45, 45");

    const ellipses = [
  		{"cx":  145, "cy":  125, "rx": 88, "ry": 20},
  		{"cx":  175, "cy":  175, "rx": 88, "ry": 77},
  		{"cx": 225, "cy": 125, "rx": 88, "ry": 55},
  		{"cx": 275, "cy": 275, "rx": 88, "ry": 77}
		];

    const svgEllipses = svgContainer
  		.selectAll("ellipse")
  		.data(ellipses)
  		.enter()
  		.append("ellipse");

    svgEllipses
    	.attr("cx", (d,i) => { return d.cx; })
    	.attr("cy", (d,i) => { return d.cy; })
    	.attr("rx", (d,i) => { return d.rx; })
    	.attr("ry", (d,i) => { return d.ry; });
    

  </script>
</body>

【问题讨论】:

  • stackoverflow.com/questions/52012949/… 重复,只是措辞略有不同。
  • rio 绝对不是。如果您有简单的解决方案,请提供
  • 获取鼠标位置并对所有形状进行多边形点测试。但是,一旦您允许旋转平移倾斜的形状,您就需要做更多的数学运算。
  • 谢谢!你知道我怎样才能确定在给定点上哪个形状“在上面”吗?
  • 如果您遍历形状列表,最后一个具有多边形点的形状

标签: javascript html d3.js svg


【解决方案1】:

这是我对这个问题的解决方案。

主要思想是点击时所有的形状都对鼠标不敏感。还有一个计数器n 是从0 开始的。然后每个形状一个接一个地变得对鼠标敏感。如果鼠标在形状内,计数器n 将加一:n++

希望对你有帮助。

let m = {};// mouse
let shapes = Array.from(document.querySelectorAll(".shape"));

svg.addEventListener("click", e => {  
  let n = 0;// a counter
  m = oMousePos(e);// thr mouse position on click
  shapes.map(s=>{
  // all the shapes are insensitive to the mouse
  shapes.map(_s=>{_s.style.pointerEvents = "none";})
  // this shape is the only one sensitive to the mouse in this moment
  s.style.pointerEvents = "all";
  // detecting if the mouse is inside the shape
  let elmt = document.elementFromPoint(m.x, m.y);
  // if it is and the element has className.baseVal == "shape"
  if(elmt.className.baseVal == "shape"){
    //increase tho counter
    n++
  };
});
  //use the counter
  console.log(n);
});

function oMousePos(evt) {
  return {
    x: evt.clientX,
    y: evt.clientY
  };
}
svg {
  border: 1px solid;
  display: block;
  margin: 0 auto;
}

.shape {
  mix-blend-mode: multiply;
}
<svg id="svg" width="500" height="400" translate="45, 45">
  <ellipse class="shape" cx="145" cy="125" rx="88" ry="20" fill="#aaa"></ellipse>
  <circle class="shape" cx="175" cy="175" r="88" fill="#bbb"></circle>
  <ellipse class="shape" cx="225" cy="125" rx="88" ry="55" fill="#ccc"></ellipse>
  <circle class="shape" cx="275" cy="275" r="77" fill="#ddd"></circle>
</svg>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    相关资源
    最近更新 更多