国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

實(shí)例講解javascript幀動(dòng)畫

來(lái)源:懂視網(wǎng) 責(zé)編:小OO 時(shí)間:2020-11-27 20:13:45
文檔

實(shí)例講解javascript幀動(dòng)畫

前面的話;幀動(dòng)畫就是在“連續(xù)的關(guān)鍵幀”中分解動(dòng)畫動(dòng)作,也就是在時(shí)間軸的每幀上逐幀繪制不同的內(nèi)容,使其連續(xù)播放而成的動(dòng)畫。由于是一幀一幀的畫,所以幀動(dòng)畫具有非常大的靈活性,幾乎可以表現(xiàn)任何想表現(xiàn)的內(nèi)容。本文將詳細(xì)介紹javascript幀動(dòng)畫。概述;【分類】;常見的幀動(dòng)畫的方式有三種,包括gif、CSS3 animation和javascript。git和CSS3 animation不能靈活地控制動(dòng)畫的暫停和播放、不能對(duì)幀動(dòng)畫做更加靈活地?cái)U(kuò)展。另外,gif圖不能捕捉動(dòng)畫完成的事件。所以,一般地,使用javascript來(lái)實(shí)現(xiàn)幀動(dòng)畫?!驹怼?;js實(shí)現(xiàn)幀動(dòng)畫有兩種實(shí)現(xiàn)方式。1、如果有多張幀動(dòng)畫圖片,可以用一個(gè)image標(biāo)簽去承載圖片,定時(shí)改變image的src屬性(不推薦)。
推薦度:
導(dǎo)讀前面的話;幀動(dòng)畫就是在“連續(xù)的關(guān)鍵幀”中分解動(dòng)畫動(dòng)作,也就是在時(shí)間軸的每幀上逐幀繪制不同的內(nèi)容,使其連續(xù)播放而成的動(dòng)畫。由于是一幀一幀的畫,所以幀動(dòng)畫具有非常大的靈活性,幾乎可以表現(xiàn)任何想表現(xiàn)的內(nèi)容。本文將詳細(xì)介紹javascript幀動(dòng)畫。概述;【分類】;常見的幀動(dòng)畫的方式有三種,包括gif、CSS3 animation和javascript。git和CSS3 animation不能靈活地控制動(dòng)畫的暫停和播放、不能對(duì)幀動(dòng)畫做更加靈活地?cái)U(kuò)展。另外,gif圖不能捕捉動(dòng)畫完成的事件。所以,一般地,使用javascript來(lái)實(shí)現(xiàn)幀動(dòng)畫?!驹怼浚籮s實(shí)現(xiàn)幀動(dòng)畫有兩種實(shí)現(xiàn)方式。1、如果有多張幀動(dòng)畫圖片,可以用一個(gè)image標(biāo)簽去承載圖片,定時(shí)改變image的src屬性(不推薦)。
下面小編就為大家?guī)?lái)一篇javascript幀動(dòng)畫(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

前面的話

幀動(dòng)畫就是在“連續(xù)的關(guān)鍵幀”中分解動(dòng)畫動(dòng)作,也就是在時(shí)間軸的每幀上逐幀繪制不同的內(nèi)容,使其連續(xù)播放而成的動(dòng)畫。由于是一幀一幀的畫,所以幀動(dòng)畫具有非常大的靈活性,幾乎可以表現(xiàn)任何想表現(xiàn)的內(nèi)容。本文將詳細(xì)介紹javascript幀動(dòng)畫

概述

【分類】

常見的幀動(dòng)畫的方式有三種,包括gif、CSS3 animation和javascript

git和CSS3 animation不能靈活地控制動(dòng)畫的暫停和播放、不能對(duì)幀動(dòng)畫做更加靈活地?cái)U(kuò)展。另外,gif圖不能捕捉動(dòng)畫完成的事件。所以,一般地,使用javascript來(lái)實(shí)現(xiàn)幀動(dòng)畫

【原理】

js實(shí)現(xiàn)幀動(dòng)畫有兩種實(shí)現(xiàn)方式

1、如果有多張幀動(dòng)畫圖片,可以用一個(gè)image標(biāo)簽去承載圖片,定時(shí)改變image的src屬性(不推薦)

2、把所有的動(dòng)畫關(guān)鍵幀都繪制在一張圖片里,把圖片作為元素的background-image,定時(shí)改變?cè)氐腷ackground-position屬性(推薦)

因?yàn)榈谝环N方式需要使用多個(gè)HTTP請(qǐng)求,所以一般地推薦使用第二種方式

【實(shí)例】

下面是使用幀動(dòng)畫制作的一個(gè)實(shí)例

<p id="rabbit" ></p> 
<button id="btn">暫停運(yùn)動(dòng)</button> 
<script>
var url = 'rabbit-big.png';
var positions = ['0,-854','-174 -852','-349 -852','-524 -852','-698 -852','-873 -848'];
var ele = document.getElementById('rabbit');
var oTimer = null;
btn.onclick = function(){
 if(btn.innerHTML == '開始運(yùn)動(dòng)'){
 frameAnimation(ele,positions,url);
 btn.innerHTML = '暫停運(yùn)動(dòng)';
 }else{
 clearTimeout(oTimer);
 btn.innerHTML = '開始運(yùn)動(dòng)';
 } 
}
frameAnimation(ele,positions,url);
function frameAnimation(ele,positions,url){
 ele.style.backgroundImage = 'url(' + url + ')';
 ele.style.backgroundRepeat = 'no-repeat'; 
 var index = 0;
 function run(){
 var pos = positions[index].split(' ');
 ele.style.backgroundPosition = pos[0] + 'px ' + pos[1] + 'px';
 index++;
 if(index >= positions.length){
 index = 0;
 }
 oTimer = setTimeout(run,80);
 }
 run();
} 
</script>

通用幀動(dòng)畫

下面來(lái)設(shè)計(jì)一個(gè)通用的幀動(dòng)畫庫(kù)

【需求分析】

  1、支持圖片預(yù)加載

  2、支持兩種動(dòng)畫播放方式,及自定義每幀動(dòng)畫

  3、支持單組動(dòng)畫控制循環(huán)次數(shù)(可支持無(wú)限次)

  4、支持一組動(dòng)畫完成,進(jìn)行下一組動(dòng)畫

  5、支持每個(gè)動(dòng)畫完成后有等待時(shí)間

  6、支持動(dòng)畫暫停和繼續(xù)播放

  7、支持動(dòng)畫完成后執(zhí)行回調(diào)函數(shù)

【編程接口】

1、loadImage(imglist)//預(yù)加載圖片

2、changePosition(ele,positions,imageUrl)//通過(guò)改變?cè)氐腷ackground-position實(shí)現(xiàn)動(dòng)畫

3、changeSrc(ele,imglist)//通過(guò)改變image元素的src

4、enterFrame(callback)//每一幀動(dòng)畫執(zhí)行的函數(shù),相當(dāng)于用戶可以自定義每一幀動(dòng)畫的callback

5、repeat(times)//動(dòng)畫重復(fù)執(zhí)行的次數(shù),times為空時(shí)表示無(wú)限次

6、repeatForever()//無(wú)限重復(fù)上一次動(dòng)畫,相當(dāng)于repeat()

7、wait(time)//每個(gè)動(dòng)畫執(zhí)行完成后等待的時(shí)間

8、then(callback)//動(dòng)畫執(zhí)行完成后的回調(diào)函數(shù)

9、start(interval)//動(dòng)畫開始執(zhí)行,interval表示動(dòng)畫執(zhí)行的間隔

10、pause()//動(dòng)畫暫停

11、restart()//動(dòng)畫從上一交暫停處重新執(zhí)行

12、dispose()//釋放資源

【調(diào)用方式】

支持鏈?zhǔn)秸{(diào)用,用動(dòng)詞的方式描述接口

【代碼設(shè)計(jì)】

1、把圖片預(yù)加載 -> 動(dòng)畫執(zhí)行 -> 動(dòng)畫結(jié)束等一系列操作看成一條任務(wù)鏈。任務(wù)鏈包括同步執(zhí)行和異步定時(shí)執(zhí)行兩種任務(wù)

2、記錄當(dāng)前任務(wù)鏈的索引

3、每個(gè)任務(wù)執(zhí)行完畢后,通過(guò)調(diào)用next方法,執(zhí)行下一個(gè)任務(wù),同時(shí)更新任務(wù)鏈索引值

【接口定義】

'use strict';
/* 幀動(dòng)畫庫(kù)類
 * @constructor
 */
function FrameAnimation(){}

/* 添加一個(gè)同步任務(wù),去預(yù)加載圖片
 * @param imglist 圖片數(shù)組
 */
FrameAnimation.prototype.loadImage = function(imglist){}

/* 添加一個(gè)異步定時(shí)任務(wù),通過(guò)定時(shí)改變圖片背景位置,實(shí)現(xiàn)幀動(dòng)畫
 * @param ele dom對(duì)象
 * @param positions 背景位置數(shù)組
 * @param imageUrl 圖片URL地址
 */
FrameAnimation.prototype.changePosition = function(ele,positions,imageUrl){}

/* 添加一個(gè)異步定時(shí)任務(wù),通過(guò)定時(shí)改變image標(biāo)簽的src屬性,實(shí)現(xiàn)幀動(dòng)畫
 * @param ele dom對(duì)象
 * @param imglist 圖片數(shù)組
 */
FrameAnimation.prototype.changeSrc = function(ele,imglist){}

/* 添加一個(gè)異步定時(shí)任務(wù),自定義動(dòng)畫每幀執(zhí)行的任務(wù)函數(shù)
 * @param tastFn 自定義每幀執(zhí)行的任務(wù)函數(shù)
 */
FrameAnimation.prototype.enterFrame = function(taskFn){}

/* 添加一個(gè)同步任務(wù),在上一個(gè)任務(wù)完成后執(zhí)行回調(diào)函數(shù)
 * @param callback 回調(diào)函數(shù)
 */
FrameAnimation.prototype.then = function(callback){}

/* 開始執(zhí)行任務(wù),異步定時(shí)任務(wù)執(zhí)行的間隔
 * @param interval
 */
FrameAnimation.prototype.start = function(interval){}

/* 添加一個(gè)同步任務(wù),回退到上一個(gè)任務(wù),實(shí)現(xiàn)重復(fù)上一個(gè)任務(wù)的效果,可以定義重復(fù)的次數(shù)
 * @param times 重復(fù)次數(shù)
 */
FrameAnimation.prototype.repeat = function(times){}

/* 添加一個(gè)同步任務(wù),相當(dāng)于repeat(),無(wú)限循環(huán)上一次任務(wù)
 * 
 */
FrameAnimation.prototype.repeatForever = function(){}

/* 設(shè)置當(dāng)前任務(wù)執(zhí)行結(jié)束后到下一個(gè)任務(wù)開始前的等待時(shí)間
 * @param time 等待時(shí)長(zhǎng)
 */
FrameAnimation.prototype.wait = function(time){}

/* 暫停當(dāng)前異步定時(shí)任務(wù)
 * 
 */
FrameAnimation.prototype.pause = function(){}

/* 重新執(zhí)行上一次暫停的異步定時(shí)任務(wù)
 * 
 */
FrameAnimation.prototype.restart = function(){}

/* 釋放資源
 * 
 */
FrameAnimation.prototype.dispose = function(){}

圖片預(yù)加載

圖片預(yù)加載是一個(gè)相對(duì)獨(dú)立的功能,可以將其封裝為一個(gè)模塊imageloader.js

'use strict';
/**
 * 預(yù)加載圖片函數(shù)
 * @param images 加載圖片的數(shù)組或者對(duì)象
 * @param callback 全部圖片加載完畢后調(diào)用的回調(diào)函數(shù)
 * @param timeout 加載超時(shí)的時(shí)長(zhǎng)
 */
function loadImage(images,callback,timeout){
 //加載完成圖片的計(jì)數(shù)器
 var count = 0;
 //全部圖片加載成功的標(biāo)志位
 var success = true;
 //超時(shí)timer的id
 var timeoutId = 0;
 //是否加載超時(shí)的標(biāo)志位
 var isTimeout = false;
 //對(duì)圖片數(shù)組(或?qū)ο?進(jìn)行遍歷
 for(var key in images){
 //過(guò)濾prototype上的屬性
 if(!images.hasOwnProperty(key)){
 continue;
 }
 //獲得每個(gè)圖片元素
 //期望格式是object:{src:xxx}
 var item = images[key];
 if(typeof item === 'string'){
 item = images[key] = {
 src:item
 };
 }
 //如果格式不滿足期望,則丟棄此條數(shù)據(jù),進(jìn)行下一次遍歷
 if(!item || !item.src){
 continue;
 }
 //計(jì)數(shù)+1
 count++;
 //設(shè)置圖片元素的id
 item.id = '__img__' + key + getId();
 //設(shè)置圖片元素的img,它是一個(gè)Image對(duì)象
 item.img = window[item.id] = new Image();
 doLoad(item);
 }
 //遍歷完成如果計(jì)數(shù)為0,則直接調(diào)用callback
 if(!count){
 callback(success);
 }else if(timeout){
 timeoutId = setTimeout(onTimeout,timeout);
 }

 /**
 * 真正進(jìn)行圖片加載的函數(shù)
 * @param item 圖片元素對(duì)象
 */
 function doLoad(item){
 item.status = 'loading';
 var img = item.img;
 //定義圖片加載成功的回調(diào)函數(shù)
 img.onload = function(){
 success = success && true;
 item.status = 'loaded';
 done();
 }
 //定義圖片加載失敗的回調(diào)函數(shù)
 img.onerror = function(){
 success = false;
 item.status = 'error';
 done();
 }
 //發(fā)起一個(gè)http(s)請(qǐng)求
 img.src = item.src;
 /**
 * 每張圖片加載完成的回調(diào)函數(shù)
 */
 function done(){
 img.onload = img.onerror = null;
 try{
 delete window[item.id];
 }catch(e){

 }
 //每張圖片加載完成,計(jì)數(shù)器減1,當(dāng)所有圖片加載完成,且沒(méi)有超時(shí)的情況,清除超時(shí)計(jì)時(shí)器,且執(zhí)行回調(diào)函數(shù)
 if(!--count && !isTimeout){
 clearTimeout(timeoutId);
 callback(success);
 }
 }
 }
 /**
 * 超時(shí)函數(shù)
 */
 function onTimeout(){
 isTimeout = true;
 callback(false);
 }
}
var __id = 0;
function getId(){
 return ++__id;
}
module.exports = loadImage;

時(shí)間軸

在動(dòng)畫處理中,是通過(guò)迭代使用setTimeout()實(shí)現(xiàn)的,但是這個(gè)間隔時(shí)間并不準(zhǔn)確。下面,來(lái)實(shí)現(xiàn)一個(gè)時(shí)間軸類timeline.js

'use strict';

var DEFAULT_INTERVAL = 1000/60;

//初始化狀態(tài)
var STATE_INITIAL = 0;
//開始狀態(tài)
var STATE_START = 1;
//停止?fàn)顟B(tài)
var STATE_STOP = 2;

var requestAnimationFrame = (function(){
 return window.requestAnimationFrame || window.webkitRequestAnimationFrame|| window.mozRequestAnimationFrame || window.oRequestAnimationFrame || function(callback){
 return window.setTimeout(callback,(callback.interval || DEFAULT_INTERVAL));
 }
})();

var cancelAnimationFrame = (function(){
 return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || function(id){
 return window.clearTimeout(id);
 } 
})();
/**
 * 時(shí)間軸類
 * @constructor
 */
function Timeline(){
 this.animationHandler = 0;
 this.state = STATE_INITIAL;
}
/**
 * 時(shí)間軸上每一次回調(diào)執(zhí)行的函數(shù)
 * @param time 從動(dòng)畫開始到當(dāng)前執(zhí)行的時(shí)間
 */
Timeline.prototype.onenterframe = function(time){

}
/**
 * 動(dòng)畫開始
 * @param interval 每一次回調(diào)的間隔時(shí)間
 */
Timeline.prototype.start = function(interval){
 if(this.state === STATE_START){
 return;
 }
 this.state = STATE_START;
 this.interval = interval || DEFAULT_INTERVAL;
 startTimeline(this,+new Date());
}

/**
 * 動(dòng)畫停止
 */
Timeline.prototype.stop = function(){
 if(this.state !== STATE_START){
 return;
 }
 this.state = STATE_STOP;
 //如果動(dòng)畫開始過(guò),則記錄動(dòng)畫從開始到現(xiàn)在所經(jīng)歷的時(shí)間
 if(this.startTime){
 this.dur = +new Date() - this.startTime;
 }
 cancelAnimationFrame(this.animationHandler);
}

/**
 * 重新開始動(dòng)畫
 */
Timeline.prototype.restart = function(){
 if(this.state === STATE_START){
 return;
 }
 if(!this.dur || !this.interval){
 return;
 }
 this.state = STATE_START;
 //無(wú)縫連接動(dòng)畫
 startTimeline(this,+new Date()-this.dur);
}

/**
 * 時(shí)間軸動(dòng)畫啟動(dòng)函數(shù)
 * @param timeline 時(shí)間軸的實(shí)例
 * @param startTime 動(dòng)畫開始時(shí)間戳 
 */
function startTimeline(timeline,startTime){
 //記錄上一次回調(diào)的時(shí)間戳
 var lastTick = +new Date();
 timeline.startTime = startTime;
 nextTick.interval = timeline.interval;
 nextTick();
 /**
 * 每一幀執(zhí)行的函數(shù)
 */
 function nextTick(){
 var now = +new Date();
 timeline.animationHandler = requestAnimationFrame(nextTick);
 //如果當(dāng)前時(shí)間與上一次回調(diào)的時(shí)間戳大于設(shè)置的時(shí)間間隔,表示這一次可以執(zhí)行回調(diào)函數(shù)
 if(now - lastTick >= timeline.interval){
 timeline.onenterframe(now - startTime);
 lastTick = now;
 }
 }
}
module.exports = Timeline;

動(dòng)畫類實(shí)現(xiàn)

下面是動(dòng)畫類animation.js實(shí)現(xiàn)的完整代碼

'use strict';

var loadImage = require('./imageloader');
var Timeline = require('./timeline');
//初始化狀態(tài)
var STATE_INITIAL = 0;
//開始狀態(tài)
var STATE_START = 1;
//停止?fàn)顟B(tài)
var STATE_STOP = 2;
//同步任務(wù)
var TASK_SYNC = 0;
//異步任務(wù)
var TASK_ASYNC = 1;

/**
 * 簡(jiǎn)單的函數(shù)封裝,執(zhí)行callback
 * @param callback 執(zhí)行函數(shù)
 */
function next(callback){
 callback && callback();
}
/* 幀動(dòng)畫庫(kù)類
 * @constructor
 */
function FrameAnimation(){
 this.taskQueue = [];
 this.index = 0;
 this.timeline = new Timeline();
 this.state = STATE_INITIAL;
}

/* 添加一個(gè)同步任務(wù),去預(yù)加載圖片
 * @param imglist 圖片數(shù)組
 */
FrameAnimation.prototype.loadImage = function(imglist){
 var taskFn = function(next){
 loadImage(imglist.slice(),next);
 };
 var type = TASK_SYNC;
 return this._add(taskFn,type);
}

/* 添加一個(gè)異步定時(shí)任務(wù),通過(guò)定時(shí)改變圖片背景位置,實(shí)現(xiàn)幀動(dòng)畫
 * @param ele dom對(duì)象
 * @param positions 背景位置數(shù)組
 * @param imageUrl 圖片URL地址
 */
FrameAnimation.prototype.changePosition = function(ele,positions,imageUrl){
 var len = positions.length;
 var taskFn;
 var type;
 if(len){
 var me = this;
 taskFn = function(next,time){
 if(imageUrl){
 ele.style.backgroundImage = 'url(' + imageUrl + ')';
 }
 //獲得當(dāng)前背景圖片位置索引
 var index = Math.min(time/me.interval|0,len);
 var position = positions[index-1].split(' ');
 //改變dom對(duì)象的背景圖片位置
 ele.style.backgroundPosition = position[0] + 'px ' + position[1] + 'px';
 if(index === len){
 next();
 }
 }
 type = TASK_ASYNC;
 }else{
 taskFn = next;
 type = TASK_SYNC;
 }
 return this._add(taskFn,type);
}

/* 添加一個(gè)異步定時(shí)任務(wù),通過(guò)定時(shí)改變image標(biāo)簽的src屬性,實(shí)現(xiàn)幀動(dòng)畫
 * @param ele dom對(duì)象
 * @param imglist 圖片數(shù)組
 */
FrameAnimation.prototype.changeSrc = function(ele,imglist){
 var len = imglist.length;
 var taskFn;
 var type;
 if(len){
 var me = this;
 taskFn = function(next,time){
 //獲得當(dāng)前背景圖片位置索引
 var index = Math.min(time/me.interval|0,len);
 //改變image對(duì)象的背景圖片位置
 ele.src = imglist[index-1];
 if(index === len){
 next();
 }
 }
 type = TASK_ASYNC;
 }else{
 taskFn = next;
 type = TASK_SYNC;
 }
 return this._add(taskFn,type); 
}

/* 添加一個(gè)異步定時(shí)任務(wù),自定義動(dòng)畫每幀執(zhí)行的任務(wù)函數(shù)
 * @param tastFn 自定義每幀執(zhí)行的任務(wù)函數(shù)
 */
FrameAnimation.prototype.enterFrame = function(taskFn){
 return this._add(taskFn,TASK_ASYNC);
}

/* 添加一個(gè)同步任務(wù),在上一個(gè)任務(wù)完成后執(zhí)行回調(diào)函數(shù)
 * @param callback 回調(diào)函數(shù)
 */
FrameAnimation.prototype.then = function(callback){
 var taskFn = function(next){
 callback(this);
 next();
 };
 var type = TASK_SYNC;
 return this._add(taskFn,type);
}

/* 開始執(zhí)行任務(wù),異步定義任務(wù)執(zhí)行的間隔
 * @param interval
 */
FrameAnimation.prototype.start = function(interval){
 if(this.state === STATE_START){
 return this; 
 }
 //如果任務(wù)鏈中沒(méi)有任務(wù),則返回
 if(!this.taskQueue.length){
 return this;
 }
 this.state = STATE_START;
 this.interval = interval;
 this._runTask();
 return this;
 
}

/* 添加一個(gè)同步任務(wù),回退到上一個(gè)任務(wù),實(shí)現(xiàn)重復(fù)上一個(gè)任務(wù)的效果,可以定義重復(fù)的次數(shù)
 * @param times 重復(fù)次數(shù)
 */
FrameAnimation.prototype.repeat = function(times){
 var me = this;
 var taskFn = function(){
 if(typeof times === 'undefined'){
 //無(wú)限回退到上一個(gè)任務(wù)
 me.index--;
 me._runTask();
 return;
 }
 if(times){
 times--;
 //回退
 me.index--;
 me._runTask();
 }else{
 //達(dá)到重復(fù)次數(shù),跳轉(zhuǎn)到下一個(gè)任務(wù)
 var task = me.taskQueue[me.index];
 me._next(task);
 }
 }
 var type = TASK_SYNC;
 return this._add(taskFn,type);
}

/* 添加一個(gè)同步任務(wù),相當(dāng)于repeat(),無(wú)限循環(huán)上一次任務(wù)
 * 
 */
FrameAnimation.prototype.repeatForever = function(){
 return this.repeat();
}

/* 設(shè)置當(dāng)前任務(wù)執(zhí)行結(jié)束后到下一個(gè)任務(wù)開始前的等待時(shí)間
 * @param time 等待時(shí)長(zhǎng)
 */
FrameAnimation.prototype.wait = function(time){
 if(this.taskQueue && this.taskQueue.length > 0){
 this.taskQueue[this.taskQueue.length - 1].wait = time;
 }
 return this;
}

/* 暫停當(dāng)前異步定時(shí)任務(wù)
 * 
 */
FrameAnimation.prototype.pause = function(){
 if(this.state === STATE_START){
 this.state = STATE_STOP;
 this.timeline.stop();
 return this;
 }
 return this;
}

/* 重新執(zhí)行上一次暫停的異步定時(shí)任務(wù)
 * 
 */
FrameAnimation.prototype.restart = function(){
 if(this.state === STATE_STOP){
 this.state = STATE_START;
 this.timeline.restart();
 return this;
 }
 return this; 
}

/* 釋放資源
 * 
 */
FrameAnimation.prototype.dispose = function(){
 if(this.state !== STATE_INITIAL){
 this.state = STATE_INITIAL;
 this.taskQueue = null;
 this.timeline.stop();
 this.timeline = null;
 return this;
 }
 return this; 
}

/**
 * 添加一個(gè)任務(wù)到任務(wù)隊(duì)列
 * @param taskFn 任務(wù)方法
 * @param type 任務(wù)類型
 * @private
 */
FrameAnimation.prototype._add = function(taskFn,type){
 this.taskQueue.push({
 taskFn:taskFn,
 type:type
 });
 return this;
}

/**
 * 執(zhí)行任務(wù)
 * @private
 */
FrameAnimation.prototype._runTask = function(){
 if(!this.taskQueue || this.state !== STATE_START){
 return;
 }
 //任務(wù)執(zhí)行完畢
 if(this.index === this.taskQueue.length){
 this.dispose();
 return;
 }
 //獲得任務(wù)鏈上的當(dāng)前任務(wù)
 var task = this.taskQueue[this.index];
 if(task.type === TASK_SYNC){
 this._syncTask(task);
 }else{
 this._asyncTask(task);
 }
}

/**
 * 同步任務(wù)
 * @param task 執(zhí)行的任務(wù)對(duì)象
 * @private
 */
FrameAnimation.prototype._syncTask = function(task){
 var me = this;
 var next = function(){
 //切換到下一個(gè)任務(wù)
 me._next(task);
 }
 var taskFn = task.taskFn;
 taskFn(next);
}

/**
 * 異步任務(wù)
 * @param task 執(zhí)行的任務(wù)對(duì)象
 * @private
 */
FrameAnimation.prototype._asyncTask = function(task){
 var me = this;
 //定義每一幀執(zhí)行的回調(diào)函數(shù)
 var enterframe = function(time){
 var taskFn = task.taskFn;
 var next = function(){
 //停止當(dāng)前任務(wù)
 me.timeline.stop();
 //執(zhí)行下一個(gè)任務(wù)
 me._next(task);
 };
 taskFn(next,time);
 }
 this.timeline.onenterframe = enterframe;
 this.timeline.start(this.interval);
}

/**
 * 切換到下一個(gè)任務(wù),支持如果當(dāng)前任務(wù)需要等待,則延時(shí)執(zhí)行
 * @private
 */
FrameAnimation.prototype._next = function(task){
 this.index++;
 var me = this;
 task.wait ? setTimeout(function(){
 me._runTask();
 },task.wait) : this._runTask();
}

module.exports = function(){
  return new FrameAnimation();
}

webpack配置

由于animation幀動(dòng)畫庫(kù)的制作中應(yīng)用了AMD模塊規(guī)范,但由于瀏覽器層面不支持,需要使用webpack進(jìn)行模塊化管理,將animation.js、imageloader.js和timeline.js打包為一個(gè)文件

module.exports = {
 entry:{
 animation:"./src/animation.js"
 },
 output:{
 path:__dirname + "/build",
 filename:"[name].js",
 library:"animation",
 libraryTarget:"umd",
 }
}

下面是一個(gè)代碼實(shí)例,通過(guò)創(chuàng)建的幀動(dòng)畫庫(kù)實(shí)現(xiàn)博客開始的動(dòng)畫效果

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
<p id="rabbit" ></p> 
<script src="../build/animation.js"></script> 
<script>var imgUrl = 'rabbit-big.png';
var positions = ['0,-854','-174 -852','-349 -852','-524 -852','-698 -852','-873 -848'];
var ele = document.getElementById('rabbit');
var animation = window.animation;
var repeatAnimation = animation().loadImage([imgUrl]).changePosition(ele,positions,imgUrl).repeatForever();
repeatAnimation.start(80); 
</script>
</body>
</html>

更多實(shí)例

除了可以實(shí)現(xiàn)兔子推車的效果,還可以使用幀動(dòng)畫實(shí)現(xiàn)兔子勝利和兔子失敗的效果

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
p{position:absolute;width:102px;height:80px;background-repeat:no-repeat;} 
</style>
</head>
<body>
<p id="rabbit1" ></p>
<p id="rabbit2" ></p>
<p id="rabbit3" ></p> 
<script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/animation.js"></script>
<script>
var baseUrl = 'http://7xpdkf.com1.z0.glb.clouddn.com/runjs/img/';
var images = ['rabbit-big.png','rabbit-lose.png','rabbit-win.png'];
for(var i = 0; i < images.length; i++){
 images[i] = baseUrl + images[i];
}
var rightRunningMap = ["0 -854", "-174 -852", "-349 -852", "-524 -852", "-698 -851", "-873 -848"];
var leftRunningMap = ["0 -373", "-175 -376", "-350 -377", "-524 -377", "-699 -377", "-873 -379"];
var rabbitWinMap = ["0 0", "-198 0", "-401 0", "-609 0", "-816 0", "0 -96", "-208 -97", "-415 -97", "-623 -97", "-831 -97", "0 -203", "-207 -203", "-415 -203", "-623 -203", "-831 -203", "0 -307", "-206 -307", "-414 -307", "-623 -307"];
var rabbitLoseMap = ["0 0", "-163 0", "-327 0", "-491 0", "-655 0", "-819 0", "0 -135", "-166 -135", "-333 -135", "-500 -135", "-668 -135", "-835 -135", "0 -262"];

var animation = window.animation;
function repeat(){
 var repeatAnimation = animation().loadImage(images).changePosition(rabbit1, rightRunningMap, images[0]).repeatForever();
 repeatAnimation.start(80); 
}
function win() {
 var winAnimation = animation().loadImage(images).changePosition(rabbit2, rabbitWinMap, images[2]).repeatForever();
 winAnimation.start(200);
}
function lose() {
 var loseAnimation = animation().loadImage(images).changePosition(rabbit3, rabbitLoseMap, images[1]).repeatForever();
 loseAnimation.start(200);
}
repeat();
win();
lose();
</script>
</body>
</html>

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

實(shí)例講解javascript幀動(dòng)畫

前面的話;幀動(dòng)畫就是在“連續(xù)的關(guān)鍵幀”中分解動(dòng)畫動(dòng)作,也就是在時(shí)間軸的每幀上逐幀繪制不同的內(nèi)容,使其連續(xù)播放而成的動(dòng)畫。由于是一幀一幀的畫,所以幀動(dòng)畫具有非常大的靈活性,幾乎可以表現(xiàn)任何想表現(xiàn)的內(nèi)容。本文將詳細(xì)介紹javascript幀動(dòng)畫。概述;【分類】;常見的幀動(dòng)畫的方式有三種,包括gif、CSS3 animation和javascript。git和CSS3 animation不能靈活地控制動(dòng)畫的暫停和播放、不能對(duì)幀動(dòng)畫做更加靈活地?cái)U(kuò)展。另外,gif圖不能捕捉動(dòng)畫完成的事件。所以,一般地,使用javascript來(lái)實(shí)現(xiàn)幀動(dòng)畫?!驹怼?;js實(shí)現(xiàn)幀動(dòng)畫有兩種實(shí)現(xiàn)方式。1、如果有多張幀動(dòng)畫圖片,可以用一個(gè)image標(biāo)簽去承載圖片,定時(shí)改變image的src屬性(不推薦)。
推薦度:
標(biāo)簽: 動(dòng)畫 js javascript
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 亚洲色图欧美激情 | 91av欧美| 精品欧美一区二区在线观看欧美熟 | 亚洲欧美激情另类 | 日韩精品一区二区三区国语自制 | 亚洲国产精品免费在线观看 | 国产在线视频在线观看 | 久久亚洲欧美综合激情一区 | 永久毛片 | 一级特黄牲大片免费视频 | 免费一级毛片 | 国产成人久久精品一区二区三区 | 久久亚洲伊人中字综合精品 | 97热久久免费频精品99国产成人 | 欧美一区二区三区视频在线观看 | 国产精品人成人免费国产 | 欧美日韩在线亚洲国产人 | 99热只有精品一区二区 | 亚洲欧美另类第一页 | 日韩一区二区三区视频 | 国产免费全部免费观看 | 国产精品网站在线进入 | 欧美色图亚洲激情 | 亚洲视频欧美视频 | 欧美在线播放视频 | 欧洲高清一区二区三区试看 | 国产三级一区 | 亚洲第一区视频 | 国产激情在线观看 | 日韩在线无 | 自拍自偷 | 91原创在线| 一级毛片一级毛片一级级毛片 | 免费国产黄网站在线观看视频 | 亚洲 欧美 日韩 小说 另类 | 91亚洲 欧美 国产 制服 动漫 | 亚洲精品一二三四区 | 天堂亚洲欧美日韩一区二区 | 欧美日韩国产在线 | 日本一区二区三区免费看 | 成人欧美一区二区三区 |