您的位置:首页 > 其它

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

2011-05-17 17:21 489 查看


今天,我们来试玩一样东西,这个东西叫图片切换滚动,其实贴切一点应该叫图片轮播。时下图片轮播作为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
.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
.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
.data.id;

if (index<targetPointNumber)
{
this.setChildIndex(nodeList.nodeList
.data,index);
}
else if (index==targetPointNumber)
{
this.setChildIndex(nodeList.nodeList
.data,this.numChildren-1);
}
else if (index>targetPointNumber && index!=this.numChildren-1)
{
this.setChildIndex(nodeList.nodeList
.data,index);
}
else if (index==this.numChildren-1)
{
this.setChildIndex(nodeList.nodeList
.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/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: