目标:
示例1:希望①旋转并②波纹扩散效果。
示例2:希望重新定义仪表盘组件。即根据数值,显示圆形进度条。
实现SVG动画的三种方式
方式1:SMIL语言
特点
- 用SVG元素标签来描述动画。
- 仅嵌入SVG使用。
- Synchronized Multimedia Integration Language(同步多媒体集成语言)。
动画标签
<set>
瞬间动画。虽然没有动画过度效果。但可实现延迟功能,类似setTimeout。<animate>
用于实现单属性的动画效果。<animateColor>
颜色发生动画效果(被animate替代)<animateTransform>
变形类动画<animateMotion>
沿着某个路径运动
各标签自由组合,作用同一个元素。
标签的位置
位置1,作为需要动画SVG元素标签的子元素。
位置2,放到任意位置,只需要利用xlink:href = ‘#id’ 做关联即可,需要做如下配置:
- svg标签中引入属性「xmlns:xlink = “http://www.w3.org/1999/xlink"」
- 对动画标签设置动画元素 「xlink:href=”#动画元素的id “ 」
方式2:CSS3
特点
- 用css样式描述动画。
- 嵌入SVG或外部css文件均可。
使用示例
1 |
|
方式3:JavaScript
特点
- 直接用js来操作svg(dom)。
- 利用第三方js库操作svg(dom):Snap.svg、Velocity.js、anime.js等。
- 单独的js文件。
- Snap.svg是使用比较多的库。但是引用起来有点费事。
- 循环动画,需要借助js setInterval来实现。
- 如果只是简单的动图,没必要使用js。
使用示例
1 | npm install snapsvg |
SVG动画的三种重要种类
核心概念
svg动画的核心概念是路径path。path就是一条线,是直线,或者曲线,虚线或者实线。一个path长这样【请学习svg基础】——
M113,318c-50.7-1.8-74.3-24.8-81-32C6.7,258.7,8.1,224.2,11,155z
一个简单path标签长这样——
<path d="M113,318c-50.7-1.8-74.3-24.8-81-32C6.7,258.7,8.1,224.2,11,155z" />
path具有如下线的属性:
- stroke:颜色,stroke=”green”。
- d:线条的形状。
- stroke-width:宽度,单位是 px。
- stroke-dasharray:定义形成一条虚线。stroke-dasharray=”5, 15” 表示,按照 实线dash为 5,间隔gap为 15 的排布重复下去。值可以为 number || percentage。
- stroke-dashoffset:设置 dasharray 定义的 dash 线条开始的位置。值可以为 number || percentage。
- stroke-linecap: 线条的端点样式。
- stroke-linejoin: 线条连接的样式
SVG预定义的六种基本形状: rect、circle、ellipse、line、polyline、polygon 都可以转换为path路径,从而实现动画。这篇文章提供了转换函数https://aotu.io/notes/2017/01/16/base-shapes-to-path/index.html
类型1:描边动画/划线动画
参见下文示例2的实现。
实现方式
- 方式1:【推荐】css3的stroke-dasharray和stroke-dashoffset。
- 方式2:SMIL的
<animate>
标签。
具体实现
描边动画有个核心问题:获取边的总长度。比如示例2中,需要获得圆盘的总长度。因为svg本身就是dom元素,可用js获取:document.getElementById('路径path的id').getTotalLength()
。
CSS3
css3实现实线描边有两种方式,假设获得总长度369px。
方式一、利用stroke-dasharray和stroke-dashoffset。调整线的偏移量即可。
1 | #path1 { |
方式二、纯利用stroke-dasharray。调整实线dash的大小即可。
1 | #path { animation: process 3s linear forwards; } |
animate
<animate>
可以通过改变样式属性来处理。
1 | <animate |
类型2:路径动画
让元素沿着某条路径进行运动。参见下文示例1的实现。
实现方式
- 方式1:【推荐】SMIL的
<animateMotion>
标签。 - 方式2:CSS3 的offset-path和offset-distance样式。
css3虽然操作顺手,但浏览器兼容性没有<animateMotion>
好。而且,因为path本身是svg内部的元素,而路径轨迹动画本身依赖于路径。因此直接<animateMotion>
比css更稳定方便。
具体实现
animateMotion
1 | <g> |
css3
1 | .ball { |
类型3:变形动画
实现方式
- 方式1:【推荐】CSS3 的transform。
- 方式2:SMIL的 animateTransform。
两种方法都有如下属性:
- translate
- rotate
- scale
- skew
- 等
具体实现
在css和svg本身的属性中,都具备这几种变形。但是,他们坐标系不同。
- css以元素本身的中心点作为坐标原点进行变形。并且css可以通过transform-origin自定义原点。
- svg以整个svg的左上角(0,0)为原点变形。当执行svg的scale时,x,y的位置也会跟着缩放。
animateTransform
1 | <animateTransform |
css3
1 | #innerCircle, #outerCircle, #middleCircle { |
目标示例的具体实现
- 静态SVG图片本身由UI利用sketch或者Adobe Illustrator工具绘制。
- 动态SVG效果,由开发人员利用代码自行处理。
- 动画所沿路径path也可以由UI利用工具帮助勾勒。
示例1:①旋转并②波纹扩散
波纹:css的scale变换。变换动画。
1 | // 静态波纹本身,由UI提供 |
运动:animateMotion标签。路径动画。
1 | // 三个棋子要走的路线path,可由UI工具勾勒 |
示例2:定义仪表盘组件。根据数值,显示圆形进度条。
此图利用stroke-dasharray实现。描边动画。
注意,总长度可由document.getElementById('路径path的id').getTotalLength()
取得。
此处为:document.getElementById(‘进度条高亮’).getTotalLength() = 365
1 | // 定义百分比 |