通常在前端中,实现动画的方案主要有6种:
- CSS3 transition;
- CSS3 animation;
- javascript直接实现;
- .jQuery的animate()API;
- requestAnimationFrame;
- SVG(可伸缩矢量图形);
- Canvas动画;
首先,我们来搭一个基本结构框架:
<style> div { position: relative; background: #999; width: 50px; height: 50px; } .animat{ } </style> <body> <div class="animat"></div> </body>
CSS3 transition
transition是过度动画。但是transition只能在某个标签元素样式或状态改变时进行平滑的动画效果过渡,而不是马上改变。
transition是渐变的意思,就是某个属性 从一个值逐渐变成另一个值,比如width:从50px,到200px
基本表达式 transition: transition-property transition-duration transition-timing-function transition-delay
- transition-property :需要做缓动的属性,默认值为all,就表示所有可以缓动的属性都做缓动动画
- transition-duration : 整个缓动动画的持续时间,比如1s 就是1秒
- transition-timing-function : 缓动动画的呈现速度方式,默认值为ease,即 先慢再快再慢,还有linear(匀速)等其他方式
- transition-delay : 延迟执行动画时间
示例
.animat{ transition:width 2s; -moz-transition:width 2s; /* Firefox 4 */ -webkit-transition:width 2s; /* Safari and Chrome */ -o-transition:width 2s; /* Opera */ } .animat:hover{ width:300px; }
完整代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> div { width:100px; height:100px; background:red; position:absolute; } } .animat{ transition:width 2s; -moz-transition:width 2s; /* Firefox 4 */ -webkit-transition:width 2s; /* Safari and Chrome */ -o-transition:width 2s; /* Opera */ } .animat:hover{ width:300px; } </style> </head> <body> <div class='animat'></div> </body> </html>
这个动画呈现效果是:当鼠标移动到div上的时候,执行width 改变动画。
很多其他的一些属性也可以,比如left,opacity 等等,这里不做赘述。
CSS3 animation
语法:
animation: name duration timing-function delay iteration-count direction;
name:keyframe的名称,也就是定义了关键帧的动画的名称,这个名称用来区别不同的动画。
duration:完成动画所需要的时间(2s 或者 2000ms)
timing-function:完成动画的速度曲线
delay:动画开始之前的延迟
iteration-count:动画播放次数
direction:是否轮流反向播放动画(normal:正常顺序播放,alternate下一次反向播放)如果把动画设置为只播放一次,则该属性没有效果。
使用animation属性制作动画可以更加灵活的设置动画帧,通过不同keyframe(动画帧)的设置,实现很多优雅的效果,keyframe中的百分数是动画完成总时间的比例。
animation是设置总的动画效果,而keyframe中设置上相应的动画名字,然后在keyframe中设置具体的动画效果。当然由于是css3的属性,仍然需要注意它的兼容性,加上必须的前缀。
keyframes
包含两部分,第一个是使用animation属性,第二部分是:用@keyframes定义动画
示例
.animat{ animation: testAni 2s infinite alternate; } /*infinite表示动画一直循环播放*/ /*alternate表示动画下一次反向播放*/ @keyframes testAni { 0% { width:100px; } 30% { width:200px; } 100% { width: 500px; } }
0% 表示最开始,30%,表示整个动画时间的30%, 100% 表示结束,
中括号里面就是需要呈现动画的属性。
注:动画优化:1)因为动画改变的太频繁,所以我们最好用position:absolute或fixed的方式把元素脱离文档流,避免频繁重绘;
2) 如果是定位属性:比如left,top等等,可以用transform:translate()的方式来替代,这样性能更好.
注:transition适合于一次性的呈现动画,animation适合多次 或者需要控制中间过程的动画.
javascript 直接实现动画
其主要思想是通过setInterval或setTimeout方法的回调函数来持续调用改变某个元素的CSS样式以达到元素样式变化的效果。
示例
<body> <div id="animat"></div> <script> let elem = document.getElementById('animat'); let left = 1; //获取某个元素的宽度:obj.offsetWidth; console.log(elem.offsetWidth); let timer = setInterval(function(){ let elemWidth=elem.offsetWidth; if(elemWidth<500){ //设置某个元素的宽度:obj.style.width; elem.style.width=elemWidth+left+'px'; left ++; }else { clearInterval(timer); } },16); </script> </body>
Jquery的animate()方法就是这种方式实现的。
存在的问题
javascript 实现动画通常会导致页面频繁性重排重绘,消耗性能,一般应该在桌面端浏览器。在移动端上使用会有明显的卡顿。
Jquery的animate()
jQuery animate() 方法用于创建自定义动画。
语法:
$(selector).animate({params},speed,callback);
示例
<!DOCTYPE html> <html> <head> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $(document).ready(function(){ $("button").click(function(){ var div=$("div"); div.animate({height:'300px',opacity:'0.4'},"slow"); div.animate({'300px',opacity:'0.8'},"slow"); div.animate({height:'100px',opacity:'0.4'},"slow"); div.animate({'100px',opacity:'0.8'},"slow"); }); }); </script> </head> <body> <button>开始动画</button> <div style="background:#98bf21;height:100px;100px;position:absolute;"> </div> </body> </html>
requestAnimationFrame
requestAnimationFrame是另一种Web API,原理与setTimeout和setInterval类似,都是通过javascript持续循环的方法调用来触发动画动作。但是requestAnimationFrame是浏览器针对动画专门优化形成的APi,在性能上比另两者要好。
通常,我们将执行动画的每一步传到requestAnimationFrame中,在每次执行完后进行异步回调来连续触发动画效果。
示例
<!DOCTYPE html> <html> <head> <title></title> <style type="text/css"> * { margin:0; padding:0; } div { width: 100px; height: 100px; background: red; } </style> </head> <body> <div id="animat"></div> <script type="text/javascript"> window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; let elem = document.getElementById("animat"); let left = 0; //自动执行持续性回调 requestAnimationFrame(step); //持续该改变元素位置 function step() { let elemWidth=elem.offsetWidth; if(elemWidth<500){ //设置某个元素的宽度:obj.style.width; elem.style.width=elemWidth+left+'px'; left ++; requestAnimationFrame(step); } } </script> </body> </html>
我们注意到,requestAnimationFrame只是将回调的方法传入到自身的参数中执行,而不是通过setInterval调用。
什么是SVG?
SVG 用来定义用于网络的基于矢量的图形
SVG 使用 XML 格式定义图形
SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
SVG 是万维网联盟的标准
Canvas动画
canvas作为H5新增元素,是借助Web API来实现动画的。
示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ margin:0; padding:0; } </style> </head> <body> <canvas id="canvas" width="700" height="550"></canvas> <script type="text/javascript"> let canvas = document.getElementById("canvas"); //getContext()获取元素的绘制对象 let ctx = canvas.getContext("2d"); let width = 100; let timer = setInterval(function(){ //clearRect不断清空画布并在新的位置上使用fillStyle绘制新矩形内容实现页面动画效果。 ctx.clearRect(0,0,700,550); ctx.beginPath(); ctx.fillStyle = red; ctx.fillRect(0,0,width,200); ctx.stroke(); if(width>700){ clearInterval(timer); } width += 5; },16); </script> </body> </html>
总结
复杂的动画是通过一个个简单的动画组合实现的。基于兼容性问题,通常在项目中,一般在
- 桌面端浏览器推荐使用javascript直接实现动画或SVG方式;
- 移动端可以考虑使用CSS3 transition、CSS3
animation、Canvas或requestAnimationFrame方式**。