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
相关产品推荐
相关产品推荐

