0

我是 Web 开发和 svg 相关主题的初学者。

我认为这对你的 svg 专家来说应该很容易,但我现在为此苦苦挣扎了一段时间。我在这个主题上找到的所有资源似乎都不适用于我相当简单的目标。

我的应用程序应该在 Chrome 浏览器中运行。

DOM 结构如下:

<div>
    <svg>
        <g>
            <circle></circle>
        </g>
    <svg>
</div>

虽然里面可能有更多的 svg 标签或嵌套的 svg 元素,但这是一般设置。

目标:

我想单击某处并找到位于我单击位置的 svg 子元素(例如圆圈)。我想到的基本功能是:

document.elementFromPoint(x, y)

问题:

1)所有元素都可以进行转换,例如应用于它们的平移、缩放和旋转,这使事情变得复杂。

2)我只希望能够单击元素,它们是 svg 节点的子节点。

我的一些尝试:

https://jsfiddle.net/a6uLn9cn/3/

我试图将“pointer-events:none”放在 DIV 和/或 SVG 节点上。这样,我就可以避免这些是“可点击的”。但是这里有两个问题:我需要 SVG 节点上的指针事件,因为它需要被缩放和平移,以及例如圆圈上的点击事件以某种方式“冒泡”到 DIV。

另一种确保 svg 节点的子节点是“可点击”的方法是检查 element.ownerSVGDocument 中找到的元素。如果它为 null 或未定义,我知道找到的元素不是 svg 子元素。

为了解决实际单击已转换的元素(通过其自身或通过其父元素)的问题,我尝试使用 element.getBoundingClientRect() ,它为我提供了元素的周围矩形。有了这个,我做了一个函数来确定点击是否在矩形周围的元素内:

e 是点击事件,elem 是 document.elementFromPoint() 收到的找到的元素

function clickIsInside(e, elem){
    var clickX = e.clientX;
    var clickY = e.clientY;

    var boxLeft = elem.getBoundingClientRect().left;
    var boxRight = elem.getBoundingClientRect().right;
    var boxTop = elem.getBoundingClientRect().top;
    var boxBottom = elem.getBoundingClientRect().bottom;

    if(clickX >= boxLeft && clickX <= boxRight && clickY >= boxTop && clickY <= boxBottom){
        return true;
    } else {
        return false;
    }
}

但是在我的 jsfiddle 中,您将无法“单击”例如其 boundingClientRect 最右侧的路径,如果您想象 boundingClientRect 在哪里,这对我来说毫无意义。

此外,如果我在添加圆圈后将路径添加到 DOM,我将无法再单击圆圈,而只能单击路径。我完全明白为什么,但如果我需要同时点击两者怎么办?

我不确定我是否能够在这里解决我的麻烦,但我会非常感谢你们可能给我的任何意见。非常感谢。

4

1 回答 1

1

我发现我在问题中所做的大部分事情都只是使事情复杂化。解决方案只是检查找到的元素是否有任何 ownerSVGDElement,如果没有,则不发送 click 事件。对元素应用转换似乎没有任何问题,因为 document.elementFromPoint() 足够强大,可以找到转换后的元素。这个问题现在似乎没用了,所以我回答并关闭它只是因为任何人都会遇到或尝试像我一样无脑的事情的罕见情况。

编辑:似乎我只能在 2 天内接受这个作为答案。

于 2017-05-30T14:03:33.183 回答