关于前端:SVG基础及其动画应用浅析

4次阅读

共计 13380 个字符,预计需要花费 34 分钟才能阅读完成。

本文作者:钱鸿昌(闪火)

一、咱们为什么应用 svg

  1. 和高清 png 来做个比照


    持续比照


    同样高清的质地,矢量图不畏惧放大,体积小。这里要阐明一点就是,因为 SVG 中保留的是点、线、面的信息,与分辨率和图形大小无关,只是跟图像的复杂程度无关,所以图像文件所占的存储空间通常会比 png 小。

  2. 优化 SEO 和无障碍的利器,因为 SVG 图像是应用 XML(可扩大标记语言【英语:Extensible Markup Language,简称:XML】标记指计算机所能了解的信息符号,通过此种标记,计算机之间能够解决蕴含各种信息的文章等)来标记构建的,浏览器通过绘制每个点和线来打印它们,而不是用预约义的像素填充某些空间。这确保 SVG 图像能够适应不同的屏幕大小和分辨率。
  3. 因为是在 XML 中定义的,SVG 图像比 JPG 或 PNG 图像更灵便,而且咱们能够应用 CSS 和 JavaScript 与它们进行交互。SVG 图像设置能够蕴含 CSS 和 JavaScript。在 react、vue 这种数据驱动视图的框架下,对于 SVG 操作就更加蛟龙得水了。(下文会跟大家分享一些小的 SVG 动画在咱们我的项目中的实际)
  4. 在使用层面上,SVG 提供了一些图像编辑成果,比方屏蔽和剪裁、利用过滤器等等。并且 SVG 只是文本,因而能够应用 GZip 对其进行无效压缩。

二、理解 SVG 罕用元素及其应用

大多数教程网上都能找到,这里写一些我感觉值得提及的点

2-1. svg 标签

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg  width="300" height="300" viewBox="0, 0, 100, 200"  xmlns="http://www.w3.org/2000/svg" version="1.1">
    <circle cx="100" cy="50" r="49" stroke="black"
    stroke-width="2" fill="red" />
</svg>

这就是咱们从设计手里拿到的 SVG 源文件,咱们掰开揉碎了说。首先咱们把 SVG 外部代码全副去掉不看,于是成了这样

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="300" height="300" viewBox="0, 0, 100, 200"  xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>

这是 99% SVG 都会体现进去的模式和及一些属性,其中蕴含 width、height 这两个视口属性,viewBox 视图属性,xmlns 属性。咱们一行一行看

第一行:蕴含了 XML 申明,XML 申明其实和 HTML 文档的 DTD 申明是相似的。类比 HTML5 的申明形式

<!DOCTYPE html>

SVG 的文档申明形式(划重点:个别如果 SVG 使用在 HTML 里,咱们能够不写这样的文档申明,但如果是独自的 SVG 文件,那就须要写了,否则浏览器可能会不意识)

<?xml version="1.0" standalone="no"?>

咱们看到的 standalone 属性是在表明该 xml 申明是否是独立的,如果不是即 standalone=”no”,那前面会引入内部的 dtd,如第二行第三行所示。version 属性用于指明 SVG 文档遵循标准的版本。它只容许在根元素<svg> 上应用。它纯正是一个阐明,对渲染或解决没有任何影响。尽管它承受任何数字,然而只有 1.0 和 1.1. 这两个无效的抉择。

第四行:这是 SVG 内容的开始

<svg width="300" height="300" viewBox="0, 0, 100, 200"  xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>
  • xmlns 属性是 SVG 的 XML 申明空间,这一部分相似于 HTML 中的 xmlns=”http://www.w3.org/1999/xhtml”

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  • width & height 属性,能够了解成画布的大小。没错是画布的大小。举个例子:

    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=100 height="100">
      <circle cx="50" cy="50" r="49" stroke="black"
      stroke-width="1" fill="red" />
    </svg>

以后这个 SVG 的画布大小是 100 * 100 的画布,咱们画上一个半径为 49 再加 1 个单位的描边的圆。刚好撑满没故障。所见即所得。那咱们试一下扭转 width 和 height。发现

<svg  
    style="background:#007fff"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    width="300"
    height="300">
    <circle cx="50" cy="50" r="49" stroke="black"
    stroke-width="1" fill="red" />
</svg>

咱们能够看到蓝色区域就是咱们定的 width 和 height , 图形局部仍然是那个圆没有变动。这样咱们就了解了 width 和 height 的作用。

  • viewBox 属性,接下来配合 viewBox 这个属性咱们再来批改下代码

    <svg 
      style="background:#007fff"
      xmlns="http://www.w3.org/2000/svg"
      version="1.1"
      <!-- viewBox 定义 -->
      viewBox="0, 0, 100, 100"
      width="300"
      height="300" >
      <circle cx="50" cy="50" r="49" stroke="black"
      stroke-width="1" fill="red" />
    </svg>

咱们能够看到蓝色区域大小不变,而咱们的圆却变得很大,大到撑满了整个画布。没错,你的想法是对的,所谓 viewBox 这个属性能够了解为咱们微信聊天时的截图操作。viewBox 属性的四个参数,前两个示意截图终点,前面两个示意截图起点,均是以左上角定点为原点。最初把截图再拉伸放在 SVG 画布上,就成了咱们下面看到的 SVG 了。上面咱们再批改一次 viewBox 成 0, 0, 50, 50 帮忙了解

<svg 
    style="background:#007fff"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    viewBox="0, 0, 50, 50" 
    width="300"
    height="300" >
    <circle cx="50" cy="50" r="49" stroke="black"
    stroke-width="1" fill="red" />
</svg>

所以整个逻辑大略是这样的

2-2.path 标签

在 SVG 里,你能够把 path 看成是最根本的绘制元素,正因为它是最根本的,万变不离其宗,他能演化出各种简单的绘制成果。所以 path 是最根本也是最简单的绘制元素。

path 的根底属性和其代表的意义

咱们晓得一个 path 标签,最重要的属性是 d 属性,它是一组指令和参数的汇合。在 d 属性的值里,咱们能看到一堆非常复杂的指令字符串。

<path d="
    M73.8616812,68.8664775
    L74.5015359,74.5939423
    L68.1746283,71.7969507
    C66.2299599,72.4159872 64.1377269,72.7711218 61.9444643,72.7711218
    C51.9719158,72.7711218 43.8883163,65.7823167 43.8883163,57.1611168
    C43.8883163,48.5399169 51.9719158,41.5511118 61.9444643,41.5511118
    C71.9164005,41.5511118 80,48.5399169 80,57.1611168
    C80,61.8286883 77.6181486,66.006419 73.8616812,68.8664775"id="Fill-1"fill="#FFFFFF"></path>

其实齐全不必感觉恶心,这里持续掰开揉碎了说

  • d 属性里的那些指令
指令 参数 含意
M x y 将画笔挪动到点(x,y)
L x y 画笔从以后的点绘制线段到点(x,y)
H x 画笔从以后的点绘制程度线段到点(x,y0),y0 示意绘制前画笔所在 y 轴坐标,也就是 y 轴不变
V y 画笔从以后的点绘制竖直线段到点(x0,y),x0 示意绘制前画笔所在 x 轴坐标,也就是 x 轴不变
A rx ry x-axis-rotation large-arc-flag sweep-flag x y 画笔从以后的点绘制一段圆弧到点(x,y)
C x1 y1, x2 y2, x y 画笔从以后的点绘制一段三次贝塞尔曲线到点(x,y)
S x2 y2, x y 非凡版本的三次贝塞尔曲线(省略第一个控制点)
Q x1 y1, x y 绘制二次贝塞尔曲线到点(x,y)
T x y 非凡版本的二次贝塞尔曲线(省略控制点)
Z 无参数 绘制闭合图形,如果 d 属性不指定 Z 命令,则绘制线段,而不是关闭图形

以上是 path 门路中的全副指令,其中加粗局部为罕用根底指令,相对来说比拟好了解。每个指令都有对应的小写指令。例如 M 10,10 有对应的 m 10,10。大写代表相对地位,所谓相对地位即对 SVG 画布左上角原点的相对 。小写代表绝对地位, 所谓绝对地位是以以后画笔所在位置进行定位

  • A(arc)画弧指令

    A rx ry x-axis-rotation large-arc-flag sweep-flag x y
    
    <svg width="100%" height="100%">
      <path d="M0 0 A 45 45, 0, 0, 0, 45 45 L 45 0 Z" fill="green"/>
    </svg>

画了张图,帮忙了解

依照图中的步骤,咱们能够画出两个圆都满足,于是再看到其中 A 指令有三个 0 咱们没有解释,回顾下 A 指令,并联合这张图咱们能够更好的了解

A rx ry x-axis-rotation large-arc-flag sweep-flag x y

  • 贝塞尔曲线
    对于贝塞尔曲线,张老师这篇文章曾经说得十分分明了,说得十分易懂深度了解 SVG 门路,举荐给心愿更多理解 svg 门路的同学

2-3. 根本图形

根本图形这块绝对比拟好了解,咱们间接一张表总结下,不做过多赘述

图形 标签 模板 含意
矩形 < rect > <rect x="60" y="10" rx="10" ry="10" width="30" height="30"/> x: 终点横坐标,y: 终点纵坐标,rx: 倒角 x 轴方向半径,ry: 倒角 x 轴方向半径,width: 宽度,height: 高度
圆形 < circle > <circle cx="100" cy="100" r="50" fill="#fff"></circle> cx: 圆心横坐标,cy: 圆心纵坐标,r: 半径
椭圆 < ellipse > <ellipse cx="75" cy="75" rx="20" ry="5"/> cx: 椭圆心横坐标,cy: 椭圆心纵坐标,rx: 椭圆 x 轴方向半径,ry: 椭圆 y 轴方向半径
直线 < line > <line x1="10" x2="50" y1="110" y2="150"/> x1,y1: 终点,x2,y2: 起点
折线 < polyline > <polyline points="60 110, 65 120, 70 115, 75 130, 80 125, 85 140, 90 135, 95 150, 100 145"/> 每两个点以空格配对为一个坐标点,逗号隔开造成坐标汇合。连成折线。
多边形 < polygon > <polygon points="50 160, 55 180, 70 180, 60 190, 65 205, 50 195, 35 205, 40 190, 30 180, 45 180"/> 相似折线,不同的是,最初一个点会主动闭合第一个点,造成闭环。

2-4.symbol 标签

symbol 标签是咱们直播团队 icon 治理平台实现的核心技术点,它的作用说文言点就是相当于是一个元件,放在咱们的工具箱里,就像上面这样:

<svg class="svg-sprite">[工具箱]
    <symbol id="icon-wave_add" viewBox="0 0 76 76"><path d="M38 0a4 4 0 014 4v30h30a4 4 0 110 8H41.999L42 72a4 4 0 11-8 0l-.001-30H4a4 4 0 110-8h30V4a4 4 0 014-4z" fill="currentColor" fill-rule="evenodd" opacity="none"></path></symbol>
    <symbol id="icon-time" viewBox="0 0 10 10"><path d="M5 0a5 5 0 110 10A5 5 0 015 0zm0 1.5a.5.5 0 00-.5.5v3.02l.008.088a.5.5 0 00.238.343L7.02 6.794l.082.039a.5.5 0 00.603-.215l.039-.082a.5.5 0 00-.216-.603L5.5 4.735V2l-.008-.09A.5.5 0 005 1.5z" fill="rgba(153,153,153,1)" fill-rule="evenodd" class=" "></path></symbol>
    <symbol id="icon-wave_delete" viewBox="0 0 40 40"><g fill="none" fill-rule="evenodd"><circle fill="#000" opacity="0.2" cx="20" cy="20" r="20"></circle><path stroke="#FFF" stroke-width="4" stroke-linecap="round" d="M13 13l14 14M27 13L13 27"></path></g></symbol>
</svg>

放一份就能够有限援用。当它在工具箱里时,咱们是看不到它的(页面不会渲染它),只有咱们应用了 <use> 标签对其进行实例援用时,咱们才能够在页面上看到它:

<use xlink:href="#icon-time"></use>

咱们应用 <symbol> + <use> 的组合,来实现 svg 雪碧图,是不是感觉很 easy。

有的同学会有疑难,symbol 标签和 g 标签,放在 defs 里好像都是在定义一个可复用的模块,那么两者之间有什么区别呢?在我的了解里,symbol 绝对于 g 标签最大的不同在于 symbol 能够给可复用代码块减少视图属性和视口属性。不便在服用的时候间接调整到适合的使用 (打印) 尺寸。

三、svg 动画及其使用

3-1.svg 动画概要

其实对于 SVG 动画,要说的有很多,本文咱们次要说一下 SVG 动画的一些根本属性和使用技巧
1、SMIL 驱动
2、JavaScript 驱动
3、CSS 驱动

技术 形容 备注
SMIL 很弱小且纯正的标签化动画 尽管 Chrome 45 当前弃用了 SMIL,然而仍然反对,各大浏览器的反对度都挺好的
CSS CSS 还只能实现简略的动画 offset-path 的兼容性很差。css 动画不适宜做交互性很强的动画
JavaScript 简单动画就要用到 JS 了,包含世面上的一些 SVG 动画库,也都是 JS 去实现的

SVG 是基于 XML 的矢量图形描述语言,能够近似了解成 HTML,所以能和 JS 以及 CSS 进行交互。特地是 CSS,咱们能够应用 CSS3 来对 SVG 做动画解决。然而要记住的是仅当 HTML 内联蕴含 SVG 文件时, 咱们才能够应用 CSS 对其做款式开发。本文咱们针对平时 CSS3 + HTML 不容易实现,而利用 SVG 能够疾速简便实现的几种场景做相应介绍

3-2.SVG 动画实际

1、直线的变动
2、path 门路实现图形的平滑变幻
3、描边动画
4、指定轨迹静止

3-2-1、直线的变动

上面这张图是一个 GIF 的 icon, 体积大概是 156KB, 压缩之后。

如果咱们用 SVG 去实现的话。应该怎么做呢。咱们分为以下两种形式,亲测兼容性都 OK

CSS+SVG 实现的代码实际

基于 SMIL 实现的代码实际

总结 & 阐明

知识点 1:

SVG 中有很多属性咱们是能够用 CSS 去形容的。在基于 CSS 动画三剑客(animation, transform, transition)的根底上。咱们对一些属性进行管制,就达到咱们想要的动画成果。上面两点值得阐明:

  • transform:transform 有两种用法,一个是在 SVG 标签里写的 transform 属性、另一种是在 CSS 文件里写的 transform,他们有着实质的区别。
<rect transform="rotate(45deg) ..."  ... />

rect {transform: rotate(45deg)
}
/** 行内的 transform 属性,他的执行基点是在咱们 svg 元素的左上角也就是 svg 的坐标原点。**/
/** 而 CSS 的 transform 原点则在元素自身的中心点。**/
  • CSS 可形容属性:很多文章通知咱们 CSS 能够管制 SVG 去做动画,然而理论开发过程中咱们会更想晓得,到底哪些属性咱们能够做 css 管制,这里给大家列出一些罕用属性并且能够放心使用的属性

    | CSS 可控属性名 | 可实现场景
    | — | — |
    | 实践上所有的显示属性,都能够应用 CSS 管制包含:比方 stroke-width、color、fill 等等 SVG 的显示属性 | 大部分的显示款式动态变化
    |x| 咱们晓得矩形有 x、y 属性,其含意是起始点,管制 x,咱们能够动态控制矩形的 X 轴位移
    |y| 管制 y,咱们能够动态控制矩形的 Y 轴向位移
    |cx|<circle cx="100" cy="100" r="50" fill="#fff" /> 这是一个圆形,管制 cx 能够管制圆形 (或者椭圆) 的 X 轴位移 |
    |cy| 管制 cy 能够管制圆形 (或者椭圆) 的 Y 轴位移
    |r|r 是圆的半径,管制 r 能够管制圆形的大小
    |rx|rx 是椭圆的 X 轴方向半径,管制 rx 能够管制椭圆的大小
    |ry|ry 是椭圆的 Y 轴方向半径,管制 ry 能够管制椭圆的大小
    |d|path 标签的 d 属性,管制 d 的门路信息,能够管制图形的变幻(d 属性在 safari 上是不反对 css 形容的。咱们下文会具体的阐明)|
    |PS: 如果各位看官们在日常开发中,不分明该属性是否能够通过 css 去管制,这边给大家提供一个查问链接 | 不反对 CSS 管制的 SVG 相干属性

知识点 2: 能够利用 SMIL 对 SVG 做动画解决,举个例子,同样的动画成果,上面这段代码不必 CSS 也能够实现

export default function App() {
    return (
    <div className="App">
        <svg width="100%" height="100%" viewBox="0 0 100% 100%">
        {[1, 2, 3, 4, 5].map((it, index) => (
            <line
            key={index}
            stroke="#000"
            strokeWidth="2"
            x1={15 + index * 5}
            y1="8"
            x2={15 + index * 5}
            y2="22"
            >
            <animate
                attributeName="y1"
                values="8; 15; 8"
                dur="1s"
                begin={`${(5 % (index + 1)) * 0.2}s`}
                repeatCount="indefinite"
            />
            <animate
                attributeName="y2"
                values="22; 15; 22"
                dur="1s"
                begin={`${(5 % (index + 1)) * 0.2}s`}
                repeatCount="indefinite"
            />
            </line>
        ))}
        </svg>
    </div>
    );
}

那么
什么是 SVG 的 SMIL 呢?

这里不想再对其做大篇幅的赘述,因为网上有很多文章都曾经说得比拟具体了[SMIL 动画指栏](https://css-tricks.com/guide-svg-animations-smil/)、[SVG SMIL animation 动画详解](https://www.zhangxinxu.com/wordpress/2014/08/so-powerful-svg-smil-animation/)。本文更想和大家交换的是在 SMIL 驱动和 CSS 驱动如何做抉择的问题。

尽管说早在 Chrome 45,chrome 就曾经官宣要弃用 SMIL,然而到目前地位,各大浏览器厂商对它的反对度是这样的


Chrom 发表弃用 SMIL 是因为要反对 CSS Animation 与 Web Animation 的倒退,所以咱们能够了解为以后是在一个过渡状态,的确有一些临时 CSS 还没法反对或者反对度很差的动画成果,SMIL 能够轻松实现。然而基于 web 动画技术倒退的大趋势,还是倡议咱们 SVG 动画实现计划的抉择优先级是 CSS 驱动 -> JS 驱动(咱们能够采纳一些框架,文末会给大家举荐一些好用的框架)-> SMIL 驱动

3-2-2、path 门路的变动(图形平滑变动)


CSS+SVG 实现的代码实际 Logo 变动

基于 SMIL 实现的代码实际 Logo 变动

CSS+SVG 实现的代码实际播放暂停

基于 SMIL 实现的代码实际播放暂停

总结 & 阐明

知识点 1:

通过对 <path/> d 属性的管制,咱们能够实现很多动画成果,对于 d 属性的管制目前有两种形式,一种是通过 CSS 管制,另一种是通过 SMIL 管制,然而目前因为 safari 不反对 用 CSS 来形容 <path> 标签的 d 属性。所以在实现这种平滑的形态变形成果上不举荐应用 CSS。更加举荐应用 SMIL 或者第三方库去实现

基于 CSS:

    path {
      transition: ease all 0.3s; // 就像对 dom 一样的看待 svg

      &.play { // 这里是播放状态下的 <path /> 门路
        d: path("M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z");
      }

      &.pause { // 这里是播放状态下的 <path /> 门路
        d: path("M 12,26 16.33,26 16.33,10 12,10 z M 20.66,26 25,26 25,10 20.66,10 z");
      }
    }

基于 SMIL(即通过 <animate> 实现对<path> d 属性的动态控制):

  const pathMap = {
    from: "M 12,26 16.33,26 16.33,10 12,10 z M 20.66,26 25,26 25,10 20.66,10 z",
    to: "M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z"
  };
  <svg class="icon" viewBox="0 0 120 120" width="400" height="400">
    <path
      d="M 12,26 16.33,26 16.33,10 12,10 z M 20.66,26 25,26 25,10 20.66,10 z"
      fill="#000000"
    >
      <animate
        attributeName="d"
        from={play ? pathMap.from : pathMap.to}
        to={play ? pathMap.to : pathMap.from}
        dur="0.3s"
        begin="indefinite" // 这里设置开始工夫为有限以达到不自动播放的成果
        fill="freeze"
      />
    </path>
  </svg>

以上两个 path 门路的切换,就能够带来这种平滑过渡的成果。

知识点 2:
咱们看到的图形变幻,都须要遵循一个准则就是点数对齐准则,什么意思呢?咱们能够看上面的 demo,五角星到 10 边形(多边形画的不好,道歉 …😜)。,都是 10 个控制点到 10 个控制点的适度。所以成果平滑

而下图的 10 个点到 3 个点就没有这种平滑的过渡成果了 (当然当初很多的 SVG 动画框架曾经解决了这个问题。 见文末的框架举荐 )

3-2-3、描边动画的利用

CSS+SVG 实现的代码实际 - 星环

CSS+SVG 实现的代码实际 - LOGO 描边

基于 SMIL 实现的代码实际 - 进度环

总结 & 阐明

知识点 1:

相似的描边动画咱们能够拿来做很多成果,比方各种形态的进度条、比方文字的描边、比方霓虹灯流水灯光等等流动动画成果。而描边动画的外围点就在于 SVG 的两个显示属性别离是 stroke-dasharray、stroke-dashoffset,咱们上文说了,简直所有的显示属性都能够用 CSS 去管制,所以这种动画,倡议应用 CSS 去开发。

属性 值举例 形容 反对范畴
stroke-dasharray 1 3 4 4 它的值是一个序列,能够传入多个值,别离指定描边短线的长度和描边线间距,多个值顺次循环,如果传入 3 个值,相似于 stroke-dasharray: 1,2,3。则会主动复制一份再失效 <circle>, <ellipse>, <line>, <mesh>, <path>, <polygon>, <polyline>, <rect> <altGlyph>, <altGlyphDef>, <altGlyphItem>, <glyph>, <glyphRef>, <textPath>, <text>, <tref>, <tspan>
stroke-dashoffset 10 描边线段的起始地位间隔图形绘制终点的偏移量。正负值能够决定顺时针还是逆时针走向 跟 stroke-dasharray 统一

构想一个场景,一个倒计时须要从 100 到 0,对应的视觉效果也就是从全描边到无描边。那么咱们初始状态将 stroke-dasharray 的第一个值设为 2πr (周长),第二个值设也设为 2πr (周长)。那么咱们会失去一个整圆。

这时如果咱们把圆开展就能看到这样的场景


所以要实现进度的动态变化其实有两种计划
第一种是将 stroke-dasharray 的第一个值从 2πr(周长)调整到 0。原开展图中的彩色局部没有了(能够了解为变成了一个点如下图,看不见了),只剩下虚线局部是空白间隙了。

第二种是将 stroke-dashoffset 的值从 0 调整到 -2πr(或者减少到 2πr)。比照第一张图成下图的样子

知识点 2:
在理论开发中,咱们会遇到一些比较复杂的图形须要做描边,这个时候咱们没方法去失去它的周长是多少,这时候分两种场景解决。一种是在 CSS 里咱们能够将 stroke-dasharray 的第二个值设置成一个十分大的数字,而后再去调整第一个值比方:

    path {stroke-dasharray: 0(调整到适合的值) 99999999999999
    }

如果在 js 里咱们须要动静去获取周长的话,SVG 提供了原生的 api 能够去获取 path 的周长。

    const inPath = document.getElementById("inner-path");
    console.log(inPath.getTotalLength());

ps:有些材料说该办法只能用于 <path />,然而笔者亲测了在 safair 和 chrome 上,根本能够反对所有的根底图形以及<path />,然而<text /> 不反对,浏览器会报 not a function。

既然说到了getTotalLength(), 那么顺带说下getPointAtLength()。getPointAtLength,顾名思义就是依据间隔获取点坐标。意思就是依据到起始点的间隔,获取该指定间隔对应的点的坐标。坐标系原点为该图形的起始点。在一些指向型的动画上咱们可能会使用到这个 api。

3-2-4、轨迹静止动画的利用

基于 SMIL 实现的代码实际 - 轨迹静止

总结 & 阐明

{/* 咱们将整个飞机图形元件用 g 标签包起 */}
<g transform="translate(-100, -35) scale(0.1)">
  <path
    d="M164.485419 578.709313L196.274694 794.731891c0.722484 5.53904 8.188147 7.224835 11.078081 2.408278l75.860772-121.377234 740.063969-363.409219L164.485419 578.709313z"
    fill="#F68206"
  ></path>
  <path
    d="M2.167451 440.233302l159.668861 132.214487 857.828787-260.334901zM289.475071 679.375353l191.217309 153.407337 542.344309-518.743179z"
    fill="#FF9900"
  ></path>
  <path
    d="M204.222013 800.030103l125.23048-80.677328-48.888053-39.014111-76.342427 118.4873"
    fill="#D3650B"
  ></path>
  {/* 而后在这里,咱们利用 animateMotion,去做这个轨迹静止 */}
  <animateMotion
    path="M 0 450 Q 150 50 250 50 Q 350 0 400 50 Q 500 50 450 200 C 300 350 250 200 500 50 C 600 50 750 200 650 250 A 50 50 0 1 1 800 50"
    begin="0s"
    rotate="auto"
    dur="20s"
    repeatCount="indefinite"
  />
</g>

这里咱们用到了 SMIL 里的<animateMotion />,animateMotion 里的 path 属性,咱们也能够像这样去应用

    <defs>
        <path id="theMotionPath" d="xxx" />
    </defs>
    <animateMotion>
        <mpath xlink:href="#theMotionPath"/>
    </animateMotion>

理论生产中,咱们这种轨迹静止的需要,是倡议应用 SMIL 去实现的,当然 CSS 也是有实现计划的《应用 CSS offset-path 让元素沿着不规则门路静止》。然而 CSS 的兼容切实不敢恭维,劝退一波。

四、写在最初

1、倡议将 CSS 动画用于无变形的过渡或简略动画。尤其是在硬件加速时。CSS 不须要加载其余资源(个别指三方库),并且悬停时的小变换能够为交互带来更好的成果。特地是当你不须要 3d、物理体感、或进行大量重叠动画成果时倡议选用 CSS。另外,CSS 不便调试也是很大的一个劣势。

2、对于较长的动画,开发时会变得非常复杂且须要花精力去调试,而 CSS 调整时间尺度很艰难,尤其是当你须要操纵一些轻微帧时,集体感觉 SMIL 更适合做有序的,简单的重叠动画群的场景。

3、对于变形的动画,倡议应用 SMIL 或者第三方库。举荐的比拟优良的三方库有以下几个。

| 库名 | 形容 |
| — | — |
| GSAP | 全称是 GreenSock Animation Platform,以前风行用 flash 的时候,GSAP 就叱咤江湖的存在,GSAP 有两个版本一个是 flash 版本,一个是 javascript 版本,也就是咱们说的 GSAP js。GSAP 速度快。GSAP 专门优化了动画性能,使之实现和 css 一样的高性能动画成果;轻量与模块化;|
| Snap.svg、SVG.js、Velocity.js | 这三个库始终会被开发者拿来比照,基本上会用 jQuery,就会应用这三个库,也就是说动手敌对,Snap.svg 更偏差于反对古代浏览器,所以它的体量也会小一些。比照 Snap.svg 来看 SVG.js,SVG.js 的写法更加的清晰,应用时会有更好的体验,且自称提供靠近残缺的 SVG 标准笼罩。Snap.svg 格调就更像一个侠客,写起来会很洒脱然而不好读,Velocity 也很弱小,简略易用、高性能、功能丰富 |
| anime.js | anime.js 尽管性能没有 GASP 弱小,然而体积很乐观,gzip 压缩完只有 9kb 左右,满足日常需要开发还是足够的 |
| D3 | Data-Driven Documents 顾名思义,更加适宜用于创立数据可视化图形场景去应用 |

4、如何应用 SMIL 进行硬件加速,应用 <animateTransform>代替<animate>,并设置 x、y、z 值(z 为 0)。原理与 CSS 相似,这会将元素移到它本人的层,从而在其产生静止时不会从新绘制。

参考资料

  • SVG 动画指栏(SMIL)
  • SVG 教程
  • CSS 反对的 SVG 属性查寻
  • 以及文章内提及的一些文章

本文公布自 网易云音乐大前端团队,文章未经受权禁止任何模式的转载。咱们长年招收前端、iOS、Android,如果你筹备换工作,又恰好喜爱云音乐,那就退出咱们 grp.music-fe(at)corp.netease.com!

正文完
 0