如何在SVG内部用JavaScript实现元素循环切换(首尾环绕)
你的思路完全可行,这是实现方案
你的类切换思路非常适合SVG内部的交互场景,不需要依赖外部资源,完全符合你的需求。以下是补全后的完整SVG代码,已经实现了首尾环绕的循环切换功能:
<svg id="Object-Panel-Security" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="132" height="72" viewBox="0 0 132 72"> <defs> <style> .cls-txt-security { font-size: 16px; font-family: Arial, Helvetica, sans-serif; text-anchor: middle; } .cls-btn-security { opacity: 0; } a:active > .cls-btn-security { opacity: 1; } .cls-security { visibility: hidden; } .cls-security.on { visibility: visible; } </style> </defs> <g id="Object-Panel-Security-BG"> <rect x="0" width="132" height="72"/> <rect x="4" y="4" width="124" height="64" fill="#dbcad1"/> <polygon points="27 12 27 27 31 27 31 45 27 45 27 60 25.875 60 12 36.125 12 35.875 25.875 12 27 12"/> <polygon points="105 12 105 27 101 27 101 45 105 45 105 60 106.125 60 120 36.125 120 35.875 106.125 12 105 12"/> </g> <text id="Object-Panel-Security-Title" class="cls-txt-security" transform="translate(66 27)">Sec Net</text> <a href="javascript:void(0)" onclick="cycleLeft()" id="Object-Panel-Security-Cycle-Left"> <rect x="12" y="12" width="19" height="48" fill="#bebebe" opacity="0"/> <polygon points="25 18 25 29 29 29 29 43 25 43 25 54 14.5 36 25 18" fill="#fff" class="cls-btn-security"/> </a> <a href="javascript:void(0)" onclick="cycleRight()" id="Object-Panel-Security-Cycle-Right"> <rect x="101" y="12" width="19" height="48" fill="#bebebe" opacity="0"/> <polygon points="107 18 107 29 103 29 103 43 107 43 107 54 117.5 36 107 18" fill="#fff" class="cls-btn-security"/> </a> <g id="Object-Panel-Security-Network-X" class="cls-security net-0"> <rect x="35" y="34" width="62" height="22" fill="#a6a6a6"/> <text class="cls-txt-security" transform="translate(66 51)">X</text> </g> <g id="Object-Panel-Security-Network-1" class="cls-security net-1 on"> <rect x="35" y="34" width="62" height="22" fill="#ca0000"/> <text class="cls-txt-security" transform="translate(66 51)">1</text> </g> <g id="Object-Panel-Security-Network-2" class="cls-security net-2"> <rect x="35" y="34" width="62" height="22" fill="#7cb400"/> <text class="cls-txt-security" transform="translate(66 51)">2</text> </g> <g id="Object-Panel-Security-Network-3" class="cls-security net-3"> <rect x="35" y="34" width="62" height="22" fill="#005eca"/> <text class="cls-txt-security" transform="translate(66 51)">3</text> </g> <g id="Object-Panel-Security-Network-4" class="cls-security net-4"> <rect x="35" y="34" width="62" height="22" fill="#e6ba08"/> <text class="cls-txt-security" transform="translate(66 51)">4</text> </g> <g id="Object-Panel-Security-Network-5" class="cls-security net-5"> <rect x="35" y="34" width="62" height="22" fill="#00a1b9"/> <text class="cls-txt-security" transform="translate(66 51)">5</text> </g> <g id="Object-Panel-Security-Network-6" class="cls-security net-6"> <rect x="35" y="34" width="62" height="22" fill="#ca00b9"/> <text class="cls-txt-security" transform="translate(66 51)">6</text> </g> <g id="Object-Panel-Security-Network-7" class="cls-security net-7"> <rect x="35" y="34" width="62" height="22" fill="#de7f00"/> <text class="cls-txt-security" transform="translate(66 51)">7</text> </g> <g id="Object-Panel-Security-Network-8" class="cls-security net-8"> <rect x="35" y="34" width="62" height="22" fill="#00ca94"/> <text class="cls-txt-security" transform="translate(66 51)">8</text> </g> <script>//<![CDATA[ function cycleLeft() { const items = document.querySelectorAll('.cls-security'); const currentIndex = Array.from(items).findIndex(item => item.classList.contains('on')); const nextIndex = currentIndex === 0 ? items.length - 1 : currentIndex - 1; items[currentIndex].classList.remove('on'); items[nextIndex].classList.add('on'); return false; } function cycleRight() { const items = document.querySelectorAll('.cls-security'); const currentIndex = Array.from(items).findIndex(item => item.classList.contains('on')); const nextIndex = currentIndex === items.length - 1 ? 0 : currentIndex + 1; items[currentIndex].classList.remove('on'); items[nextIndex].classList.add('on'); return false; } //]]></script> </svg>
函数逻辑说明
cycleLeft():获取所有安全分组元素,找到当前激活项的索引,计算上一个元素的索引(如果当前是第一个,就跳转到最后一个),然后切换on类的归属。cycleRight():同理,计算下一个元素的索引(如果当前是最后一个,跳转到第一个),完成类切换。
性能优化替代方案
如果想减少DOM查询次数,提升性能,可以用变量缓存当前索引和元素列表:
let currentIndex = 1; // 对应初始激活的net-1 const items = document.querySelectorAll('.cls-security'); function cycleLeft() { items[currentIndex].classList.remove('on'); currentIndex = currentIndex === 0 ? items.length - 1 : currentIndex - 1; items[currentIndex].classList.add('on'); return false; } function cycleRight() { items[currentIndex].classList.remove('on'); currentIndex = currentIndex === items.length - 1 ? 0 : currentIndex + 1; items[currentIndex].classList.add('on'); return false; }
这种方式只在初始化时查询一次DOM元素,后续切换直接操作缓存的变量和列表。
内容的提问来源于stack exchange,提问作者Lawton
相关产品推荐
相关产品推荐

