前端必备神器 Snap.svg 弹动效果


Posted in Javascript onNovember 10, 2014

有人说不会 SVG 的前端开发者不叫开发者,而叫爱好者。前端不光是 Angularjs 了,这时候再不学 SVG 就晚了!(如果你只会 jQuery 就当我没说。。。)这里我就给大家分享一个前几天在别处看到的一个高大上的 SVG 效果,左边菜单弹出来会动动弹的说,链接点这里。

当时我就震惊了,今天抽空搞清了源码,然后下面是我潜心研究后做出来的 Demo,虽然比较粗糙,但还是很洋气的感觉呢。下面我就这个 DEMO 跟大家分享一下。

http://jsfiddle.net/windwhinny/n6w1ur5k/3/

本案例需要有些 PS 或者 AI 中路径的知识,下面是本例中运涉及到的知识点和工具:

snap.svg
svg path data
Adobe Illustrator
animation timing

先给出原理:根据时间变换坐标。如下图所示,本例其实就是 A、B、C 三条线之间的转换,A 是初始状态,点击后经过 B 最后形成 C。其中有两次动画,分别是 A-B 和 B-C,而这两次动画的 timing function 和时间都是不同的。

前端必备神器 Snap.svg 弹动效果

第一步:画草稿

做动画前第一步就是画草稿(如上图),我一般用 AI 来画,因为 AI 可以精确的控制元素尺寸和位置,而且其原理和 SVG 是一样的。

然后有的同学就会说,“老湿,是不是要保存为 SVG 格式的,然后做修改啊?”

画草稿图的目的只是为了方便的确定每个点的坐标,自己算太麻烦了,而且还容易出错。除此之外 AI 没有任何作用。AI 生成的 SVG 文件在此例中根本不能拿来用,因为其中的路劲点太混乱了,下面会详说。

什么?你不会用 AI ?

如果你还想在前端这条路上走下去的话,那现在就去学吧。(在这里我想吐槽一下,PS 是用来处理点阵图片的,根本不适合拿来做设计图。相比之下 AI 才是做这个的,google 给出的 metrial design 布局模板全都是 AI 格式的。但国内不管是什么企业,用 PS 都好像很开心的样子,不知道为什么。)

第二步:计算路径

这一步就比较复杂了,上面说过了,这个动画其实就是坐标之间转换。而从四边形到圆弧之间的转换不光是坐标位移而已,还有曲线弧度的转换。上面的设计图直接保存为 SVG 后代码如下:

<?xml version="1.0" encoding="utf-8"?>

<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->

<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"

     viewBox="0 0 175 175" enable-background="new 0 0 175 175" xml:space="preserve">

<!-- 路径 A -->

<path fill="none" stroke="#BF3A41" stroke-miterlimit="10" d="

    M12.5,12.5

    h75

    h75

    v75

    v75

    h-75

    h-75

    v-35

    V12.5z"/>

<!-- 路径 B -->

<path fill="none" stroke="#0000FF" stroke-miterlimit="10" d="

    M37.5,37.5

    c0,0,10-25,50-25

    s50,25,50,25

    s25,10,25,50

    s-25,50-25,50

    s-10,25-50,25

    s-50-25-50-25

    s-25.1-10-25.1-50

    S37.5,37.5,37.5,37.5z"/>

<!-- 路径 C -->

<path fill="none" stroke="#000000" stroke-miterlimit="10" d="

    M37.5,37.5

    h50

    h50

    v50

    v50

    h-50

    h-50

    v-50

    V37.5z"/>

</svg>

我们只需要关注路径的 d 属性就行了,可以看出,AB 两个路径之间还是可以互相转换的,但他们和 C 路径(有弧线的路径)之间就不能转换了。他们所用到的绘图命令都不同,AB 两个都是矩形,绘图时用到的都是 h、v,也就是横纵之间的位移,画出来的都是横竖线。而 C 路劲用到的都是 s、c这些命令,画出来的都是曲线。所以 AI 给出来的图我们不能用,要自己根据 svg path data 重新绘制一遍。

下面我参照 AI 设计图重新绘制的三条路径:

<!-- 路径 A -->

<path d="

    M37.5,37.5

    S87.5,37.5,87.5,37.5

    S137.5,37.5,137.5,37.5

    S137.5,87.5,137.5,87.5

    S137.5,137.5,137.5,137.5

    S87.5,137.5,87.5,137.5

    S37.5,137.5,37.5,137.5

    S37.5,87.5,37.5,87.5

    S37.5,37.5,37.5,37.5z">

<!-- 路径 B -->

<path d="

    M 37.5,37.5

    S47.5,12.5,87.5,12.5

    S127.5,25,137.5,37.5

    S162.5,47.5,162.5,87.5

    S150,127.5,137.5,137.5

    S127.5,162.5,87.5,162.5

    S47.5,150,37.5,137.5

    S12.5,127.5,12.5,87.5

    S25,47.5,37.5,37.5z">

<!-- 路径 C -->

<path d="

    M12.5,12.5

    S87.5,12.5,87.5,12.5

    S162.5,12.5,162.5,12.5

    S162.5,87.5,162.5,87.5

    S162.5,162.5,162.5,162.5

    S87.5,162.5,87.5,162.5

    S12.5,162.5,12.5,162.5

    S12.5,127.5,12.5,127.5

    S12.5,12.5,12.5,12.5z">

有过设计基础的同学应该明白上面代码的含义,就是将所有锚点转换成平滑,然后再更改手柄的位置。形状没变,虽然代码多了不少,但是把绘制命令都变成了 S ,这样三条路径就只有数值之间的不同了。而动画的过程就是数值之间的转换。

第三步:Timing

这一步就是设定动画的时间点和 timing function 。时间点比较好说,A-B 和 B-C 我设置的分别是300毫秒和400毫秒。

timing function 就是我们在做 CSS 动画中运用到的 animation-timing-function 属性,比较常见的有 ease、linear、easein,我们也可以用贝塞尔曲线自己定制。但是CSS的 timing function 比较简单,只能定义一条均匀的曲线,A-B 转换用到的 ease-out,但是 B-C 为了体现弹动的效果,所用到的 timing-function 就不是一条均匀曲线这么简单了。

前端必备神器 Snap.svg 弹动效果

上面列出了一些比较常用的 timing-function ,其中大概分为 ease、bounce、elastic 三类。ease 一般用作减速或者加速动效。bounce如同他的曲线图一样,一般用作小球落地那种动效。而 elastic 一般用在如琴弦一样的动效上,这种动效一个特点就是有部分偏移到负坐标上了,而 B-C 用到的就是这个,如下图。

前端必备神器 Snap.svg 弹动效果

根据上面已经画出来的路径,结合动画,代码就出来了:

var svg=Snap("#svg");

var pathes=[

    "M37.5,37.5S87.5,37.5,87.5,37.5S137.5,37.5,137.5,37.5S137.5,87.5,137.5,87.5 S137.5,137.5,137.5,137.5S87.5,137.5,87.5,137.5S37.5,137.5,37.5,137.5S37.5,87.5,37.5,87.5S37.5,37.5,37.5,37.5z",

    "M 37.5,37.5 S47.5,12.5,87.5,12.5 S127.5,25,137.5,37.5 S162.5,47.5,162.5,87.5 S150,127.5,137.5,137.5 S127.5,162.5,87.5,162.5 S47.5,150,37.5,137.5 S12.5,127.5,12.5,87.5 S25,47.5,37.5,37.5z",

    "M12.5,12.5S87.5,12.5,87.5,12.5S162.5,12.5,162.5,12.5S162.5,87.5,162.5,87.5S162.5,162.5,162.5,162.5S87.5,162.5,87.5,162.5S12.5,162.5,12.5,162.5S12.5,127.5,12.5,127.5S12.5,12.5,12.5,12.5z"

];
var path=svg.path(pathes[0]);
path.attr({

    fill:"#2E70FF"

});
function animateIn(callback){

    path.animate({

        d:pathes[1]

    },300,mina.easeout,function(){

        path.animate({

            d:pathes[0]

        },400,mina.elastic,callback)

    });

};
function animateOut(callback){

    path.animate({

        d:pathes[1]

    },300,mina.easeout,function(){

        path.animate({

            d:pathes[2]

        },400,mina.elastic,callback)

    });

};

Snap 是 Adobe 出品处理 SVG 的库,mina是 Snap 自带的一个动画工具集,其中有很多预设的动画。

结语

用 Snap 制作的动画可以兼容 IE9 ,而且速度也不错,自定义功能很强大。相信不久的将来还会有更多狂拽酷炫?耪ㄌ斓亩?Щ嵊 Snap 制作出来。

如果想学习动效的话,可以先看一下 TED 一集关于动效的视频

Javascript 相关文章推荐
清华大学出版的事半功倍系列 javascript全部源代码
May 04 Javascript
浏览器脚本兼容 文本框中,回车键触发事件的兼容
Jun 21 Javascript
JavaScript 匿名函数和闭包介绍
Apr 13 Javascript
js将json格式的对象拼接成复杂的url参数方法
May 25 Javascript
JS简单获取客户端IP地址的方法【调用搜狐接口】
Sep 05 Javascript
简单介绍react redux的中间件的使用
Apr 06 Javascript
vue2.0 可折叠列表 v-for循环展示的实例
Sep 07 Javascript
AjaxFileUpload.js实现异步上传文件功能
Apr 19 Javascript
Jquery异步上传文件代码实例
Nov 13 jQuery
vue keep-alive列表页缓存 详情页返回上一页不刷新,定位到之前位置
Nov 26 Javascript
vue实现防抖的实例代码
Jan 11 Vue.js
vue实现简易音乐播放器
Aug 14 Vue.js
浅谈JavaScript 框架分类
Nov 10 #Javascript
使用script的src实现跨域和类似ajax效果
Nov 10 #Javascript
jquery插件推荐 jquery.cookie
Nov 09 #Javascript
jquery插件推荐浏览器嗅探userAgent
Nov 09 #Javascript
Javascript限制网页只能在微信内置浏览器中访问
Nov 09 #Javascript
js闭包的用途详解
Nov 09 #Javascript
js闭包实例汇总
Nov 09 #Javascript
You might like
Smarty的配置与高级缓存技术分享
2012/06/05 PHP
基于php中使用excel的简单介绍
2013/08/02 PHP
PHP工厂模式简单实现方法示例
2018/05/23 PHP
php+Ajax处理xml与json格式数据的方法示例
2019/03/04 PHP
读JavaScript DOM编程艺术笔记
2011/11/15 Javascript
jQuery性能优化28条建议你值得借鉴
2013/02/16 Javascript
Javascript倒计时页面跳转实例小结
2013/09/11 Javascript
jQuery标签替换函数replaceWith()的使用例子
2014/08/28 Javascript
js获取内联样式的方法
2015/01/27 Javascript
JS中用EL表达式获取上下文参数值的方法
2018/03/28 Javascript
JS中的算法与数据结构之链表(Linked-list)实例详解
2019/08/20 Javascript
合并百度影音的离线数据( with python 2.3)
2015/08/04 Python
对Python的Django框架中的项目进行单元测试的方法
2016/04/11 Python
Python中函数eval和ast.literal_eval的区别详解
2017/08/10 Python
PyQt5实现下载进度条效果
2018/04/19 Python
详解Django中间件执行顺序
2018/07/16 Python
对python添加模块路径的三种方法总结
2018/10/16 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
详解Python对JSON中的特殊类型进行Encoder
2019/07/15 Python
django 快速启动数据库客户端程序的方法示例
2019/08/16 Python
Python列表原理与用法详解【创建、元素增加、删除、访问、计数、切片、遍历等】
2019/10/30 Python
python能自学吗
2020/06/18 Python
用HTML5中的Canvas结合公式绘制粒子运动的教程
2015/05/08 HTML / CSS
Html5让容器充满屏幕高度或自适应剩余高度的布局实现
2020/05/14 HTML / CSS
二年级体育教学反思
2014/01/15 职场文书
运动会800米加油稿
2014/02/22 职场文书
教师反腐倡廉演讲稿
2014/09/03 职场文书
人身意外保险授权委托书
2014/10/01 职场文书
2015年党风廉政建设目标责任书
2015/05/08 职场文书
学历证明样本
2015/06/16 职场文书
教师听课学习心得体会
2016/01/15 职场文书
2016年小学端午节活动总结
2016/04/01 职场文书
LayUI+Shiro实现动态菜单并记住菜单收展的示例
2021/05/06 Javascript
matlab xlabel位置的设置方式
2021/05/21 Python
python中的class_static的@classmethod的巧妙用法
2021/06/22 Python
MySQL学习必备条件查询数据
2022/03/25 MySQL