svg动画类库Snap.svg简介

SVG元素是一种特殊的DOM元素,可以使用CSS以及一般的JS类库来实现动画控制。但是这些方法都没提供SVG动画样式属性的完整控制,现在介绍一个专门的SVG动画类库Snap.svg,其github地址为:https://github.com/adobe-webplatform/Snap.svg

安装

Snap.svg提供多种安装方式。

HTML直接加载JS方式

<script src="snap.svg-min.js"></script>
// Manual Minified - https://github.com/adobe-webplatform/Snap.svg/raw/master/dist/snap.svg-min.js
// Manual Unminified - https://raw.githubusercontent.com/adobe-webplatform/Snap.svg/master/dist/snap.svg.js
//注意:上面url直接添加到src无法正常下载
//错误信息:Refused to execute script from 'https://.../snap.svg-min.js' because its MIME type ('text/plain') is not executable.
//是服务端返回类型错误,浏览器无法解析。可以手工下载到本地使用。

webpack加载方式

// 支持npm或者bower下载
bower install snap.svg
npm install snapsvg
// webpack配置
module: {
  rules: [
    {
      test: require.resolve('snapsvg/dist/snap.svg.js'),
      use: 'imports-loader?this=>window,fix=>module.exports=0',
    },
  ],
},
resolve: {
  alias: {
    snapsvg: 'snapsvg/dist/snap.svg.js',
  },
},
// 引用
import Snap from 'snapsvg';

Snap.svg动画基本实现步骤

// 1、在HTML中添加SVG
<svg id="demo1" width="300" height="300"></svg>

// 2、SVG中图形元素初始化
let svg = Snap('#demo1');
let circle = svg.select('.circle'); //如果SVG中已有实际图形元素,直接选择器初始化
let circle = svg.circle(150, 150, 10);//如果SVG中没有实际图形元素,调用方法创建化

// 3、修改属性和时间参数,实现动画设置。例如一秒钟内,圆半径变为100px
circle.animate({ r: 100 }, 1000, mina.easeout(), () => {
    //动画结束,doSomething
  });

Snap.svg常用API介绍

Snap(...)

功能描述: 创建或加载已有的SVG元素。
参数说明:

参数形式 参数类型 参数说明 备注
(width, height) 数字 创建新SVG的宽和高
(DOM) 对象 根据DOM对象加载SVG
(arry) 数组 根据元素数组返回SVG元素数组
(query) 字符串 根据JS选择器加载SVG

返回值: SVG元素

Element.select(query)

功能描述: 根据JS选择器加载SVG元素内已有的图形元素。
参数说明:

参数形式 参数类型 参数说明 备注
query 字符串 图形元素JS选择器定义

返回值: 选择器命中的元素Element,当存在多个命中的元素时,只返回第一个元素

Paper.circle(x, y, r)

功能描述: 在SVG元素内绘制一个圆。
参数说明:

参数形式 参数类型 参数说明 备注
x 数字 圆心X轴坐标
y 数字 圆心X轴坐标
r 数字 半径

返回值: 新建的circle元素Element

Paper.path([pathString])

功能描述: 在SVG元素内绘制一条Path。
参数说明:

参数形式 参数类型 参数说明 备注
pathString 字符串 path的d属性值

返回值: 新建的path元素Element

Paper.rect(x, y, width, height, [rx], [ry])

功能描述: 在SVG元素内绘制一个矩形。
参数说明:

参数形式 参数类型 参数说明 备注
x 数字 矩形左上角X轴坐标
y 数字 矩形左上角Y轴坐标
width 数字 矩形宽度
height 数字 矩形高度
rx 数字 圆角的水平半径
ry 数字 圆角的垂直半径

返回值: 新建的rect元素Element

Snap.animation(attr, duration, [easing], [callback])

功能描述: 在一段时间内匀速变更相关属性到目标值。
参数说明:

参数名称 参数类型 参数说明 备注
attr 对象 属性目标值
duration 数字 动画持续总时长,单位MS
easing 函数 自定义或者mina定义的缓动函数 控制移动速度是匀速还是加减速
callback 函数 动画结束时回调函数

返回值: 动画对象

Snap.animate(from, to, setter, duration, [easing], [callback])

功能描述: 根据设置的参数,执行动画操作。
参数说明:

参数名称 参数类型 参数说明 备注
from 数字/数组 动画的启始帧数
to 数字/数组 动画的结束帧数
setter 函数 动画帧设置参数,该函数可传入当前帧数
duration 数字 动画持续总时长,单位MS
easing 函数 自定义或者mina定义的缓动函数
callback 函数 动画结束时回调函数

返回值: mina格式的动画对象

Matrix.translate(x, y)

功能描述: 执行位移操作。
参数说明:

参数名称 参数类型 参数说明 备注
x 数字 水平移动距离,单位是像素
y 数字 垂直移动距离,单位是像素

Matrix.rotate(a, x, y)

功能描述: 使推行围绕指定的圆心,旋转一定角度。
参数说明:

参数名称 参数类型 参数说明 备注
a 数字 旋转角度,单位是度
x 数字 旋转圆心的水平位置,单位是像素
y 数字 旋转圆心的垂直位置,单位是像素

常见动画效果的示例

尺寸缩放

初始化参考上面“基本实现步骤”中的相关描述,后续只描述动画控制部分。

// 圆形半径缩放,在1S内半径从10,放大到100,动画效果是缓出
let circle = svg.circle(150, 150, 10);
circle.animate({ r: 100 }, 1000, mina.easeout(), () => {
    //动画结束,doSomething
  });

// 矩形长宽缩放,在2S内宽度100缩小到10,长度200缩小到20,动画效果是缓入
let rect = svg.circle(0, 0, 100, 200);
rect.animate({ width: 10, height:20 }, 2000, mina.easein(), () => {
    //动画结束,doSomething
  });

颜色渐变

// 圆形填充色渐变,3S内从绿色变成蓝色,动画效果是缓出
let circle = svg.circle(150, 150, 100).attr({
    fill: "#bada55",
    stroke: "#000",
    strokeWidth: 5
});
circle.animate({ fill: "#0059b3", }, 3000, mina.easeout(), () => {
    //动画结束,doSomething
  });

线条渐变

// 1S内线条从起始态变换到终止态,动画效果是缓出
// 起始态:任意形状
let path = svg.paper.path({d: 'M0.500,65.500 C18.680,33.758 45.141,-6.797 72.500,2.500 C99.859,11.797 72.148,59.027 79.500,98.500 C86.852,137.973 117.668,128.914 138.500,59.500 C159.332,-9.914 246.500,59.500 246.500,59.500 C273.181,117.750 137.350,184.417 225.500,173.500 C351.137,157.940 155.369,160.617 162.500,86.500 C165.180,58.645 237.169,-2.418 283.500,2.500 C357.654,10.371 363.758,80.355 364.500,109.500',stroke:'#f00', fill: 'rgba(0,0,0,0)'});

// 终止态:心形
path.animate({d: 'M114.500,58.500 C106.230,58.751 23.907,-37.262 5.500,21.500 C-26.759,124.483 111.761,221.360 119.500,219.500 C154.464,211.096 201.234,149.580 220.500,104.500 C250.260,34.864 220.892,7.159 194.500,1.500 C160.455,-5.800 122.344,58.262 114.500,58.500 Z'}, 1000, mina.easeout(), () => {
  //动画结束,doSomething
});

位置移动

// 1S内矩形移动100次,从(0,0)移动到(100,200),动画效果是缓出
let rect = svg.paper.rect({x: 0, y: 0, width: 50, height: 30, fill: '#f00'});

Snap.animate(0, 100, (val) => {
    let m = new Snap.Matrix();
    m.translate(val, val * 2); // translate位移API
    rect.transform(m);  // 在rect节点应用matrix
  }, 1000, mina.easeout(), () => {
  //动画结束,doSomething
});

位置移动

// 1S内矩形围绕矩形的中心旋转100次,完成旋转一周,动画效果是缓出
let rect = svg.paper.rect({x: 10, y: 10, width: 50, height: 30, fill: '#f00'});

Snap.animate(0, 100, (val) => {
    let m = new Snap.Matrix();
    m.rotate((val/100)*360,  35, 25);  // 注意,旋转中心是矩形的中心
    rect.transform(m);  // 在rect节点应用matrix
  }, 1000, mina.easeout(), () => {
  //动画结束,doSomething
});

参考资料

《Snap.svg API文档》
《使用 Snap.svg 制作动画》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容