溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

javascript如何實(shí)現(xiàn)幀動(dòng)畫

發(fā)布時(shí)間:2021-08-17 14:10:37 來源:億速云 閱讀:142 作者:小新 欄目:web開發(fā)

小編給大家分享一下javascript如何實(shí)現(xiàn)幀動(dòng)畫,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

概述

【分類】

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

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

<div id="rabbit" ></div> 
<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)畫

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

【需求分析】

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

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

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

  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)//通過改變?cè)氐腷ackground-position實(shí)現(xiàn)動(dòng)畫

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

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

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

6、repeatForever()//無限重復(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í)行完畢后,通過調(diào)用next方法,執(zhí)行下一個(gè)任務(wù),同時(shí)更新任務(wù)鏈索引值

javascript如何實(shí)現(xiàn)幀動(dòng)畫

【接口定義】

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

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

/* 添加一個(gè)異步定時(shí)任務(wù),通過定時(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ù),通過定時(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(),無限循環(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){
  //過濾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)所有圖片加載完成,且沒有超時(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)畫處理中,是通過迭代使用setTimeout()實(shí)現(xiàn)的,但是這個(gè)間隔時(shí)間并不準(zhǔn)確。下面,來實(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)畫開始過,則記錄動(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;
 //無縫連接動(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)畫庫類
 * @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ù),通過定時(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ù),通過定時(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ù)鏈中沒有任務(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'){
   //無限回退到上一個(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(),無限循環(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)畫庫的制作中應(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í)例,通過創(chuàng)建的幀動(dòng)畫庫實(shí)現(xiàn)博客開始的動(dòng)畫效果

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
<div id="rabbit" ></div> 
<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>
div{position:absolute;width:102px;height:80px;background-repeat:no-repeat;} 
</style>
</head>
<body>
<div id="rabbit1" ></div>
<div id="rabbit2" ></div>
<div id="rabbit3" ></div> 
<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>

以上是“javascript如何實(shí)現(xiàn)幀動(dòng)畫”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI