通常在前端中,實作動畫的方案主要有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({width:\'300px\',opacity:\'0.8\'},"slow");
div.animate({height:\'100px\',opacity:\'0.4\'},"slow");
div.animate({width:\'100px\',opacity:\'0.8\'},"slow");
});
});
</script>
</head>
<body>
<button>開始動畫</button>
<div style="background:#98bf21;height:100px;width: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 指可伸縮矢量圖形 (Scalable Vector Graphics)
SVG 用來定義用于網絡的基于矢量的圖形
SVG 使用 XML 格式定義圖形
SVG 圖像在放大或改變尺寸的情況下其圖形品質不會有所損失
SVG 是網際網路聯盟的标準
SVG 與諸如 DOM 和 XSL 之類的 W3C 标準是一個整體
(SVG是HTML下的一個分支)
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方式**。