用了那么久的 SVG,你还没有入门吗?(三)

简介: 用了那么久的 SVG,你还没有入门吗?

添加动画

通过以上的方式就实现了一个静态的环形进度条了,接下来就需要它动起来,由于 stroke-dasharray(在这它的值其实就是圆的周长stroke-dashoffset 的属性值是需要动态生成的,因此我们得添加一些 JavaScript 代码:

function setProcessCircle(percent = 0) {
    const processCircle = document.querySelector('.process-circle')
    // 获取圆的周长
    const circumference = processCircle.getTotalLength()
    // 把周长赋值给 strokeDasharray
    processCircle.style.strokeDasharray = circumference
    // 动态计算 offset 赋值给 strokeDashoffset
    // 为了支持 percent = 0 | '0%',所以使用 parseInt 转换
    processCircle.style.strokeDashoffset =
      circumference * (1 - parseInt(percent) / 100)
}
复制代码

效果图中的 html + css 部分就不贴出来了,容易占篇幅。

image.png

loading 动画

例如 ElementUI 中 区域加载 的 loading 形式如下:

image.png

简单分析

  • 观察整体不难发现只需要一个圆形,即使用 <circle> 元素即可
  • 其蓝色部分一直在 缩短 或 增长,这点可以通过 stroke-dasharraystroke-dashoffset 属性来实现,同时添加 transition 过渡动画即可
  • 最后是每个 缩短 或 增长 的位置不是相同的,那么可以直接用过动画 animationroate 来实现停的旋转即可

具体实现

// html
<svg stroke-width="3">
    <circle
      cx="50"
      cy="50"
      r="20"
      fill="none"
      class="circle-loading"
    ></circle>
</svg>
// style
<style>
  .circle-loading {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: 0;
    stroke: #409eff;
    stroke-linecap: round;
    animation: loading-dash 1.5s ease-in-out infinite, 
    laoding-color 1.5s ease-in-out infinite;
  }
  @keyframes laoding-color {
    0% {
      stroke: #de3e35;
    }
    25% {
      stroke: #ffa500;
    }
    50% {
      stroke: #ffff00;
    }
    75% {
      stroke: #008000;
    }
    100% {
      stroke: #0000ff;
    }
  }
  @keyframes loading-dash {
    0% {
      stroke-dasharray: 1, 200;
      stroke-dashoffset: 0;
    }
    50% {
      stroke-dasharray: 90, 150;
      stroke-dashoffset: -40px;
    }
    to {
      stroke-dasharray: 90, 150;
      stroke-dashoffset: -120px;
    }
  }
</style>
复制代码

image.png

按钮动效

image.png

简单分析

  • 外层包裹的矩形可以通过 <rect> 元素实现
  • 矩形的线条残缺不完整,可以通过 stroke-dasharraystroke-dashoffset 属性来实现
  • 当鼠标放置上去时,产生的动画可通过 animationstroke-dasharraystroke-dashoffset 等属性结合即可

具体实现

// html
 <svg class="svg-wrap">
    <text class="text" x="60" y="75">CLICK HERE</text>
    <rect class="rect" x="40" y="35" />
  </svg>
// style
<style>
  .svg-wrap {
    stroke-width: 3px;
    background-color: black;
  }
  .rect {
    height: 60px;
    width: 220px;
    stroke: #fff;
    fill: transparent;
    stroke-dasharray: 220 60;
    stroke-dashoffset: -260;
    stroke-width: 4px;
  }
  .text {
    fill:  #1287f4;
    font-size: 30px;
  }
  .svg-wrap:hover .rect {
    animation: line-move 0.5s linear forwards;
  }
  .svg-wrap:hover .text{
    fill:  #fff;
    transition: all 1s ease-in-out;
  }
  @keyframes line-move {
    0% {
      stroke-dasharray: 220 60;
      stroke-dashoffset: -260;
      stroke-width: 4px;
      stroke: #e32727;
    }
    to {
      stroke-dasharray: 560;
      stroke-dashoffset: 0;
      stroke-width: 2px;
      stroke: #1234f4;
    }
  }
</style>
复制代码

复杂案例实战

以上的基础案例由于涉及的计算不多,因此我们可以人工进行计算宽、高、偏移等等数据,但是针对复杂的内容,很多参数就不是那么容易计算出来了,因此,我们需要一些工具来快速得到一些必要参数,然后我们在基于这些必要参数取做修改,让其产生更丰富的效果即可。

工具推荐

和 SVG 相关的工具就现在来说已经遍地开花了(就好像现在的 ChatGPT、文心一言),通过搜索引擎查找都能找出来很多,这里也不谈这些工具的优劣了,下面简单列举一些:

  • figma:支持浏览器在线,支持客户端下载
  • sketch:支持浏览器在线,支持客户端下载(Mac)
  • Adobe Illustrator:支持浏览器在线,支持客户端下载
  • Pixso:号称 Sketch 的新选择,几乎还原了Sketch 的专业功能
  • ...

下面的示例都是基于 figma 来演示的,不再后续赘述。

文字动效

image.png

还是同样的第一个案例这里尽量讲详细点,后续案例就不再述说过于详细的内容了。

使用 figma 创建文字路径如下

由于文字内容的路径很难直接计算处理,因此我们可以通过 figma 来帮助我们生成相应的文字路径,大致操作如下:

image.png

处理 SVG 代码内容

得到的 SVG 内容大致如下,代码内容比较多这里用图片代替,其中各个内容的对应关系如下所示:

image.png

其中的 <mask> 需要去掉,否则文字的颜色值将无法填充。

stroke-dasharray & stroke-dashoffset 属性

由于我们需要让文字具备断续连接的能力,这里还是得使用前面提到 stroke-dasharraystroke-dashoffset 属性来实现,它们的功能前面已经描述过了,也用了几次了,如果你不记得了可以回过头去看看。

但是这里的 stroke-dasharraystroke-dashoffset 的值到底该设置成多少呢?

首先一定是设置成每个文字的长度,那么问题就变成了怎么获取文字的长度了,不用担心,还记得在实现 环形进度条 时用到的 getTotalLength() 方法吗?

这里我们仍然可以使用它来获取每个文字的长度了,代码如下:

const paths = document.querySelectorAll('path')
  for (const [ptah,index] of paths) {
    console.log(`path 的路径长度 = ${ptah.getTotalLength()}`)
  }
  输出结果:
   path 的路径长度 = 179.47874450683594  S
   path 的路径长度 = 150.7733917236328   V
   path 的路径长度 = 274.966064453125    G
   path 的路径长度 = 442.99505615234375  文
   path 的路径长度 = 514.3809204101562   字
复制代码

接下来为每个 path 设置样式:

#svg-text > path:nth-of-type(1) {
    stroke-dasharray: 179.479;
    stroke-dashoffset: 179.479;
}
#svg-text > path:nth-of-type(2) {
    stroke-dasharray: 150.773;
    stroke-dashoffset: 150.773;
}
#svg-text > path:nth-of-type(3) {
    stroke-dasharray: 274.966;
    stroke-dashoffset: 274.966;
}
#svg-text > path:nth-of-type(4) {
    stroke-dasharray: 442.995;
    stroke-dashoffset: 442.995;
}
#svg-text > path:nth-of-type(5) {
    stroke-dasharray: 514.381;
    stroke-dashoffset: 514.381;
}
复制代码

设置了这些值之后,文字内容就会不可见了,而这也是 动画的初始状态

animation 动画

前面种种操作已经完成了动画的初始状态,接下来我们要添加上 animation 动画,核心改变的就是 stroke-dashoffset 的值,就是把它设置成 0,文字内容就会被从隐藏变成显示,再添加过渡时间就完成了,重复内容就不贴出来了:

#svg-text > path:nth-of-type(1) {
    /* ... */
    animation: text-line 2s ease forwards;
}
#svg-text > path:nth-of-type(2) {
    /* ... */
    animation: text-line 2s ease forwards 300ms;
}
#svg-text > path:nth-of-type(3) {
     /* ... */
    animation: text-line 2s ease forwards 600ms;
}
#svg-text > path:nth-of-type(4) {
    /* ... */
    animation: text-line 2s ease forwards 900ms;
}
#svg-text > path:nth-of-type(5) {
    /* ... */
    animation: text-line 2s ease forwards 1200ms;
}
#svg-text{
    stroke: #d205f7;
    fill: none;
    animation: fill-color 2.5s ease-in forwards;
}
@keyframes text-line {
    to {
      stroke-dashoffset: 0;
    }
}
@keyframes fill-color{
    to{
      stroke: transparent;
      fill: #d205f7;
    }
}
复制代码

重复的事交给 JavaScript

上面才 5 个文字就需要写那么多的样式,属实不能忍,于是我们可以将重复的部分交给 JavaScript 代码去处理:

<style>
  #svg-text {
    stroke: #d205f7;
    stroke-width: 2px;
    fill: none;
    animation: fill-color 2.5s ease-in forwards;
  }
  @keyframes text-line {
    to {
      stroke-dashoffset: 0;
    }
  }
  @keyframes fill-color {
    to {
      stroke: transparent;
      fill: #d205f7;
    }
  }
</style>
<script>
    function init() {
        const paths = Array.from(document.querySelectorAll('path'))
        paths.forEach((path, index) => {
          const len = path.getTotalLength()
          path.style.strokeDasharray = len
          path.style.strokeDashoffset = len
          path.style.animation = `text-line 2.5s ease-in forwards ${
            index * 300
          }ms`
        })
    }
    init()
</script>
复制代码

运动轨迹

image.png

简单分析

完成以上效果需要包括以下几个内容:

  • 获取 目标物SVG 代码
  • 绘制 运动路径
  • 让目标物 沿着路径运动

获取目标物的 SVG 代码

这个可以直接从 iconfont 上选择对应的内容,然后复制它的 SVG 代码。

image.png

绘制运动路径

运动路径的绘制我们仍然可以通过 SVG 工具 figma 来获取,值得注意的是默认的路径是用还是填充的,真正在应用时可以通过 stroke="transparent" 将路径颜色变成透明色,整体感官更好,大致如下:

image.png

让目标物沿着路径运动

针对这种按特定运动轨迹进行的动画,也不需要你去一点点计算了,我们可以借助 GreenSock 中的 motionpath 插件来实现,在其对应的文档中有详细的介绍,核心就是引入以下两个内容:

image.png

<div id="app">
  <!-- 鸟 -->
  <svg
    id="bird"
    t="1679665908640"
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="14202"
    width="100"
    height="100"
  >
    省略内容
  </svg>
  <!-- 路径 -->
  <svg
    width="719"
    height="419"
    viewBox="0 0 719 419"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      id="path"
      d="M1 268C146.006 483.259 245.695 450.805 336 268C518.233 -96.9549 599.902 -63.7284 718 222"
      stroke="transparent"
    />
  </svg>
</div>
<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script>
<script src="https://unpkg.com/gsap@3/dist/MotionPathPlugin.min.js"></script>
<script>
  // 注册插件
  gsap.registerPlugin(MotionPathPlugin);
  // 开启动画
  gsap.to("#bird", {
    duration: 5,
    repeat: 12,
    repeatDelay: 1,
    yoyo: true,
    ease: "power1.inOut",
    motionPath: {
      path: "#path",
      align: "#path",
      alignOrigin: [0.5, 0.5],
    },
  });
</script>
复制代码

最后

以上就是本文有关 SVG 基础部分的介绍和使用了,不知道你是入门了,还是被门绊了一下,还是那句话:希望本文对你所有帮助!!!


目录
相关文章
|
Web App开发 前端开发 JavaScript
前端面试实录CSS篇(最近一周)(上)
前端面试实录CSS篇(最近一周)
|
3月前
|
前端开发
【前端web入门第四天】02 CSS三大特性+背景图
本文详细介绍了CSS的三大特性:继承性、层叠性和优先级,并深入讲解了背景图的相关属性,包括背景属性、背景图的平铺方式、位置设定、缩放、固定以及复合属性。其中,继承性指子元素自动继承父元素的文字控制属性;层叠性指相同属性后定义覆盖前定义,不同属性可叠加;优先级涉及选择器权重,包括行内样式、ID选择器等。背景图部分则通过具体示例展示了如何设置背景图像的位置、大小及固定方式等。
264 91
|
编解码 前端开发 JavaScript
前端面试实录CSS篇(最近一周)(下)
前端面试实录CSS篇(最近一周)(下)
|
前端开发
我用 CSS 告诉你,我每天是怎么度过的~
我用 CSS 告诉你,我每天是怎么度过的~
|
前端开发
css光泽一闪而过的效果(整理)
css光泽一闪而过的效果(整理)
|
前端开发 JavaScript
【web前端阶段二】CSS巩固学习(持续更新)
【web前端阶段二】CSS巩固学习(持续更新)
|
前端开发
用了那么久的 SVG,你还没有入门吗?(二)
用了那么久的 SVG,你还没有入门吗?
147 0
|
XML 编解码 前端开发
用了那么久的 SVG,你还没有入门吗?(一)
用了那么久的 SVG,你还没有入门吗?
174 0
|
前端开发
CSS实战笔记(四) 抖动效果
CSS实战笔记(四) 抖动效果
131 0