You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SVG树形结构点击父元素仅隐藏子元素功能实现问题

修复SVG树形交互结构的显示/隐藏逻辑

问题核心

原代码存在三个关键问题:所有<g>元素平级无嵌套,无法区分父子关系;place函数逻辑错误,会批量修改非根元素的显示状态;点击事件会冒泡到父元素,导致误触发。

修复后的完整代码

<style>
.hidden {
  display: none;
}
</style>

<svg width="1250" height="1250">
  <rect x="0" y="0" width="1250" height="1250" style="fill:White;stroke:black;stroke-width:5" />
  <defs>
    <marker id="arrow" viewBox="0 0 15 15" refX="8" refY="8" markerWidth="10" markerHeight="10" orient="auto-start-reverse">
      <path d="M 0 0 L 15 8 L 0 15 z" />
    </marker>
  </defs>
  <!-- 嵌套结构明确父子层级 -->
  <g id="A" onclick="place(event, this)">
    <rect x="100" y="100" width="100" height="50" stroke="black" stroke-width="1" fill="white" rx="10"></rect>
    <text x="150" y="125" alignment-baseline="middle" font-size="12" stroke-width="0.5" stroke="#000" font-family="Arial, Helvetica, sans-serif" text-anchor="middle">Tech Stack</text>
    
    <g id="AA" onclick="place(event, this)">
      <rect x="250" y="150" width="100" height="50" stroke="black" stroke-width="1" fill="white" rx="10"></rect>
      <text x="300" y="175" alignment-baseline="middle" font-size="12" stroke-width="0.5" stroke="#000" font-family="Arial, Helvetica, sans-serif" text-anchor="middle">Frontend</text>
      <line x1="200" y1="125" x2="225" y2="125" stroke="black"/> 
      <line x1="225" y1="125" x2="225" y2="175" stroke="black"/>
      <line x1="225" y1="175" x2="245" y2="175" stroke="black" marker-end="url(#arrow)" />
      
      <g id="AAA" onclick="place(event, this)">
        <line x1="350" y1="175" x2="375" y2="175" stroke="black"/>
        <line x1="375" y1="175" x2="375" y2="225" stroke="black"/>
        <line x1="375" y1="225" x2="395" y2="225" stroke="black" marker-end="url(#arrow)" />
        <rect x="400" y="200" width="100" height="50" stroke="black" stroke-width="1" fill="white" rx="10"></rect>
        <text x="450" y="225" alignment-baseline="middle" font-size="12" stroke-width="0.5" stroke="#000" font-family="Arial, Helvetica, sans-serif" text-anchor="middle">React</text>
      </g>
    </g>
  </g>
</svg>
<br/>
<button type="button" onclick="reset()">Reset</button>

<script>
function place(event, element) {
  // 阻止事件冒泡,避免触发父元素点击事件
  event.stopPropagation();
  
  // 获取当前元素的直接子级g元素
  const childGs = element.querySelectorAll(':scope > g');
  
  // 切换子元素的显示/隐藏状态
  childGs.forEach(g => {
    g.classList.toggle('hidden');
  });
}

function reset() {
  document.querySelectorAll("g").forEach(g => g.classList.remove("hidden"));
}
</script>

关键修改说明

  • 嵌套DOM结构:将子元素<g>嵌套到父元素内部,明确父子层级,方便精准定位子元素
  • 阻止事件冒泡:通过event.stopPropagation()避免点击子元素时触发父元素的点击逻辑
  • 重构place函数:仅针对点击元素的直接子级<g>元素进行显示状态切换,不再批量修改所有元素
  • 简化逻辑:使用classList.toggle()替代手动判断添加/移除类,代码更简洁

内容的提问来源于stack exchange,提问作者Sun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 10:25:55