动态SVG交互问题:JavaScript弹窗功能为何无法正常运行?
问题修复方案
核心问题
SVG属于XML命名空间,无法直接解析HTML的<div>标签,导致你定义的mypopup元素无法被浏览器正确渲染和获取,这是弹窗功能失效的根本原因。此外,原代码将事件绑定在父容器上,无法针对单个柱状条展示个性化内容。
修复后完整代码
<svg id="iamsvg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080"> <defs> <style> .zahlen { font-family:OpenSans-Regular, "Open Sans"; font-size:50px; stroke:#000000; fill:#000000; } .balken { stroke-width:.5px; stroke:#5e5eee; fill:#5e5eee; } .balken:hover { stroke:#e70e7e; fill:#e70e7e; } .linien { stroke:#aeb6e5; stroke-miterlimit:10; fill:none; } #mypopup { width: 400px; padding: 20px; font-family: Arial, sans-serif; font-size: 10pt; background-color: white; border-radius: 6px; position: absolute; display: none; box-shadow: 0 2px 8px rgba(0,0,0,0.15); z-index: 9999; } #mypopup::before { content: ""; width: 12px; height: 12px; transform: rotate(45deg); background-color: white; position: absolute; left: -6px; top: 68px; } </style> </defs><g> <line class="linien" x1="186.58" y1="1020.62" x2="1858.99" y2="1020.62"/> <line class="linien" x1="186.58" y1="1020.62" x2="186.58" y2="998.37"/></g> <g><g> <text class="zahlen" transform="translate(17.5 901.7)"><tspan x="0" y="0">10000</tspan></text> <text class="zahlen" transform="translate(17.5 753.37)"><tspan x="0" y="0">20000</tspan></text> <text class="zahlen" transform="translate(17.5 605.05)"><tspan x="0" y="0">30000</tspan></text> <text class="zahlen" transform="translate(17.5 456.72)"><tspan x="0" y="0">40000</tspan></text> <text class="zahlen" transform="translate(17.5 308.39)"><tspan x="0" y="0">50000</tspan></text> <text class="zahlen" transform="translate(17.5 160.07)"><tspan x="0" y="0">60000</tspan></text> </g> <line class="linien" x1="186.58" y1="1020.62" x2="186.58" y2="130.67"/><g> <line class="linien" x1="186.58" y1="1020.62" x2="228.39" y2="1020.62"/> <line class="linien" x1="186.58" y1="872.3" x2="1859.24" y2="872.3"/> <line class="linien" x1="186.58" y1="723.97" x2="1859.24" y2="723.97"/> <line class="linien" x1="186.58" y1="575.65" x2="1859.24" y2="575.65"/> <line class="linien" x1="186.58" y1="427.32" x2="1859.24" y2="427.32"/> <line class="linien" x1="186.58" y1="279" x2="1859.24" y2="279"/> <line class="linien" x1="186.58" y1="130.67" x2="1859.24" y2="130.67"/></g></g> <g id="myicon" pointer-events="all"> <rect class="balken" x="201.21" y="572.25" width="75.26" height="448.37" data-title="柱状条1" data-desc="数值:40000,对应图表底部到顶部的高度"/> <rect class="balken" x="305.74" y="350.95" width="75.26" height="669.67" data-title="柱状条2" data-desc="数值:55000,为所有柱状条中最高"/> <rect class="balken" x="410.26" y="834" width="75.26" height="186.62" data-title="柱状条3" data-desc="数值:15000,属于较低水平"/> <rect class="balken" x="514.79" y="901.44" width="75.26" height="119.18" data-title="柱状条4" data-desc="数值:10000,接近最低刻度"/> <rect class="balken" x="619.31" y="982.58" width="75.26" height="38.05" data-title="柱状条5" data-desc="数值:3000,为所有柱状条中最低"/> <rect class="balken" x="723.84" y="919.9" width="75.26" height="100.73" data-title="柱状条6" data-desc="数值:9000,略高于最低刻度"/> <rect class="balken" x="828.37" y="766.11" width="75.26" height="254.51" data-title="柱状条7" data-desc="数值:20000,处于中等水平"/> <rect class="balken" x="932.89" y="951.99" width="75.26" height="68.63" data-title="柱状条8" data-desc="数值:6000,偏低水平"/> <rect class="balken" x="1037.42" y="603.16" width="75.26" height="417.46" data-title="柱状条9" data-desc="数值:38000,较高水平"/> <rect class="balken" x="1141.95" y="214.64" width="75.26" height="805.98" data-title="柱状条10" data-desc="数值:60000,达到最高刻度"/> <rect class="balken" x="1246.47" y="839.68" width="75.26" height="180.94" data-title="柱状条11" data-desc="数值:14500,较低水平"/> <rect class="balken" x="1351" y="973.31" width="75.26" height="47.32" data-title="柱状条12" data-desc="数值:4000,接近最低值"/> <rect class="balken" x="1455.52" y="852.61" width="75.26" height="168.01" data-title="柱状条13" data-desc="数值:13500,较低水平"/> <rect class="balken" x="1560.05" y="920.3" width="75.26" height="100.33" data-title="柱状条14" data-desc="数值:9000,略高于最低刻度"/> <rect class="balken" x="1664.58" y="859.22" width="75.26" height="161.41" data-title="柱状条15" data-desc="数值:13000,较低水平"/> <rect class="balken" x="1769.1" y="946.4" width="75.26" height="74.22" data-title="柱状条16" data-desc="数值:6500,偏低水平"/> </g> <script type="application/javascript"> <![CDATA[ // 动态创建弹窗并添加到HTML body function createPopup() { const popup = document.createElement('div'); popup.id = 'mypopup'; popup.innerHTML = ` <h3 id="popup-title">Popup title</h3> <p id="popup-desc">Lorem ipsum dolor sit amet...</p> `; window.document.body.appendChild(popup); return popup; } let mypopup = window.document.getElementById('mypopup'); if (!mypopup) { mypopup = createPopup(); } const bars = document.querySelectorAll('.balken'); // 为每个柱状条绑定悬停事件 bars.forEach(bar => { bar.addEventListener('mouseover', showPopup); bar.addEventListener('mouseout', hidePopup); }); function showPopup(evt) { const bar = evt.target; const barPos = bar.getBoundingClientRect(); // 定位弹窗到柱状条右侧 mypopup.style.left = (barPos.right + 20) + "px"; mypopup.style.top = (window.scrollY + barPos.top - 60) + "px"; // 替换弹窗内容为当前柱状条的自定义数据 document.getElementById('popup-title').textContent = bar.dataset.title; document.getElementById('popup-desc').textContent = bar.dataset.desc; mypopup.style.display = "block"; } function hidePopup(evt) { mypopup.style.display = "none"; } ]]> </script> </svg>
关键修改说明
- 移除SVG内的HTML标签:通过JavaScript动态创建弹窗元素并插入到浏览器的HTML body中,避开SVG无法解析HTML标签的限制。
- 单个柱状条绑定事件:将事件从父容器移到每个
<rect>元素上,实现精准的悬停触发。 - 自定义数据属性:给每个柱状条添加
data-title和data-desc属性,支持展示个性化的弹窗内容。 - 优化弹窗样式:增加阴影效果提升视觉层级,确保弹窗不会被SVG内容遮挡。
内容的提问来源于stack exchange,提问作者spiderkitty
相关产品推荐
相关产品推荐

