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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:24:51