【问题标题】:How do I select all SVG elements within a rectangle with javascript如何使用javascript选择矩形内的所有SVG元素
【发布时间】:2017-02-06 15:47:22
【问题描述】:

我编写了一个通用的 javascript 库,可以创建各种类型的 SVG 图形(条形图、绘图、饼图等)。我也有来自this post 的选框选择代码,效果很好。

所以现在我的 SVG 中有 x1、y1、x2、y2 坐标,我正在寻找一种简单的方法来选择在该选择中至少有 1 个像素的所有 SVG 元素。

对于只有点的绘图,这很容易实现,但我正在寻找一种适用于矩形、椭圆和路径的简单通用解决方案。

【问题讨论】:

  • 邮政编码以便更好地理解问题/问题。
  • 我已经更新了问题,以便更具体地了解我所拥有的参数。我的 SVG 中有 topLeft 和 bottomRight 坐标,我正在寻找这些边界内(或部分内)的所有元素。
  • 你可以得到每个形状的边界框(getBBox),看看它是否在你的选择范围内,但这并不是万无一失的。
  • 我现在不能测试,但我可以给你一个意见。您已经拥有 X1、X2、Y1 和 Y2。现在使用 $('svg path') 元素的 position().top 和 position().left 属性,您可以找到它们的 X'1 和 Y'1。现在添加宽度和高度,您也有了 X'2 和 Y'2。最后一件事是将 Xs、Ys 与 X 和 Y 进行比较。我希望这行得通。

标签: javascript svg


【解决方案1】:

这实际上只是部分答案,因为我可以向您展示如何在简单的情况下实现您的目标,但不是在您提出的所有情况下。

一个简单的解决方案是使用svgSvgElement.getIntersectionList。下面的代码演示了这一点。它显示了如何确定三个彩色三角形中的哪一个被选择矩形“击中”。但是请注意,它不是确定哪些 元素 与选择矩形重叠,而是确定哪些 元素边界框 与选择矩形重叠。因此,下面的蓝色三角形被认为与预期重叠,红色三角形被认为没有如预期重叠,但绿色三角形 被认为重叠不是因为三角形本身重叠,而是因为虚线的绿色它周围的矩形确实如此。要真正确定哪个形状本身与矩形重叠更复杂,并且自古以来就一直是很多麻烦的根源。

const qs = (selctr) => document.querySelector(selctr);

const svg   = qs('svg'   );
const green = qs('#green');
const blue  = qs('#blue' );
const red   = qs('#red'  );

const r = svg.createSVGRect();
r.x = 10;
r.y = 10;
r.width = 100;
r.height = 40;
const nodeList = svg.getIntersectionList(r, null);
const arr = Array.from(nodeList);
console.log('The following triangles "overlap" the black rectangle:');
console.log('green:', arr.indexOf(green) >= 0, '(?!)');
console.log('blue: ', arr.indexOf(blue ) >= 0);
console.log('red:  ', arr.indexOf(red  ) >= 0);
<svg>
  <g fill="none" stroke-width="1" stroke-dasharray="2" opacity="0.5">
    <rect x="25" y="10" width="100" height="40" stroke="black"/>
    <rect x="10" y="40" width="20" height="40" stroke="green" transform="translate(0)"/>
    <rect x="10" y="40" width="20" height="40" stroke="blue"  transform="translate(50)"/>
    <rect x="10" y="40" width="20" height="40" stroke="red"   transform="translate(120)"/>
  </g>
  <g opacity="0.5">
    <path id="green" fill="green" d="M10,40 L30,60 20,80" transform="translate(0)"/>
    <path id="blue"  fill="blue"  d="M10,40 L30,60 20,80" transform="translate(50)"/>
    <path id="red"   fill="red"   d="M10,40 L30,60 20,80" transform="translate(120)"/>
  </g>
</svg>

suggested that you could use document.elementFromPoint 一直是解决此问题的一种方法。例如,您可以测试选择矩形的四个角点或中心点中的任何一个是否落在您的形状内。但是请注意,即使是这种方法也会遗漏以下内容:

<svg>
  <rect x="10" y="10" width="50" height="50" fill="none" stroke="black" stroke-width="1" stroke-dasharray="2" opacity="0.5"/>
  <path fill="red" opacity="0.5" d="M45,30 L80,0 90,70"/>
</svg>

【讨论】:

  • 太棒了,即使不完美,这些都是我一直在寻找的功能!
  • 不要使用svg.getIntersectionList 函数! 我已将SVGRect (r) 更改为r.x = 25,现在我在IE10 和新Opera 中得到了完全不同的结果。在 Opera 中这是非常错误的:对于三角形以及所有形状和路径,它们都采用矩形。在 IE 中是正确的:三角形是三角形,路径 - 路径,只有 rects - rects。有关演示,请参阅我的 Codepen。请参阅 bugs report list 了解 Chrome、WebKit 和 FF(完全缺少支持)。
  • 为什么要报警,@Bharata?答案已经表明它采用边界框而不是实际形状。答案(和上一版)比您的评论更早(2017 年 vs 2019 年)。并且兼容性列表可见caniuse.com/?search=getIntersectionList
猜你喜欢
  • 1970-01-01
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多