创建幻灯片放映
现在已经有了能够确定幻灯片中图像的 Web 服务,还需要显示这些幻灯片并执行 Ken-Burns-Effect 动画的客户端代码。为此必须将执行三种基本功能的 JavaScript 对象结合起来:
1、封装图像 2、提供基本的动画引擎 3、实现特效(比如移动、缩放和渐变)
封装图像
首先从图像容器开始,我创建一个类 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'; }
幻灯片中每幅图片都有一个对应的 ImageInfo 对象。该对象封装了图像信息:src、width 和 height。该对象还包含对在文档中显示图像的 HTML <img> 标记的引用,以及移动图像、设置透明度等的 helper 方法。注意,在 Firefox 和其他基于 Gecko® 的浏览器中,MozOpacity 样式用于设置不透明性。Internet Explorer 中则使用过滤器效果。
创建简单的动画引擎
下面我们来编写一个简单的动画引擎。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 对象列表中的第一项发送动画消息。当 Animation 对象报告自己已经完成的时候,该类就转向下一项,依此类推。
Animation 在一定的时间(按秒数指定)内对特定图片应用一系列特效。Animation 对象需要计算完成度消息并将其发送给每种特效的 apply 方法。特效然后根据这个百分比计算应该如何处理图像。比如,移动特效知道起点和终点,可以根据这个百分比计算应该将图像放到何处。如果是 50%,图像应该移到起点和终点之间。
作为我工作的一部分,同时也为了撰写本文,我考察了大量的 JavaScript 动画代码。JavaScript 动画经常因为不稳定而受到指责,因为所有 JavaScript 动画都使用 window.setInterval 方法来完成。这是一个定时器方法,同时指定了回调时间间隔和回调函数。Web 上的大部分代码都要求每次调用该函数时动画移动一步。但这并不能真正工作,因为告诉浏览器的间隔仅仅是一个建议。如果规定 20 毫秒,但实际上可能第一次在 25 毫秒时调用,下一次却要等到一秒钟以后。浏览器是单线程的,因此不能依赖于定时器。
解决方案是使用 Date 对象的 valueOf 方法确定动画开始了多长时间。这个时间差是用毫秒计的,用于确定当 setInterval 定时器离开时动画应该执行百分之多少。该方法可以提供规定的任意长时间的平滑动画。
出处:IBM developerWorks
责任编辑:moby
上一页 用DHTML与XML制作Ajax幻灯片 [3] 下一页 用DHTML与XML制作Ajax幻灯片 [5]
◎进入论坛网络编程版块参加讨论
|