創(chuàng)建幻燈片放映
現(xiàn)在已經(jīng)有了能夠確定幻燈片中圖像的 Web 服務(wù),還需要顯示這些幻燈片并執(zhí)行 Ken-Burns-Effect 動畫的客戶端代碼。為此必須將執(zhí)行三種基本功能的 JavaScript 對象結(jié)合起來:
1、封裝圖像 2、提供基本的動畫引擎 3、實(shí)現(xiàn)特效(比如移動、縮放和漸變)
封裝圖像
首先從圖像容器開始,我創(chuàng)建一個類 ImageInfo,如 清單 4 所示。
清單 4. ImageInfo.js
function ImageInfo( src, width, height, htmlObj ) { this.src = src; this.width = width; this.height = height; this.current_width = width; this.current_height = height;
this.htmlObj = htmlObj; this.htmlObj.src = this.src; this.htmlObj.width = this.current_width; this.htmlObj.height = this.current_height; }
ImageInfo.prototype.set_opacity = function( opacity ) { this.htmlObj.style.MozOpacity = opacity / 100; var f = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+opacity+')'; this.htmlObj.style.filter = f; }
ImageInfo.prototype.set_position = function( x, y ) { this.htmlObj.style.left = x+'px'; this.htmlObj.style.top = y+'px'; }
ImageInfo.prototype.set_size = function( w, h ) { this.current_width = w; this.current_height = h;
this.htmlObj.width = this.current_width; this.htmlObj.height = this.current_height; }
ImageInfo.prototype.get_image = function() { return this.htmlObj; }
ImageInfo.prototype.hide = function() { this.htmlObj.style.visibility = 'hidden'; }
ImageInfo.prototype.show = function() { this.htmlObj.style.visibility = 'visible'; }
幻燈片中每幅圖片都有一個對應(yīng)的 ImageInfo 對象。該對象封裝了圖像信息:src、width 和 height。該對象還包含對在文檔中顯示圖像的 HTML <img> 標(biāo)記的引用,以及移動圖像、設(shè)置透明度等的 helper 方法。注意,在 Firefox 和其他基于 Gecko® 的瀏覽器中,MozOpacity 樣式用于設(shè)置不透明性。Internet Explorer 中則使用過濾器效果。
創(chuàng)建簡單的動畫引擎
下面我們來編寫一個簡單的動畫引擎。Animation.js 文件中的代碼如 清單 5 所示。
清單 5. Animation.js
function Animation( am, img, seconds, effects ) { this.img = img; this.animationManager = am; this.seconds = seconds; this.effects = effects; this.startMS = 0; }
Animation.prototype.start = function() { this.animationManager.add( this ); this.startMS = 0;
this.img.hide(); for( var e in this.effects ) { this.effects[e].apply( 0 ); } this.img.show(); }
Animation.prototype.animate = function() { var d = new Date(); if ( this.startMS == 0 ) this.startMS = d.valueOf();
var p = (((d.valueOf()-this.startMS)/1000)/this.seconds)*100; for( var e in this.effects ) this.effects[e].apply( p ); }
Animation.prototype.done = function() { var d = new Date(); return ( ( d.valueOf() - this.startMS ) / 1000 ) > this.seconds; }
function AnimationManager( speed ) { this.animations = []; var self = this; window.setInterval( function() { self.idle(); }, speed ); }
AnimationManager.prototype.add = function( anim ) { this.animations.push( anim ); }
AnimationManager.prototype.idle = function() { if ( this.animations.length > 0 ) { this.animations[0].animate(); if ( this.animations[0].done() ) this.animations.shift(); if ( this.animations.length == 0 ) this.on_finished(); } }
AnimationManager.prototype.on_finished = function() { }
清單 5 包含兩個類:Animation 和 AnimationManager。AnimationManager 類控制定時器并向其 Animation 對象列表中的第一項(xiàng)發(fā)送動畫消息。當(dāng) Animation 對象報告自己已經(jīng)完成的時候,該類就轉(zhuǎn)向下一項(xiàng),依此類推。
Animation 在一定的時間(按秒數(shù)指定)內(nèi)對特定圖片應(yīng)用一系列特效。Animation 對象需要計算完成度消息并將其發(fā)送給每種特效的 apply 方法。特效然后根據(jù)這個百分比計算應(yīng)該如何處理圖像。比如,移動特效知道起點(diǎn)和終點(diǎn),可以根據(jù)這個百分比計算應(yīng)該將圖像放到何處。如果是 50%,圖像應(yīng)該移到起點(diǎn)和終點(diǎn)之間。
作為我工作的一部分,同時也為了撰寫本文,我考察了大量的 JavaScript 動畫代碼。JavaScript 動畫經(jīng)常因?yàn)椴环(wěn)定而受到指責(zé),因?yàn)樗?JavaScript 動畫都使用 window.setInterval 方法來完成。這是一個定時器方法,同時指定了回調(diào)時間間隔和回調(diào)函數(shù)。Web 上的大部分代碼都要求每次調(diào)用該函數(shù)時動畫移動一步。但這并不能真正工作,因?yàn)楦嬖V瀏覽器的間隔僅僅是一個建議。如果規(guī)定 20 毫秒,但實(shí)際上可能第一次在 25 毫秒時調(diào)用,下一次卻要等到一秒鐘以后。瀏覽器是單線程的,因此不能依賴于定時器。
解決方案是使用 Date 對象的 valueOf 方法確定動畫開始了多長時間。這個時間差是用毫秒計的,用于確定當(dāng) setInterval 定時器離開時動畫應(yīng)該執(zhí)行百分之多少。該方法可以提供規(guī)定的任意長時間的平滑動畫。
出處:IBM developerWorks
責(zé)任編輯:moby
上一頁 用DHTML與XML制作Ajax幻燈片 [3] 下一頁 用DHTML與XML制作Ajax幻燈片 [5]
◎進(jìn)入論壇網(wǎng)絡(luò)編程版塊參加討論
|