Javascript動畫效果(3)
前面我們已經(jīng)介紹了速度動畫、透明度動畫、多物體運動和任意值變化,并且我們在Javascript動畫效果(二)中介紹到我們封裝了一個簡單的插件雛形,接下來我們對前面的動畫效果進行進一步擴充,盡量將我們的框架做到更實用。在這里我們還需要了解兩個運動,一個是鏈式運動,一個是同時運動。它們間的區(qū)別分別是:鏈式運動是指運動一個接著一個(一個運動完成馬上進行下一個運動);而同時運動是指所有的運動同時進行。在這里,我們該如何實現(xiàn)呢?
1、鏈式運動
前面的效果中,我們已經(jīng)能對任意值進行相應(yīng)的變化,我們該如何在一個動畫后添加一個動畫呢?
思路:我們能不能在參數(shù)中傳入一個函數(shù),當一個效果完成后馬上執(zhí)行后面的函數(shù)(效果),該函數(shù)可以是想要的動畫效果
實現(xiàn):在function startMove(obj,attr,iTarget)中在傳入一個參數(shù)fn,代表一個函數(shù)。這時我們還需要修改的有在定時器的后面增加一個判斷if(fn){fn(); },當存在fn函數(shù)時執(zhí)行fn函數(shù),當不存在fn函數(shù)時清除定時器。這樣我們的window.onload函數(shù)也應(yīng)該發(fā)生相應(yīng)變化,代碼如下:
window.onload = function() {
var Li = document.getElementById('li1');
Li.onmouseover = function() {
startMove(Li, 'width', 400, function() {
startMove(Li, 'height', 200, function() {
startMove(Li, 'opacity', 100);
});
});
};
Li.onmouseout = function() {
startMove(Li, 'opacity', 30, function() {
startMove(Li, 'height', 100, function() {
startMove(Li, 'width', 200);
});
});
};
};
所以我們得到鏈式運動的如下代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鏈式運動</title>
<style type="text/css">
body,ul,li{ margin: 0px; padding: 0px; }
ul,li{ list-style: none; }
ul li{ width: 200px; height: 100px; background: yellow; margin-bottom: 20px; border: 4px solid #000; filter:alpha(opacity:30); opacity:0.3; }
</style>
</head>
<body>
<ul>
<li id="li1"></li>
</ul>
<script type="text/javascript">
window.onload = function(){
var Li = document.getElementById('li1');
Li.onmouseover = function(){
startMove(Li,'width',400,function(){
startMove(Li,'height',200,function(){
startMove(Li,'opacity',100);
});
});
};
Li.onmouseout = function(){
startMove(Li,'opacity',30,function(){
startMove(Li,'height',100,function(){
startMove(Li,'width',200);
});
});
};
};
function startMove(obj,attr,iTarget,fn){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var icur = 0;
if(attr == 'opacity'){
icur = Math.round(parseFloat(getStyle(obj,attr))*100);
}else{
icur = parseInt(getStyle(obj,attr));
}
var speed = (iTarget - icur)/10;
speed = speed>0?Math.ceil(speed):Math.floor(speed);
if(iTarget == icur){
clearInterval(obj.timer);
if(fn){
fn();
}
}
else{
if(attr == 'opacity'){
obj.style.filter = 'alpha(opacity:'+(icur+speed)+')';
obj.style.opacity = (icur+speed)/100;
}
else{
obj.style[attr] = icur+speed+'px';
}
}
},30)
}
function getStyle(obj,attr){
if(obj.currentStyle){
return obj.currentStyle[attr];
}
else{
return getComputedStyle(obj,false)[attr];
}
}
</script>
</body>
</html>
2、同時運動
說到同時運動,你可能會覺得很簡單,直接在onmouseover事件后面同時添加兩個不同的starMove()函數(shù)就可以解決了(錯誤思路?。?,實際上并不是這樣的,當有多個效果時,我們看到的是最后添加的那個效果。也就是說我們想同時改變寬度和高度(高度在后),我們得到的效果為只改變高度,寬度并沒有變化。這里我們應(yīng)該繼續(xù)傳參數(shù)么?從鏈式運動來看,傳參數(shù)的效果只能在后面添加函數(shù)得到連續(xù)的動畫效果。
思路:我們可不可以用JSON的方法來同時改變多個動畫效果?
實現(xiàn):將function startMove(obj,attr,iTarget,fn)中的attr和iTarget合并為一個參數(shù):json,我們用for/in的方法來遍歷json中的數(shù)據(jù),例如:
var json = {"a":12,"b":21};
for(var attr in json){
alert(json);//結(jié)果分別是:a,b
alert(json[attr]);//結(jié)果分別是:12,21
}
按照此方法,我們依次改變前面的代碼:在定時器函數(shù)的后面加上代碼:for(var attr in json) {...},并且修改里面的iTarget為json[attr],再將window.onload函數(shù)修改為:
window.onload = function() {
var Li = document.getElementById('li1');
Li.onmouseover = function() {
startMove(Li, {
width: 400,
height: 200,
opacity: 100
});
};
Li.onmouseout = function() {
startMove(Li, {
width: 200,
height: 100,
opacity: 30
});
};
};
這時我們差不多就可以得到我們想要的效果了,但是這樣離我們最終的效果還是查了那么一點點,比如說我們將onmouseover事件中的starMove中的width修改為202,再執(zhí)行我們的代碼,我們會發(fā)現(xiàn)最終的height不是200px,opacity也不是100,如圖:
這樣就很尷尬了,之前我們的效果不是還蠻好的么?我們再回到我們的JS代碼中分析結(jié)構(gòu),覺得最有可能出錯的就是starMove函數(shù)中,我們發(fā)現(xiàn)這段代碼的意思有點難理解:
if(json[attr] == icur) {
clearInterval(obj.timer);
if(fn) {
fn();
}
}
我們并不知道是不是所有的運動都到達終點時停止所有運動還是當只有一個運動達到終點時立馬停止所有運動。但是通過我們前面的操作,可以知道的實際結(jié)果為,只有一個運動到達終點值時,所有的運動都停止了(此時還有運動沒執(zhí)行完),我們該如何進行操作呢?
思路:我們可以假定一個參數(shù)flag,并且賦值為true,在執(zhí)行clearInterval(obj.timer);操作前我們先進行判斷if(json[attr] != icur) { flag = false;},后面執(zhí)行之前else里面的語句,再執(zhí)行如下語句if(flag = true) {clearInterval(obj.timer); if(fn) {fn();}},這樣我們就可以得到同時運動的完整代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鏈式運動</title>
<style type="text/css">
body,ul,li{ margin: 0px; padding: 0px; }
ul,li{ list-style: none; }
ul li{ width: 200px; height: 100px; background: yellow; margin-bottom: 20px; border: 4px solid #000; filter:alpha(opacity:30); opacity:0.3; }
</style>
</head>
<body>
<ul>
<li id="li1"></li>
</ul>
<script type="text/javascript">
window.onload = function(){
var Li = document.getElementById('li1');
Li.onmouseover = function(){
startMove(Li,{width:202,height:200,opacity:100});
};
Li.onmouseout = function(){
startMove(Li,{width:200,height:100,opacity:30});
};
};
function getStyle(obj, attr) {
if(obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
function startMove(obj, json, fn) {
//定義標桿
var flag = true; //假設(shè)的
clearInterval(obj.timer);
obj.timer = setInterval(function() {
for(var attr in json) {
var icur = 0;
if(attr == 'opacity') {
icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
} else {
icur = parseInt(getStyle(obj, attr));
}
var speed = (json[attr] - icur) / 10;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
if(json[attr] != icur) {
flag = false;
}
if(attr == 'opacity') {//判斷是否為opacity
obj.style.filter = 'alpha(opacity:' + (icur + speed) + ')';
obj.style.opacity = (icur + speed) / 100;
} else {
obj.style[attr] = icur + speed + 'px';
}
if(flag){
clearInterval(obj.timer);
if(fn){
fn();
}
}
}
}, 30)
}
</script>
</body>
</html>
這樣我們的同時運動的動畫效果就實現(xiàn)了。在這里,你有沒有覺得很神奇?
在這里我們已經(jīng)將一個簡單的運動插件封裝完成了,我們將里面的代碼做一些解釋,并且將它保存為一個foodoir.animate.js文件,代碼如下:
/*
* 簡單的運動框架
* 作者:foodoir
* 此框架僅作參考?。?!
*
* 使用方法見博文
*/
function getStyle(obj, attr) {
if(obj.currentStyle) {
return obj.currentStyle[attr];
} else {
return getComputedStyle(obj, false)[attr];
}
}
function startMove(obj, json, fn) {
clearInterval(obj.timer); //清除定時器,避免重復(fù)生成多個定時器
obj.timer = setInterval(function() {
var flag = true; //假設(shè)剛開始時所有運動都已完成
for(var attr in json) { //遍歷json
var icur = null;
//1.判斷類型
if(attr == 'opacity') {
icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
} else {
icur = parseInt(getStyle(obj, attr));
}
//2.算速度
var speed = (json[attr] - icur) / 5;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
//3.檢測停止
if(icur != json[attr]) {
flag = false;
}
if(attr == 'opacity') {
obj.style.filter = 'alpha(opacity:' + (icur + speed) + ')';
obj.style.opacity = (icur + speed) / 100;
} else {
obj.style[attr] = icur + speed + 'px';
}
}
if(flag) { //當所有運動都完成時,清除定時器
clearInterval(obj.timer);
if(fn) {
fn();
}
}
}, 30);
}
后面,我們將介紹用自己的框架來實現(xiàn)多種動畫效果,并且和jquery中的動畫效果進行比較。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于js拖拽上傳 [一個拖拽上傳修改頭像的流程]
拖拽是操作系統(tǒng)用戶體驗最偉大的改進之一。它讓人隨心所欲的操作,更符合人們的直觀感受。2011-07-07
javascript截取字符串(通過substring實現(xiàn)并支持中英文混合)
用js方法substring()、方法substr()實現(xiàn)如標題所示的截取字符串并支持中英文混合,具體代碼如下,感興趣的各位可以參考下哈2013-06-06
JavaScript實現(xiàn)自動彈出窗口并自動關(guān)閉窗口的方法
這篇文章主要介紹了JavaScript實現(xiàn)自動彈出窗口并自動關(guān)閉窗口的方法,可實現(xiàn)從頁面左側(cè)彈出窗口5秒后窗口向右移動并消失的效果,涉及javascript針對頁面窗口及樣式的定義操作技巧,需要的朋友可以參考下2015-08-08
webpack中CommonsChunkPlugin詳細教程(小結(jié))
微信小程序 獲取手機號 JavaScript解密示例代碼詳解

