flash特效原理:图片切换滚动

  

今天,我们来试玩一样东西,这个东西叫图片切换滚动,其实贴切一点应该叫图片轮播。时下图片轮播作为web方面在各大网站已经非常流行,这种图片轮播非常经典,前段时间花了两天写了像一个QQ视频网站看到的效果。

  参考效果地址:http://v.qq.com/music/index.html

 

  要想玩,但是我比较懒,所以在分解他们效果的时候,顺便查询网站里面一个xml里面的数据,只是为了演示作用,故此只是借用了他们的xml数据内容。

  查看:http://v.qq.com/music/pic.xml 里面的xml信息可以查看到里面图片和描述 以及一些视频地址链接。我们只是需要获取到里面数据并进行分析保存起来。

  <?xml version="1.0" encoding="UTF-8" ?> - <root> - <item> <sid>0</sid> <bpurl>/video/play.html?vid=s0090IljcFW</bpurl> <url>http://imgcache.qq.com/qqlive/images/i1305516206_1.jpg</url> <link>/video/play.html?vid=s0090IljcFW</link> - <title> - <!--[CDATA[ 刘惜君《怎么唱情歌》MV首播 ]]> </title> - <subtitle> - <![CDATA[ “透明系女生”身陷两大型男无法自拔! ]]> </subtitle> </item> - <item> <sid>1</sid> <bpurl>/video/play.html?vid=A0090V89apA</bpurl> <url>http://imgcache.qq.com/qqlive/images/i1305195532_1.jpg</url> <link>/video/play.html?vid=A0090V89apA</link> - <title> - <![CDATA[ 震撼有力!2NE1新MV《lonely》 ]]> </title> - <subtitle> - <![CDATA[ 韩国女子天团回归,柔美单曲给炎炎夏日带来一丝清凉! ]]> </subtitle> </item> - <item> <sid>2</sid> <bpurl>/video/play.html?vid=M0090YAejKV</bpurl> <url>http://imgcache.qq.com/qqlive/images/i1305026066_1.jpg</url> <link>/video/play.html?vid=M0090YAejKV</link> - <title> - <![CDATA[ 谢娜自导自演最新MV震撼出炉 ]]> </title> - <subtitle> - <![CDATA[ 青春动力、活泼立志,最新MV《蓝色巧克力》俏皮来袭! ]]> </subtitle> </item> - <item> <sid>3</sid> <bpurl>/video/play.html?vid=X0090zlLq5P</bpurl> <url>http://imgcache.qq.com/qqlive/images/i1305006822_1.jpg</url> <link>/video/play.html?vid=X0090zlLq5P</link> - <title> - <![CDATA[ 终极挑逗!辣妹蕾哈娜最新MV ]]> </title> - <subtitle> - <![CDATA[ 全新时尚大片,带你领略加州绝美风光… ]]> </subtitle> </item> - <item> <sid>4</sid> <bpurl>/video/play.html?vid=p0090sSzkSC</bpurl> <url>http://imgcache.qq.com/qqlive/images/i1305014875_1.jpg</url> <link>/video/play.html?vid=p0090sSzkSC</link> - <title> - <![CDATA[ 郭富城章子怡:《最爱》主题曲 ]]> </title> - <subtitle> - <![CDATA[ 顾长卫新片主题曲《一直都在》首度曝光,感动上映! ]]--> </subtitle> </item> </root>

主类执行:

调用URLLoader 类对其xml 进行读取,读取完毕后,把数据转至photoItem 类,把需要的数据设置一下,如链接,图片地址,和文字描述。 在设置图片位置的时候,记录他们位置,以便在时间间隔调用的时候,进行切换下一个位置。

轮播当中需要工作:使用时间调度方式让图片进行轮播,

                           点击图片的时候可以进行轮播

                           点击中间图片的时候跳转到相应的链接处

                           切换图片时候 需要对图片进行暗处理,并隐藏主要文字

                           切换位置的时候,使用TweenLite进行轮播到下一个位置,

                           判断左右切换的方向。

                           深度排序

                           初始化图片的时候记录初始位置

                           

                                          

流程:

         加载xml数据-->实例化效果-->实例化图片元件,并赋予数据--->进行时间调度切换

当中交互里面,经常涉及到左右两只切换的方式,这两种方式使用频率比较高,在coverFlow 和一些轮播当中使用制作需要解决这两种交互的做法。

  制作这个效果之前,当时参考了双链表的方式来制作,但是在制作的时候,双链表并没有完全满足个人需求,于是采用循环链表来替代制作,这种结构对付这种效果十分有意思,借助队列思想 和链表当中思维结合, 可以帮助我们解决实际上一些交互的难题。

 

package { import flash.display.Sprite; import flash.events.*; import flash.net.URLLoader; import flash.net.URLRequest; import flash.display.StageAlign; import flash.display.StageScaleMode; import org.summerTree.utils.XMLManager; import org.summerTree.effect.FollowEffect; import org.summerTree.model.Photoparam; public class Main extends Sprite { private var dataPath:String = "http://v.qq.com/music/pic.xml"; private var effect:FollowEffect; public function Main() { if (stage) { initData(); } else { addEventListener(Event.ADDED_TO_STAGE,initData); } } private function initData(event:Event=null):void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; //加载xml var loader:URLLoader=new URLLoader(); loader.addEventListener(Event.COMPLETE,onLoadDataCompleteHandler); loader.addEventListener(IOErrorEvent.IO_ERROR,onLoadDataErrorHandler); loader.load(new URLRequest(dataPath)); } private function onLoadDataCompleteHandler(event:Event):void { event.currentTarget.removeEventListener(Event.COMPLETE,onLoadDataCompleteHandler); event.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR,onLoadDataErrorHandler); var xmlData:* = event.currentTarget.data; effect=new FollowEffect(); effect.targetPointNumber = 2; effect.initData(XMLManager.getXMLData(xmlData)); effect.addEventListener(Event.COMPLETE,onLoadCompleteHandler); } private function onLoadDataErrorHandler(event:IOErrorEvent):void { trace("数据加载失败了"); } private function onLoadCompleteHandler(event:Event):void { effect.removeEventListener(Event.COMPLETE,onLoadCompleteHandler); var n:int = 0; var len:int = effect.photoLength; //设置好队列顺序。 for (var i:int=0; i<len; i++) { effect.getPhotoItem(i).x = stage.stageWidth / 2 - (2 - i) * effect.getPhotoItem(i).width / 2; effect.getPhotoItem(i).y = stage.stageHeight / 2; effect.getPhotoItem(i).scaleX=effect.getPhotoItem(i).scaleY=1-Math.abs(2-i)*0.2; if (i!=2) { effect.photoList[i].data.isTextVisible = false; } effect.setParameters(new Photoparam(effect.getPhotoItem(i).x,effect.getPhotoItem(i).scaleX)); } effect.sortZ(); addChild(effect); effect.startMotion(); } } }

图片元件:记录xml 当中描述,设置图片地址,和图片显示。id是图片标记

package org.summerTree.display { import flash.display.Sprite; import flash.display.Loader; import flash.events.Event; import flash.events.IOErrorEvent; import flash.net.URLRequest; import flash.system.LoaderContext; import flash.display.Bitmap; import flash.display.Shape; import flash.filters.GlowFilter; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFieldAutoSize; import flash.geom.Point; public class PhotoItem extends Sprite { private var loader:Loader; private var title:String; private var bitmap:Bitmap; private var link:String; //点击链接 private var _isTextVisible:Boolean; private var photoContain:Sprite=new Sprite();//图片容器 private var bigTitle:TextField; private var blackMask:Shape; //黑色背景 public var id:int; public var level:int;//深度 public var isClick:Boolean = false;//是否允许点击 public var positionXY:Point;//记录开始的默认位置值 public function PhotoItem(url:String) { this.buttonMode = true; loader=new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadImageCompleteHandler); loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,onIOErrorHandler); loader.load(new URLRequest(url),new LoaderContext(true)); } private function onLoadImageCompleteHandler(event:Event):void { loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,onLoadImageCompleteHandler); loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,onIOErrorHandler); bitmap = Bitmap(event.currentTarget.content); addChild(photoContain); photoContain.x = - bitmap.width / 2; photoContain.y = - bitmap.height / 2; photoContain.addChild(bitmap); drawBaseBottom(bitmap.width,bitmap.height); blackMask=new Shape(); setTextDescription(); photoContain.addChild(blackMask); this.dispatchEvent(new Event(Event.COMPLETE)); } private function onIOErrorHandler(event:IOErrorEvent):void { trace("错误了"); } private function drawBaseBottom(width:Number,height:Number):void { var shape:Shape=new Shape(); shape.graphics.beginFill(0xCCCCCC); shape.graphics.drawRect(-5,-5,width+10,height+10); shape.graphics.endFill(); shape.filters = [new GlowFilter(0x999999,0.3)]; photoContain.addChildAt(shape,0); } //设置文本信息 public function setText(info:String):void { title = info; addEventListener(Event.ENTER_FRAME,render); } //设置图片链接 public function set imageUrl(value:String):void { this.link = value; } public function get imageUrl():String { return this.link; } //设置文本是否可见 public function set isTextVisible(value:Boolean):void { this._isTextVisible = value; photoContain.getChildAt(2).visible = value; blackMask.graphics.clear(); if (value) { blackMask.graphics.clear(); } else { blackMask.graphics.beginFill(0x333333,0.5); blackMask.graphics.drawRect(0,0,bitmap.width,bitmap.height); blackMask.graphics.endFill(); } } public function get isTextVisible():Boolean { return this._isTextVisible; } private function render(event:Event):void { if (bitmap) { removeEventListener(Event.ENTER_FRAME,render); bigTitle.text = title; } } private function setTextDescription():void { var contain:Sprite=new Sprite(); contain.graphics.beginFill(0x000000,0.5); contain.graphics.drawRect(0,0,bitmap.width,bitmap.height/4); contain.graphics.endFill(); photoContain.addChild(contain); var button:PlayButton = new PlayButton(40,40); contain.addChild(button); button.x = 8; button.y = 10; contain.y = bitmap.height - contain.height; bigTitle=new TextField(); bigTitle.defaultTextFormat = new TextFormat("黑体",12,0xffffff); bigTitle.multiline = true; bigTitle.autoSize = TextFieldAutoSize.LEFT; bigTitle.mouseEnabled = false; bigTitle.text = title; bigTitle.x = 60; bigTitle.y = contain.height - bigTitle.textHeight - 15; contain.addChild(bigTitle); blackMask.graphics.clear(); } } }

播放按钮图标:使用绘图api绘制

package org.summerTree.display { import flash.display.Sprite; public class PlayButton extends Sprite { public function PlayButton(width:Number,height:Number) { this.graphics.beginFill(0x333333,0.5); this.graphics.drawRoundRect(0,0,width,height,5,5); this.graphics.endFill(); this.graphics.lineStyle(2,0xffffff,0.5); this.graphics.drawRoundRect(-1,-1,width+2,height+2,5,5); this.graphics.beginFill(0xffffff,0.5); this.graphics.moveTo(width/3,height/3); this.graphics.lineTo(width/3,height*0.7); this.graphics.lineTo(width-width/3,height/2); this.graphics.lineTo(width/3,height/3); this.graphics.endFill(); } } }

交互当中常用接口:

package org.summerTree.effect { //常见左右交互当中的使用的接口 public interface IEffect { function next():void; function preview():void; } }

轮播效果主实现方法:当中使用了循环链表。

让其实现左右切换的交互。

package org.summerTree.effect { import flash.display.Sprite; import flash.utils.Timer; import flash.events.TimerEvent; import flash.events.MouseEvent; import flash.net.navigateToURL; import flash.net.URLRequest; import flash.events.*; import org.summerTree.display.PhotoItem; import org.summerTree.datastruct.CLinkedList; import org.summerTree.datastruct.DLinkNode; import org.summerTree.model.Photoparam; import org.summerTree.utils.Config; import com.greensock.TweenLite; import flash.geom.Point; public class FollowEffect extends Sprite implements IEffect { public var timeInterval:Number = 5000;//每隔一段时间播放j间隔 private var timer:Timer; private var currentTargetPhoto:PhotoItem;//当前的图片 private var isCurrentPage:Boolean = false; private var nodeList:CLinkedList=new CLinkedList(); private var photoNums:int = 0;//图片数目 public var targetPointNumber:int;//目标放大点 private var parameters:Array = [];//保存路径 public var motionDirection:String="right";//运动方向 public static const RIGHT:String="right"; public static const LEFT:String="left"; public function FollowEffect() { } public function initData(data:Array):void { if (data.length == 0) { return; } var len:int = data.length; photoNums = len; for (var i:int=0; i<len; i++) { var photoItem:PhotoItem = new PhotoItem(data[i].url); photoItem.addEventListener(Event.COMPLETE,onLoadImageCompleteHandler); photoItem.addEventListener(MouseEvent.CLICK,onGotoPage); if (data[i].link.indexOf(Config.domain) == -1) { data[i].link = "http://"+Config.domain+ data[i].link; } photoItem.setText(data[i].title); photoItem.imageUrl = data[i].link; photoItem.id = i; addChild(photoItem); nodeList.appendNode(photoItem); } currentTargetPhoto = nodeList.nodeList[1].data; addEventListener(MouseEvent.ROLL_OVER,onMotionHandler); addEventListener(MouseEvent.ROLL_OUT, onMotionHandler); } private function onLoadImageCompleteHandler(event:Event):void { event.currentTarget.removeEventListener(Event.COMPLETE,onLoadImageCompleteHandler); photoNums--; if (photoNums==0) { this.dispatchEvent(new Event(Event.COMPLETE)); } } private function onGotoPage(event:MouseEvent):void { if (PhotoItem(event.currentTarget).isClick) { navigateToURL(new URLRequest(event.currentTarget.imageUrl)); } else { flow(PhotoItem(event.currentTarget)); } } private function onMotionHandler(event:MouseEvent):void { if(event.type==MouseEvent.ROLL_OVER) { stopMotion(); } else { startMotion(); } } //开始运动 public function startMotion():void { if(timer==null) { timer = new Timer(timeInterval); timer.addEventListener(TimerEvent.TIMER,onTimerHandler); timer.start(); } else { timer.start(); } } //停止运动 public function stopMotion():void { timer.stop(); } private function onTimerHandler(event:TimerEvent):void { if(motionDirection=="right") { next(); } else if(motionDirection=="left") { preview(); } } //获取图片列表 public function get photoList():Array { return nodeList.nodeList; } //获取图片列表长度 public function get photoLength():int { return nodeList.nodeList.length; } //获取图片单项 public function getPhotoItem(index:int):PhotoItem { return nodeList.nodeList[index].data; } //添加基本图片参数 public function setParameters(value:Photoparam):void { parameters.push(value); } //设置时间间隔 public function setTimeInterval(value:Number):void { timeInterval=value; } //设置运动方向 public function setMotionDirection(value:String):void { motionDirection=value; } //左右的交互切换过程 public function flow(target:PhotoItem):void { currentTargetPhoto = target; //判断左右 if (target.id > targetPointNumber) { walkLeft(); } else if (target.id<targetPointNumber && target.id!=targetPointNumber) { walkRight(); } sortZ(); } //左方向交互 public function preview():void { if (nodeList.nodeOf(currentTargetPhoto).nextNode != null) { currentTargetPhoto = nodeList.nodeOf(currentTargetPhoto).nextNode.data as PhotoItem; flow(currentTargetPhoto); } } //右方向交互 public function next():void { if (nodeList.nodeOf(currentTargetPhoto).preNode != null) { currentTargetPhoto = nodeList.nodeOf(currentTargetPhoto).preNode.data as PhotoItem; flow(currentTargetPhoto); } } private function walkLeft():void { var len:int = nodeList.nodeList.length; var n:int = 0; var temp:int = 0; var index:int = 0; for (var i:int=len-1; i>-1; i--) { if (i==len-1) { temp = nodeList.nodeList[i].data.id; } if (i==0) { n = len - 1; nodeList.nodeList[i].data.id = temp; } else { n = i - 1; nodeList.nodeList[i].data.id = nodeList.nodeList[n].data.id; } index = nodeList.nodeList[i].data.id; if (currentTargetPhoto!=nodeList.nodeList[i].data) { nodeList.nodeList[i].data.isClick = false; } if (nodeList.nodeList[i].data.id != targetPointNumber) { nodeList.nodeList[i].data.isTextVisible = false; nodeList.nodeList[i].data.isClick = false; } else { nodeList.nodeList[i].data.isTextVisible = true; nodeList.nodeList[i].data.isClick = true; } TweenLite.to(nodeList.nodeList[i].data,0.5,{x:parameters[index].x,scaleX:parameters[index].scale,scaleY:parameters[index].scale}); } } private function walkRight():void { var len:int = nodeList.nodeList.length; var n:int = 0; var temp:int = 0; var index:int = 0; for (var i:int=0; i<len; i++) { if (i==0) { temp = nodeList.nodeList[i].data.id; } if (i==len-1) { n = 0; nodeList.nodeList[i].data.id = temp; } else { n = i + 1; nodeList.nodeList[i].data.id = nodeList.nodeList[n].data.id; } index = nodeList.nodeList[i].data.id; if (currentTargetPhoto!=nodeList.nodeList[i].data) { nodeList.nodeList[i].data.isClick = false; } if (nodeList.nodeList[i].data.id != targetPointNumber) { nodeList.nodeList[i].data.isTextVisible = false; nodeList.nodeList[i].data.isClick = false; } else { nodeList.nodeList[i].data.isTextVisible = true; nodeList.nodeList[i].data.isClick = true; } TweenLite.to(nodeList.nodeList[i].data,0.5,{x:parameters[index].x,scaleX:parameters[index].scale,scaleY:parameters[index].scale}); } } //深度排序() public function sortZ():void { var n:int = 0; while (n<this.numChildren) { var index:int = nodeList.nodeList[n].data.id; if (index<targetPointNumber) { this.setChildIndex(nodeList.nodeList[n].data,index); } else if (index==targetPointNumber) { this.setChildIndex(nodeList.nodeList[n].data,this.numChildren-1); } else if (index>targetPointNumber && index!=this.numChildren-1) { this.setChildIndex(nodeList.nodeList[n].data,index); } else if (index==this.numChildren-1) { this.setChildIndex(nodeList.nodeList[n].data,targetPointNumber); } n++; } } } }

获取xml 数据:

package org.summerTree.utils { public class XMLManager { //获取xml ,返回xml的数据 public static function getXMLData(data:String):Array { var array:Array=[]; var xml:XML=null; try{ xml=new XML(data); } catch(e:Error) { trace("数据发生了错误了"); } if(xml==null) return array; xml.ignoreWhitespace = true; var itemList:XMLList = xml..item; var len:int= itemList.length(); for(var i:int=0;i<len;i++) { var sonXML:XMLList=itemList[i].children(); var dataObject:Object={}; var nodeLen:int=sonXML.length();//节点长度 for(var j:int=0;j<nodeLen;j++) { var name:String = itemList[i].children()[j].name().toString(); var value:* = itemList[i].children()[j].toString(); dataObject[name]=value; } array.push(dataObject); } return array; } } }

配置文件

package org.summerTree.utils { public class Config { public static var domain:String="v.qq.com"; } }

循环链表使用:

package org.summerTree.datastruct { import org.summerTree.datastruct.DLinkNode; public class CLinkedList { private var _size:int = 0; public var head:DLinkNode = null;//头节点 public var tail:DLinkNode = null;//尾节点 private var first:DLinkNode=null; private var last:DLinkNode=null; private var NodeList:Array=[]; public function CLinkedList() { } //插入节点 public function appendNode(obj: * ):void { var newNode:DLinkNode = new DLinkNode(obj); if (this.isEmpty()) { head = newNode; } else { tail.nextNode = newNode; newNode.preNode = tail; newNode.nextNode=head; head.preNode=newNode; } tail = newNode; _size++; NodeList.push(newNode); } //搜索当前节点 public function nodeOf(obj: * ):DLinkNode { var len:int=NodeList.length; for(var i:int=0;i<len;i++) { if(NodeList[i].data==obj) { return NodeList[i]; } } return null; } //判断是否空链表 public function isEmpty():Boolean { return size == 0; } //返回节点数 public function get size():int { return _size; } public function get nodeList():Array { return NodeList; } } }

节点:

package org.summerTree.datastruct { public class DLinkNode { public var data:*; public var preNode:DLinkNode; public var nextNode:DLinkNode; public function DLinkNode(obj:*) { preNode = nextNode = null; data = obj; } } }

 记录他们参数

 package org.summerTree.model { //记录图片的位置和缩放信息 public class Photoparam { public var x:Number; public var scale:Number; public function Photoparam(x:Number,scale:Number) { this.x=x; this.scale=scale; } } }

除了这个之后,我们可以观看到百度视频当中的,也有这种flash制作,他们的特点是实用,替换数据方便,显示效果也比较有意思。

不妨去参考他们的swf 来尝试制作一个属于自己轮播效果。

 http://video.baidu.com/hd/index/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值