浅谈前端实现动画效果的一些方式(包括但不限于)。
以下内容是我16年3月份在公司做内部分享时的一些内容,虽然时间有点远,但是我觉得还是比较适用的。
1. Flash,很久以前都会使用的一个方式,在十年以前甚至有很多用纯flash做的网站,我自己还做过一个,还是比较有意思的。到了中期,用flash来做动画效果后再引到html内,在html5 video之前也基本用flash的音视频播放器。现在基本已经弃用。
- 功能强大:动画、视频、播放器、特效等。
- 有flash的脚本语言ActionScript,简称AS。能做网页、能做事件交互、能够完成js做不了的BOM操作和本地操作等
- 移动端不兼容
- 过时-adobe已放弃-正式停止更新
2. GIF图片
- 兼容性最好
- 画质差,PNG有毛边
- 无交互、图片大
- 前端人员不太擅长制作
3.javascript 定时器动画 setInterval setTimeout
定时器:实现上就是通过一个定时器setInterval 每隔一定时间来改变元素的样式,动画结束时clearInterval即可。早期的类库包括 jquery、prototype等等都是这种方式。在CSS3之前,最初的前端动画大多都是JS来实现。
- 使用简单,可以交互,可控性很强,兼容好
- 性能不佳,因为需要不断获取和修改Dom的布局,所以导致了大量页面重绘
- 缺乏标准,不同的库使用了不同的API,导致即使是简单的动画也有各不相同的实现方式
- 复杂和长时间的定时器在移动端效果不稳定
- 定时器不靠谱:setInterval多个间隔可能会被跳过,setInterval多个间隔可能比预期小,不同浏览器的精度不同
4. css3动画
transition过渡:顾名思议,可以实现一些简单的不需要太多的控制与步骤的过渡动画。
animation动画:与transition不同的是,animation属性可以像FLASH制作动画一样,通过关键帧控制动画的每一步,实现更为复杂的效果。并且功能更强大。
css3动画相比与JS动画更轻量,性能更好,更易于实现。animation相比 transtion 使用起来更为复杂,但也提供了更多的控制。
css3动画缺点:不同的动画无法实现同步,多个动画彼此无法堆叠,复杂的动画编辑麻烦,低版本兼容性不好。
关于CSS3动画,网上案例太多,就不细说了。
5.SVG实现动画
svg动画能够实现的:
- 动画元素的数值属性(X, Y, …)
- 动画属性变换(平移或旋转)
- 动画颜色属性
- 沿着运动路径运动
前面的三条CSS3都是可以有所担当的,最后这一条,呵呵。
示例1:
<svg width="120" height="420" >
<rect x="10" y="10" width="100" height="100">
<animate attributeType="XML"
attributeName="y"
from="-100" to="120"
dur="5s"
repeatCount="1"
fill="remove"/>
</rect>
</svg>
attributeType:CSS|XML|auto,变化的是属性还是CSS还是自动匹配,可以省
attributeName:要变化的元素属性名称,也可以是CSS名称
from:开始值
to:结束值
repeatCount:表示动画执行次数,可以是合法数值或者无限“indefinite”
dur:动画时间,常见单位有 "h"|"min"|"s"|"ms"
fill:表示动画结束状态。支持参数有:freeze | remove. 其中remove是默认值,表示动画结束直接回到开始的地方。freeze“冻结”表示动画元素保持了动画结束之后的状态。
不写form to的情况下,可以写values="300;200;300"
示例2:多个变化一起
<svg width="800" height="300" >
<g transform="translate(100,100)" >
<text id="TextElement" x="0" y="0"
font-family="Verdana" font-size="35.27" visibility="hidden" >
It's alive!
<set attributeName="visibility" attributeType="CSS" to="visible"
begin="1s" dur="6s" fill="freeze" />
<animateMotion path="M 0 0 L 100 100"
begin="1s" dur="6s" fill="freeze" />
<animate attributeName="fill" attributeType="CSS"
from="rgb(0,0,255)" to="rgb(128,0,0)"
begin="1s" dur="6s" fill="freeze" />
<animateTransform attributeName="transform" attributeType="XML"
type="rotate" from="-30" to="0"
begin="1s" dur="6s" fill="freeze" />
<animateTransform attributeName="transform" attributeType="XML"
type="scale" from="1" to="3" additive="sum"
begin="1s" dur="6s" fill="freeze" />
</text>
</g>
</svg>
set:是animate的简化,主要用来改变非数值属性的属性值。
begin:延时开始
animateMotion:沿某运动路线移动SVG元素。
additive控制动画是否附加。支持参数有:replace | sum. 默认值是replace.
示例3:延着某一路径
<body>
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
<text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">马
<animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" repeatCount="indefinite"/>
</text>
<path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
<text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">马
<animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" rotate="auto" repeatCount="indefinite"/>
</text>
<path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
<svg width="5cm" height="3cm" viewBox="0 0 500 300">
<path id="path1" d="M100,250 C 100,50 400,50 400,250"
fill="none" stroke="blue" stroke-width="7.06" />
<circle cx="100" cy="250" r="17.64" fill="blue" />
<circle cx="250" cy="100" r="17.64" fill="blue" />
<circle cx="400" cy="250" r="17.64" fill="blue" />
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" fill="yellow" stroke="red" stroke-width="7.06" >
<animateMotion dur="6s" repeatCount="indefinite" rotate="auto" >
<mpath xlink:href="#path1"/>
</animateMotion>
</path>
</svg>
</body>
通过将 rotate="auto" ,用来控制是否自动旋转
示例4:SVG结合CSS3做点有意思的事情:
<style>
* {
margin: 0;
padding: 0;
}
path {
stroke-dasharray:44;animation: dash 5s linear infinite;
}
@keyframes dash {
to {
stroke-dashoffset: 1000;
}
}
</style>
</head>
<body>
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
</body>
和
<style>
* {
margin: 0;
padding: 0;
}
path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear infinite;
}
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
</style>
</head>
<body>
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
<path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
</body>
svg动画总结
- svg可以实现比DIV更复杂的图形,所以也可以实现更复杂的动画
- svg DOM结构可以被其特定语法(animate)或者Javascript控制,从而轻松的实现动画
- 整个SVG作为一个动画,并且动画复杂编辑麻烦
- 效率不高,而且如果其结构多而杂,就更慢
- 浏览器兼容性不好,IE8-以及Android 2.3以下是不支持SVG,移动端未测
html5 的canvas、webgl,只是增加了绘画方式的选择,与动画的怎么变化无关,没有实现动画的API,你必须依靠定时器和其他事件来更新画布。所以与本次说的主题动画无关。但是html5也提供了一个新的动画接口....
6.RAF
性能更好的js动画实现方式——requestAnimationFrame。
前面说过,JS定时器有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。这个时候,就该requestAnimationFrame出马了。
这专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前低版本安卓上并不支持,不过未来全面支持这已经是大势所趋。
<body>
<div id="box" style="width:1px;height:100px; background:red"></div>
<script>
var oBox=document.getElementById('box');
var w=1,id;
function render(t){
console.log(t);//返回的间隔时间
w++;
oBox.style.width=w+'px';
if(w<500)id=requestAnimationFrame( render );
console.log(id);
};
id=requestAnimationFrame( render );
oBox.onclick=function(){
cancelAnimationFrame(id); //通过id停止
};
</script>
</body>
是不是看起来很简单就可以实现。
- requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率约为每秒60帧(每帧约16MS)。
- 如果页面不是激活状态下或在隐藏或不可见的元素中,将不会进行重绘,这当然就意味动画会自动暂停,有效节省了cpu和内存使用量。
- 原理其实也就跟定时器差不多,通过递归调用同一方法来不断更新画面以达到动起来的效果,但它优于定时器的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用。
- 所以,可以这么说,requestAnimationFrame就是一个性能优化版、专为动画量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回调函数运行的时间。
- 在前几年各个支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。
*总结:
无论何种需求,首选RAF
轻量级简单动画用css3
复杂动画效果CSS3不能满足的情况下用JS定时器
以上都无法满足的情况下还是网上找相应的动画库吧(js库、css3库、svg动画库)*
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。