Javascript 如何捕获命中viewbox的SVG单击事件,而不是其上的元素?

Javascript 如何捕获命中viewbox的SVG单击事件,而不是其上的元素?,javascript,html,svg,Javascript,Html,Svg,我有一个具有各种路径的SVG文件,它使用object标记嵌入到HTML页面中。Javascript用于为每个路径提供一些交互性—单击该路径时,将显示工具提示rect。这就是它看起来的样子: 我希望当有人在工具提示关联的路径之外单击时,工具提示消失,这是通过向每个路径添加这样的事件侦听器来实现的: path.addEventListener("click", function(event){ if (!isTipShown()){ createTooltip()

我有一个具有各种路径的SVG文件,它使用
object
标记嵌入到HTML页面中。Javascript用于为每个路径提供一些交互性—单击该路径时,将显示工具提示
rect
。这就是它看起来的样子:

我希望当有人在工具提示关联的路径之外单击时,工具提示消失,这是通过向每个路径添加这样的事件侦听器来实现的:

path.addEventListener("click", function(event){
    if (!isTipShown()){
        createTooltip()
    }
    else{
        hideTooltip()
    }
})

isTipShown
createTooltip
hideTooltip
是检查SVG DOM并相应修改它的函数

这是可行的,但如果单击指向路径本身之间的空白区域,则会失败,因为没有对象可以捕捉它

可以选择什么方法来实现这些功能?

我现在的想法是:

  • 创建一个覆盖整个视口的透明矩形,并将其用作单击目标。如何确保矩形位于所有内容的底部
  • 整个HTML文档的单击处理程序会起作用,但仅当用户在视口之外单击时

解决方案是确保矩形位于路径下方,就像它是底层一样

,但可以通过确保
rect
在SVG DOM中的所有元素之前,并且所有后续元素都将以可视方式放置在其顶部来实现:

<rect x="0" y="0" width="30" height="30" fill="purple"/>
<rect x="20" y="5" width="30" height="30" fill="blue"/>
<rect x="40" y="10" width="30" height="30" fill="green"/>
<rect x="60" y="15" width="30" height="30" fill="yellow"/>
<rect x="80" y="20" width="30" height="30" fill="red"/>
svgDoc.rootElement.insertBefore(rect,svgDoc.rootElement.children[0])
使其成为第一个,因为它插入到索引0处的当前子级之前。

形状上的工具提示不是我的SVG! 按下svg时如何最好地删除工具提示?
他们认为我解决问题的方法是:

  • 工具提示上的ID
  • 使用ID修改现有工具提示
  • 在其他任何位置按下时删除ID为的工具提示
  • 通过重复使用工具提示,页面上一次只能有一个工具提示。
    删除工具提示(而不是删除)可以在显示新路径时再次重用相同的工具提示

    以下是一个例子:

    document.addEventListener(“DOMContentLoaded”,function()){
    var pathRed=document.getElementById(“红色”);
    var pathrange=document.getElementById(“橙色”);
    var pathBlue=document.getElementById(“蓝色”);
    变量路径=[pathRed,PathRange,pathBlue];
    var toolTip=document.createElement(“div”);
    toolTip.id=“toolTip”;
    var svg=document.getElementById(“框”);
    显示的var=假;
    path.forEach(函数(元素){
    元素。addEventListener(“单击”),函数(事件){
    如果(显示==错误){
    toolTip.innerText=element.id;
    toolTip.style.top=(event.pageY)+“px”;
    toolTip.style.left=(event.pageX)+“px”;
    document.body.appendChild(工具提示);
    显示=正确;
    //仅单击路径
    event.stopPropagation();
    }否则{
    移除工具头();
    }
    });
    });
    addEventListener(“单击”),函数(事件){
    移除工具头();
    event.preventDefault();
    });
    函数removeToolTip(){
    显示=假;
    if(document.body.contains(工具提示)){
    document.body.removeChild(工具提示);
    }
    }
    });
    
    #工具提示{
    位置:绝对位置;
    背景色:#00000099;
    填充:2px;
    边界半径:2px;
    颜色:白色;
    字体大小:20px;
    }
    点击框!
    
    您可以对文档使用单击处理程序并检查event.currentTarget,如果单击目标是路径,则不要执行任何操作,否则隐藏工具提示。我会执行rect操作。不确定你所说的“一切尽在最底层”是什么意思,你所描述的方法是有效的,但是当点击进入路径之间的空白处时它就会失败(因为没有元素接收到点击事件)。Robert,将其视为层-透明矩形放置在所有东西的顶部,因此所有单击都指向它(而不是它下面的路径)。你看不到它,因为它是透明的,但它仍然可以点击。
        function createBackgroundRectangle(svgDoc){
            var rect = svgDoc.createElementNS("http://www.w3.org/2000/svg", 'rect')
            rect.setAttributeNS(null, 'height', 500)
            rect.setAttributeNS(null, 'width', 900)
            rect.setAttributeNS(null, 'id', 'pseudo-background')
            rect.setAttributeNS(null, 'x', 0)
            rect.setAttributeNS(null, 'y', 0)
            // the opacity is set to 0, so it doesn't get in the way visually. For debugging
            // purposes, you can change it to another value and see the actual rectangle
            rect.setAttributeNS(null, 'style', 'opacity:0;fill:#ffd42a;fill-opacity:1;')
            svgDoc.rootElement.insertBefore(rect, svgDoc.rootElement.children[0])
        }