阅读 187
SVG路径动画是如何实现的?

SVG路径动画是如何实现的?

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

实现步骤

  • 引入svg.js(一个使用jssvg的库),绘制一个折线图
    image.png

     <!DOCTYPE html> 
     <html> 
     <head> 
         <title>SVG.js</title> 
         <script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.0/dist/svg.min.js"></script> 
         <style>
            #drawing {
              width: 1000px;
              height: 500px;
              background: #399979;
              margin-left: 100px;
              margin-top: 100px;
            }
         </style>
     </head> 
         <body> 
             <div id="drawing"></div> 
         </body> 
     </html>
     
     <script>
         let draw = SVG().addTo('#drawing').size('100%', '100%')
         draw.viewbox('0 0 100 100')
         let path = draw.path('M10 10 L40 10 40 20 80 20').fill('none').attr({stroke: '#cfcfcf', 'stroke-width': 0.3})
     </script>
    复制代码
  • 使用stroke-dasharray属性,值分别为2、6效果

        // js
        path.attr({'stroke-dasharray': 2})
    复制代码

    image.png

        // js
        path.attr({'stroke-dasharray': 6})
    复制代码

    image.png

  • 获取path长度,如果stroke-dasharray不断增加,直到刚好等于path长度,整个图形被这一段虚线覆盖,效果相当于初始化图形一样。但是实际上只是虚线的一段。此时再结合stroke-dashoffset属性配合CSS动画,即可添加动画效果

    • 这里stroke-dashoffset的意义是:dash模式到路径开始的距离。初始化值如果大于0,可以理解为以绘制好的dash模式的path包括可见和不可见部分为参照,路径往右移动了一定距离(所以,此时添加keyframe,值从大于0变为0时,路径就像自我描绘一样的动画效果)。如果stroke-dashoffset小于0,路径往左移动了一定距离。这个决定了动画效果的运动轨迹方向。
        <style>
            .path {
                animation: drawPath 3s infinite;
            }
        </style>
        <script>
            path.addClass("path")
            let pathLength = path.length()
            path.attr({'stroke-dasharray': pathLength, 'stroke-dashoffset': pathLength})
            var keyFrames = 
            `@keyframes drawPath {
              0% {
                stroke-dashoffset: ${pathLength}
              }
              100% {
                stroke-dashoffset: 0;
              }
            }`
          createKeyframes(keyFrames)
          // 动态添加style方法
          const getStyleElement = () => {
          let style = document.querySelector('style#dynamic-keyframes')
              if (!style) {
                style = document.createElement('style')
                style.id = 'dynamic-keyframes'
                style.type = 'text/css'
                document.getElementsByTagName('head')[0].appendChild(style)
              }
             return style
          }
    
          const createKeyframes = (keyframeString) => {
            let style = getStyleElement()
            style.insertAdjacentHTML('beforeend', keyframeString)
          }
        </scritp>
    复制代码

总结

  • 可以直接使用现成的svgcss实现类似动画效果。使用js是为了可以精确计算path的长度,动态设置stroke-dashoffsetstroke-dasharray的值,因为实际场景中,path长度不固定
  • stroke-dashoffset的运动轨迹的方向由初始值决定
  • 路径动画实际上是pathdash模式下,偏移量offset的运动过程

参考

MDN-SVG
svg.js
How SVG Line Animation Works

文章分类
前端
文章标签