简单的svg线性动画

465 阅读1分钟

要实现的效果

让每条线都动起来,一直循环,每次循环的线条的长度和速度都随机。

所使用到的属性和api

  • svg中的属性 stroke-dasharray 设置间距
  • svg中的属性 stroke-dashoffset 设置偏移量
  • window中的api window.requestAnimationFrame() 运行动画

通过Adobe Illustrator(Ai)生成的svg代码

<svg version="1.1" id="svg-line" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1920 1080" style="enable-background:new 0 0 1920 1080;" xml:space="preserve">
    <g class="st0">
        <path class="st1" d="M1681.2,3v417.4c0,8.5-3.4,16.6-9.4,22.6l-2.9,2.9c-6,6-9.4,14.2-9.4,22.7l1,611.5" />
        <path class="st1" d="M1920.2,488.6h-311.4c-22,0-43.3,7.2-60.8,20.6l-181.8,139.2c-17.5,13.4-38.8,20.6-60.8,20.6H94.7 c-26.5,0-52-10.5-70.7-29.3l-50.3-50.3" />
        <path class="st1" d="M1490.2,553.5l-325.7-297.7c-18.4-16.8-42.5-26.2-67.5-26.2H232.4c-55.2,0-100-44.8-100-100V3" />
        <path class="st1" d="M1659.5,682.1l-228,208.4c-18.4,16.8-42.5,26.2-67.5,26.2H667.4c-55.2,0-100,44.8-100,100v126.7" />
        <line class="st1" x1="1246.1" y1="553.5" x2="1490.1" y2="553.5" />          
        <path class="st1" d="M1276.3-11v212.6c0,26.5,10.5,52,29.3,70.7l304.9,304.9c18.8,18.8,44.2,29.3,70.7,29.3h243.1" />
        <path class="st1" d="M1920.2,278.2l-163,105.9c-28.4,18.4-45.5,50-45.5,83.9v612" />
        <line class="st1" x1="1920.2" y1="833.7" x2="1711.1" y2="624.6" />
        <line class="st1" x1="1952.3" y1="801.6" x2="1757.1" y2="606.5" />
    </g>
    <g>
        <path class="st1 move move1" d="M1681.2,3v417.4c0,8.5-3.4,16.6-9.4,22.6l-2.9,2.9c-6,6-9.4,14.2-9.4,22.7l1,611.5" />
        <path class="st1 move" d="M1920.2,488.6h-311.4c-22,0-43.3,7.2-60.8,20.6l-181.8,139.2c-17.5,13.4-38.8,20.6-60.8,20.6H94.7 c-26.5,0-52-10.5-70.7-29.3l-50.3-50.3" />
        <path class="st1 move" d="M1490.2,553.5l-325.7-297.7c-18.4-16.8-42.5-26.2-67.5-26.2H232.4c-55.2,0-100-44.8-100-100V3" />
        <path class="st1 move" d="M1659.5,682.1l-228,208.4c-18.4,16.8-42.5,26.2-67.5,26.2H667.4c-55.2,0-100,44.8-100,100v126.7" />
        <line class="st1 move" x1="1246.1" y1="553.5" x2="1490.1" y2="553.5" />
        <path class="st1 move" d="M1276.3-11v212.6c0,26.5,10.5,52,29.3,70.7l304.9,304.9c18.8,18.8,44.2,29.3,70.7,29.3h243.1" /><path class="st1 move" d="M1920.2,278.2l-163,105.9c-28.4,18.4-45.5,50-45.5,83.9v612" />
        <line class="st1 move" x1="1920.2" y1="833.7" x2="1711.1" y2="624.6" />
        <line class="st1 move" x1="1952.3" y1="801.6" x2="1757.1" y2="606.5" />
    </g>
</svg>

一丢丢css代码

<style>
    body {
        background-color: #000000;
    }

    .st0 {
        opacity: 0.2;
    }

    .st1 {
        fill: none;
        stroke: #FFFFFF;
        stroke-width: 2;
        stroke-miterlimit: 10;
    }
</style>

js正文

首先获取所有的线条

let moveList = document.querySelectorAll('#svg-line .move');

然后循环遍历获取每个线条的长度 通过使用 svg提供的方法 getTotalLength() 获取目标长度

moveList.forEach((item, index) => {
    const svgTotal = item.getTotalLength();
    svgAn(item, svgTotal);
})

编写辅助函数实现动画

/**
 * @param {DOM} item 当前线条
 * @param {Number} svgTotal 当前线条长度
*/
function svgAn(item, svgTotal) {
    // 随机生成每次运行的距离(运行速度)
    let speedNum = Math.floor(Math.random() * (10 - 5) + 5);
    // 随机生成线条的长度
    let lengthNum = Math.floor(Math.random() * (180 - 60) + 60);

    // 设置间距
    item.style.strokeDasharray = `${lengthNum}px, ${svgTotal}px`;
    // 设置偏移量
    item.style.strokeDashoffset = lengthNum;
    // 运行动画
    window.requestAnimationFrame(svgRun);

    // 总共要运行的距离
    let total = lengthNum;
    function svgRun() {
        if (total > -svgTotal) {
            window.requestAnimationFrame(svgRun);
            total -= speedNum;
            item.style.strokeDashoffset = total;
        } else {
            total = svgTotal;
            svgAn(item, svgTotal);
        }
    }
}