纯 svg 实现文字路径动画

效果

纯 svg 实现文字路径动画

文字转路径

要实现该效果的第一步是需要把文字转化为路径,在 svg 中文字可以使用 text 标签绘制,文字转路径需要把 text 绘制的内容转化为使用 path 标签来绘制。

大部分的矢量图形编辑器都具有文字转路径的功能,我是使用 Adobe Illustrator 这款软件进行转化的。使用也很简单,先通过文字工具(T)绘制出掘金两个字,然后在文字上右键点击创建轮廓就可以了。

默认会创建出两个 path 元素,我故意在金字上面右键,然后点击释放复合路径,这样一个 path 路径就会释放为 4 个 path 路径,之后稍微调整一下 path 元素的顺序,就可以按照文字的绘制顺序绘制路径了。

之后把获取的路径导出,然后在 html 文件中使用

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=750px, user-scalable=yes, initial-scale=1.0, maximum-scale=2.0, minimum-scale=0.5"
    />
    <title>index</title>
    <style>
      body {
        margin: 0;
      }
      .svg {
        margin: auto;
        display: block;
      }
      path {
        fill: none;
        stroke-width: 1;
        stroke: #1e80ff;
      }
    </style>
  </head>

  <body>
    <div id="container" class="container">
      <svg class="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" id="图层_1" x="0px" y="0px" width="800px" height="800px" viewBox="0 0 800 800" enable-background="new 0 0 800 800">
        <path class="jue" d="M166.863,320.827c0-33.058-0.395-59.162-1.148-78.311l26.414,14.357l-10.336,7.831v56.123h6.891l11.484-13.052  l18.375,20.883h-36.75v62.649l32.156-14.357l2.297,3.916l-34.453,22.188v103.11c0,13.908-7.662,25.227-22.969,33.935  c0-10.441-10.73-20.026-32.156-28.714v-5.221c16.078,2.61,26.791,3.915,32.156,3.915c5.348,0,8.039-3.467,8.039-10.441V412.19  c-20.672,11.318-32.551,20.026-35.602,26.104l-14.93-22.188c8.416-1.734,25.266-7.832,50.531-18.273v-69.175h-28.711l-10.336,2.61  l-9.188-10.441H166.863z M182.941,540.099c15.307-25.227,26.02-52.207,32.156-80.922c6.119-28.714,9.367-59.814,9.762-93.321  c0.377-33.486,0.18-68.951-0.574-106.373l17.227,11.747h103.359l10.336-11.747l16.078,18.272l-9.188,6.526  c0,19.149,0.377,35.24,1.148,48.292l-16.078,7.832v-13.052H239.215c3.051,99.195-14.553,170.98-52.828,215.356L182.941,540.099z   M239.215,279.061v40.461h107.953v-40.461H239.215z M248.402,512.689c0-32.181-0.395-55.246-1.148-69.175l21.82,13.052l-6.891,7.831  v52.208h39.047v-92.668h-32.156l-8.039,7.831l-12.633-14.357l6.891-6.526c0-23.494-0.395-42.194-1.148-56.123l21.82,13.052  l-6.891,7.831v40.462h32.156c0-41.767-0.395-69.604-1.148-83.533l22.969,11.747l-8.039,7.831v63.955h31.008  c0-26.104-0.395-45.683-1.148-58.734l21.82,11.747l-6.891,7.831c0,21.76,0.377,39.157,1.148,52.208l-14.93,7.831v-13.052h-31.008  v92.668h40.195c0-28.714-0.395-52.208-1.148-70.48l22.969,13.052l-8.039,6.526c0,35.688,0.377,58.733,1.148,69.175l-14.93,7.831  v-18.272h-93.023l-8.039,10.441l-13.781-14.356L248.402,512.689z"></path>
        <path d="M548.145,267.314l10.336-6.526l-24.117-18.272c-27.563,73.09-67.758,123.993-120.586,152.707l1.148,5.221  c57.422-25.227,100.291-67.87,128.625-127.909c27.563,57.428,66.215,96.584,115.992,117.467c3.822-11.298,11.09-17.396,21.82-18.273  v-5.221C628.535,359.554,584.123,326.496,548.145,267.314z">
        </path>
        <path d="M643.465,527.047h-93.023V439.6h101.063l-19.523-23.493l-13.781,15.662h-67.758v-48.293h66.609l-18.375-22.188  l-12.633,14.357H476.941l10.336,11.747c8.416-2.61,17.604-3.916,27.563-3.916h19.523v48.293h-91.875l10.336,11.746  c8.416-2.61,17.604-3.915,27.563-3.915h53.977v87.447H414.926l10.336,11.747c8.416-2.61,17.604-3.916,27.563-3.916h226.242 l-20.672-24.799L643.465,527.047z">
        </path>
        <path d="M499.91,523.132c1.525,0,3.625-2.183,6.316-6.526c2.674-4.344,4.02-9.564,4.02-15.662c0-3.467-0.969-8.035-2.871-13.705  c-1.92-5.648-15.127-16.742-39.621-33.282l-3.445,3.916c14.535,20.026,23.723,36.994,27.563,50.902  C494.168,518.339,496.842,523.132,499.91,523.132z">
        </path>
        <path d="M626.238,468.313l-25.266-19.578c-2.827,12.834-15.038,43.979-29.551,77.483c0.562,0.577,3.656-4.922,4.706-5.9  c11.93-15.26,27.469-30.859,37.478-46.784L626.238,468.313z">
        </path>
      </svg>
    </div>
    <script>

    </script>
  </body>
</html>

对 path 的样式设置可以让路径显示出来,其中的 fill, stroke-width, stroke 设置也可以直接设置在 path 元素上。

让路径动起来

可以使用 stroke-dasharray 和 stroke-dashoffset 属性,然后让 stroke-dashoffset 随时间变动就可以让路径动起来。

stroke-dasharray 属性可以让路径以虚线的形式进行绘制。例如设置为 stroke-dasharray:”4 1″, 那么就会出现一段为 4 的实线和一段为 1 的虚线,并且以一样的规律绘制下去。

stroke-dashoffse 属性可以设置虚线的偏移量,在一条水平向右的虚线中,如果增加 stroke-dashoffse 的值,虚线会向左移动,如果减少 stroke-dashoffse 的值,虚线会向右移动。

通过把 stroke-dasharray 设置为路径的总长度,然后把 stroke-dashoffse 也设置为路径的总长度,那么就可以把整条路径隐藏起来,之后不断减少 stroke-dashoffse 的值,那么路径就可以不断显示出来。

现在的关键是如何获取路径的总长度,一般的做法是通过 path 元素的 getTotalLength() 方法来获取路径的总长度,但这样需要使用到 js。除了这样的办法外,其实还可以通过给 path 元素设置 pathLength 属性,这样 stroke-dasharray 和 stroke-dashoffset 就会认为 pathLength 的值就是路径的总长度。

pathLength 不能设置在 css 中,需要直接设置在 path 元素上,我给每一个 path 元素的 pathLength 都设置为 100,并为每一个 path 元素增加了 stroke-dasharray 和 stroke-dashoffse 的设置, stroke-dasharray 和 stroke-dashoffse 这两个属性也可以直接设置在 path 元素上

    path {
        fill: none;
        stroke-width: 1;
        stroke: #1e80ff;
        stroke-dasharray: 100;
        stroke-dashoffset: 100;
      }
    <path pathLength="100" class="jue" d="M166..."></path>
    <path pathLength="100" d="M548..."></path>
    <path pathLength="100" d="M643....."></path>
    <path pathLength="100" d="M499...."></path>
    <path pathLength="100" d="M626...."></path>

目前所有的路径都隐藏了起来,只需要通过动画把 stroke-dashoffse 变为 0,就可以实现路径移动的效果。动画使用了 svg 的 animate 元素来实现,只需要把 animate 元素嵌套在 path 元素内就可以了。animate 元素通过设置元素属性来控制动画的执行,下面是掘这个字的动画设置。

<path pathLength="100" class="jue" d="M166.863,320.827c0-33.058-0.395-59.162-1.148-78.311l26.414,14.357l-10.336,7.831v56.123h6.891l11.484-13.052  l18.375,20.883h-36.75v62.649l32.156-14.357l2.297,3.916l-34.453,22.188v103.11c0,13.908-7.662,25.227-22.969,33.935  c0-10.441-10.73-20.026-32.156-28.714v-5.221c16.078,2.61,26.791,3.915,32.156,3.915c5.348,0,8.039-3.467,8.039-10.441V412.19  c-20.672,11.318-32.551,20.026-35.602,26.104l-14.93-22.188c8.416-1.734,25.266-7.832,50.531-18.273v-69.175h-28.711l-10.336,2.61  l-9.188-10.441H166.863z M182.941,540.099c15.307-25.227,26.02-52.207,32.156-80.922c6.119-28.714,9.367-59.814,9.762-93.321  c0.377-33.486,0.18-68.951-0.574-106.373l17.227,11.747h103.359l10.336-11.747l16.078,18.272l-9.188,6.526  c0,19.149,0.377,35.24,1.148,48.292l-16.078,7.832v-13.052H239.215c3.051,99.195-14.553,170.98-52.828,215.356L182.941,540.099z   M239.215,279.061v40.461h107.953v-40.461H239.215z M248.402,512.689c0-32.181-0.395-55.246-1.148-69.175l21.82,13.052l-6.891,7.831  v52.208h39.047v-92.668h-32.156l-8.039,7.831l-12.633-14.357l6.891-6.526c0-23.494-0.395-42.194-1.148-56.123l21.82,13.052  l-6.891,7.831v40.462h32.156c0-41.767-0.395-69.604-1.148-83.533l22.969,11.747l-8.039,7.831v63.955h31.008  c0-26.104-0.395-45.683-1.148-58.734l21.82,11.747l-6.891,7.831c0,21.76,0.377,39.157,1.148,52.208l-14.93,7.831v-13.052h-31.008  v92.668h40.195c0-28.714-0.395-52.208-1.148-70.48l22.969,13.052l-8.039,6.526c0,35.688,0.377,58.733,1.148,69.175l-14.93,7.831  v-18.272h-93.023l-8.039,10.441l-13.781-14.356L248.402,512.689z">
      <animate id="jue" attributeType="XML"
        begin="container.click"
        attributeName="stroke-dashoffset"
        to="0"
        dur="2"
        fill="freeze"
        repeatCount="1"/>
    </path>

attributeName 设置需要应用的属性。
to 是目标值
dur 是动画持续的时间
fill 为 freeze 表示动画结束后停留在最后一帧上,默认为 remove,会回到最初的状态
repeatCount 是重复次数
begin 是动画开始的时机,begin 支持多种使用的方式,这里是当 container 元素点击后动画启动。

如果希望掘字动画结束后执行金字的动画,那么可以设置 begin=”jue.end”,其中 jue 是掘字对应的 animate 元素,这个元素有 end 事件。

 <path pathLength="100" d="M548.145,267.314l10.336-6.526l-24.117-18.272c-27.563,73.09-67.758,123.993-120.586,152.707l1.148,5.221  c57.422-25.227,100.291-67.87,128.625-127.909c27.563,57.428,66.215,96.584,115.992,117.467c3.822-11.298,11.09-17.396,21.82-18.273  v-5.221C628.535,359.554,584.123,326.496,548.145,267.314z">
      <animate id="jin1" attributeType="XML"
        attributeName="stroke-dashoffset"
        to="0"
        dur="1"
        fill="freeze"
        begin="jue.end"
        repeatCount="1"/>
    </path>

通过这种设置就可以依次执行后续的动画。

到这里基本就实现了整个动画了,但是你会发现掘字虽然对应只有一个 path 元素,但是动画执行时会分 4 段同时执行。而对应的 path 路径指令中,就有 4 个 M 移动指令,也就是 stroke-dashoffse 和 stroke-dashoffset 是按照 M 指令的起点绘制虚线的,而不是从 path 路径从头到尾来绘制的。因此掘字的路径其 stroke-dashoffse 和 stroke-dashoffset 属性应该设置为这 4 段中比较长的那一段,这样整个字的路径都能完整显示出来,而不是整个路径的总长度。而比较长的那段大概是总长的一半

.jue {
    stroke-dasharray: 50;
    stroke-dashoffset: 50;
  }

如果希望更精确的控制,那么可以像金字一样把一个 path 路径进行打散。

总结

通过以上的例子,主要介绍了 svg 中 pathLength 属性和 animate 元素的使用。

在线的例子(codepen.io/changli/pen…)

如果发现点击后没有反应,可能是浏览器不支持 SVG Animations Level 2

如果希望控制路径的起点以精确控制绘制过程,那么可能需要在矢量编辑器中进行操作。

参考链接

svg 的 animate 元素
svg 的 pathLength 属性

原文链接:https://juejin.cn/post/7311882547688161332 作者:changli2018

(0)
上一篇 2023年12月14日 上午12:13
下一篇 2023年12月14日 上午12:24

相关推荐

发表回复

登录后才能评论