说明:这个例子包括了上一篇的videoDisplay的视频锯齿的处理,state状态的切换,控件全屏和部分控件全屏,双击单个视频全屏,那个全屏的按钮是所有视频的全屏,还有一个位置计算的方法
刚学Flex不久,要做一个类似图中那样的视频展示网页。(代码写的太乱了真希望有大神可以帮忙优化!)
先看下效果图
1. main.mxml
主页面
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="960" height="530" xmlns:c="component.*" initialize="init(event)" applicationComplete="applicationCompleteHandler(event)" backgroundColor="0x000000" > <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <s:states> <s:State name="one"/> <s:State name="two"/> <s:State name="three"/> <s:State name="four"/> <s:State name="five"/> <s:State name="six"/> </s:states> <fx:Script> <![CDATA[ import mx.core.UIComponent; import mx.events.FlexEvent; import it.sephiroth.utils.HashMap; private var bId:String; private var vdAllArray:Array = null; private var stateArrayMap:HashMap = new HashMap(); protected function init(event:FlexEvent):void { ExternalInterface.addCallback("changeState",changeState); } private var fullBlocks:int = 1; private function allFullScreen():void{ this.fullScreen(this.getGroupId(Math.sqrt(fullBlocks)), 1); } private function singlefullScreen(event:MouseEvent):void{ this.fullScreen(event.currentTarget as SVideoDisplay, 0); } private function fullScreen(displayObject:UIComponent, flag:int):void{ if(FullScreenUtil.isFullScreen){ FullScreenUtil.exitFullScreen(); selectRect.width = 0; selectRect.height = 0; }else{ FullScreenUtil.goFullScreen(); if(flag == 0){ // 加入要全屏的对像.videoDisplay FullScreenUtil.addChild(null, displayObject, true, true, true); }else{ FullScreenUtil.addChild(stateArrayMap.getValue("map" + fullBlocks) as Array, displayObject, true, true, true); } } } private var stateMap:HashMap = new HashMap(); private function changeState(gState:String, blocks:int):void{ // vdAllArray = null; currentState = gState; if(stateMap.getValue(gState) == null){ this.vdFitGroup(blocks); stateArrayMap.put("map" + blocks, vdAllArray); } selectRect.width = 0; selectRect.height = 0; fullBlocks = blocks; stateMap.put(gState, blocks); } private function getGroupId(sqrtBlocks:int):Group{ var groupId:Group; if(1 == sqrtBlocks){ groupId = oneVideo; } else if(2 == sqrtBlocks){ groupId = twoVideo; }else if(3 == sqrtBlocks){ groupId = threeVideo; }else if(4 == sqrtBlocks){ groupId = fourVideo; }else if(5 == sqrtBlocks){ groupId = fiveVideo; }else if(6 == sqrtBlocks){ groupId = sixVideo; } return groupId; } private function vdFitGroup(blocks:int):void{ var sumWidth:int = 960; //容器宽度 var sumHeight:int = 480; //容器高度 var cuttingLineWidht:int = 2; //分割线宽 var x:int = 2; //相对X轴的距离 var y:int = 2; //相对Y轴的距离 var sqrtBlocks:int = Math.sqrt(blocks); //取平方根 var videoHeight:int = (sumHeight - (sqrtBlocks + 1) * 2) / sqrtBlocks; //视频的高度 var videoWidth:int = (sumWidth - (sqrtBlocks + 1) * 2) / sqrtBlocks; //视频的宽度 var remainX:int = (sumWidth - (sqrtBlocks + 1) * 2) % sqrtBlocks; //X轴剩余的像素 var remainY:int = (sumHeight - (sqrtBlocks + 1) * 2) % sqrtBlocks; //Y轴剩余的像素 var vd:SVideoDisplay = null; var vh:int; var vw:int; var hk:int = 0; vdAllArray = new Array(); for(var i:int = 0; i < sqrtBlocks; i++){ //行 var wk:int = 0; if(i >= (sqrtBlocks - remainY + 1)){ hk++; } vdAllArray[i] = new Array(); for(var j:int = 0; j < sqrtBlocks; j++){ //列 vd = new SVideoDisplay(); if(remainX > 0 && j >= (sqrtBlocks - remainX)){ vw = videoWidth + 1; } else { vw = videoWidth; } if(remainY > 0 && i >= (sqrtBlocks - remainY)){ vh = videoHeight + 1; } else { vh = videoHeight } if(j >= (sqrtBlocks - remainX + 1)){ wk++; } x = 2 + 2 * j + j * videoWidth + wk; //列相距X轴的距离公式 y = 2 + 2 * i + i * videoHeight + hk; //行相距Y轴的距离公式 vd.x = x; vd.y = y; vd.id = blocks + "" + i + "" + j; vd.videoURL = "http://helpexamples.com/flash/video/clouds.flv"; vd.height = vh; vd.width = vw; vd.toolTip = blocks + "" + i + "" + j; vd.addEventListener(MouseEvent.CLICK, vdClick); vd.doubleClickEnabled = true; vd.addEventListener(MouseEvent.DOUBLE_CLICK,singlefullScreen); vdAllArray[i][j] = vd; this.getGroupId(sqrtBlocks).addElement(vd); } } } //点击视频窗口的时候重新画一个矩形包围视频 private function vdClick(event:MouseEvent):void{ selectRect.x = SVideoDisplay(event.currentTarget).x; selectRect.y = SVideoDisplay(event.currentTarget).y; selectRect.width = SVideoDisplay(event.currentTarget).width; selectRect.height = SVideoDisplay(event.currentTarget).height; } protected function applicationCompleteHandler(event:FlexEvent):void { // TODO Auto-generated method stub this.vdFitGroup(1); stateArrayMap.put("map" + 1, vdAllArray); stateMap.put("one", 1); } ]]> </fx:Script> <!-- 视频容器 --> <s:Group id="oneVideo" height="480" width="100%" includeIn="one"> </s:Group> <s:Group id="twoVideo" height="480" width="100%" includeIn="two"> </s:Group> <s:Group id="threeVideo" height="480" width="100%" includeIn="three"> </s:Group> <s:Group id="fourVideo" height="480" width="100%" includeIn="four"> </s:Group> <s:Group id="fiveVideo" height="480" width="100%" includeIn="five"> </s:Group> <s:Group id="sixVideo" height="480" width="100%" includeIn="six"> </s:Group> <!-- 选择框 --> <s:Rect id="selectRect"> <s:stroke> <s:SolidColorStroke color="0xff0000" weight="2" /> </s:stroke> </s:Rect> <s:BorderContainer x="0" y="480" height="50" width="960" borderColor="0xff0000"> <s:layout> <s:HorizontalLayout/> </s:layout> <s:Button name="one" label="1" click="changeState(event.currentTarget.name, 1)"/> <s:Button name="two" label="4" click="changeState(event.currentTarget.name, 4)"/> <s:Button name="three" label="9" click="changeState(event.currentTarget.name, 9)"/> <s:Button name="four" label="16" click="changeState(event.currentTarget.name, 16)"/> <s:Button name="five" label="25" click="changeState(event.currentTarget.name, 25)"/> <s:Button name="six" label="36" click="changeState(event.currentTarget.name, 36)"/> <s:Button label="全屏" click="allFullScreen();"/> </s:BorderContainer> </s:Application>
2. SVideoDisplay.mxml
自定义组件为VideoDisplay设置背景色,并且动态绑定一个source属性,还有视频锯齿的处理
还有一个原因就是因为VideoDisplay如果视频源为空的话,他这个对象就为空,到时候需要点击的时候就获取不到
<?xml version="1.0" encoding="utf-8"?> <s:BorderContainer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" backgroundColor="#999999" borderVisible="false" width="400" height="200"> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations> <fx:Script> <![CDATA[ import spark.components.VideoDisplay; /** *自定义视频url属性 ,因为这个视频源要动态的,所以加了个_videoURL属性用来动态绑定他(不知道这样合不合理) * */ [Bindable] private var _videoURL:String = ""; public function set videoURL(url:String):void{ this._videoURL=url; } public function get videoURL():String{ return this._videoURL; } import org.osmf.events.MediaPlayerStateChangeEvent; private function checkState(e:MediaPlayerStateChangeEvent):void{ if(e.state == "playing") vid_player.videoObject.smoothing = true; } ]]> </fx:Script> <s:VideoDisplay id="vid_player" width="100%" height="100%" source="{_videoURL}" scaleMode="stretch" mediaPlayerStateChange="checkState(event)" /> </s:BorderContainer>
FullScreenUtil.as
网上的一个全屏的as类,自己加了一些代码进去
package { import flash.display.DisplayObject; import flash.display.StageDisplayState; import flash.events.FullScreenEvent; import flash.utils.Dictionary; import mx.containers.Canvas; import mx.core.FlexGlobals; import mx.core.IVisualElementContainer; import mx.core.UIComponent; import mx.events.ResizeEvent; import mx.managers.PopUpManager; public class FullScreenUtil { private static var theCanvas:Canvas; private static var displayObjectMap:Dictionary = new Dictionary(true); private static var anchorMap:Dictionary = new Dictionary(true); private static var _canvasStyleName:String = null; public static var isFullScreen:Boolean = false; private static var displayObjectArr:Array = new Array(); //自定义一个数组 /** *Getters and setters to facilitate styling the background canvas * @param val * */ public static function set canvasStyleName(val:String):void{ _canvasStyleName = val; } public static function get canvasStyleName():String{ return _canvasStyleName; } /** *Use this method to send the application full screen * @param color color for the full screen background to be * */ public static function goFullScreen(color:uint = 0x000000):void{ isFullScreen = true; theCanvas = new Canvas(); theCanvas.mouseEnabled = false; if(canvasStyleName){ theCanvas.styleName = canvasStyleName; }else{ theCanvas.setStyle(‘backgroundColor‘, color); } PopUpManager.addPopUp(theCanvas, FlexGlobals.topLevelApplication as DisplayObject); FlexGlobals.topLevelApplication.stage.displayState = StageDisplayState.FULL_SCREEN; onResize(); (FlexGlobals.topLevelApplication as DisplayObject).addEventListener(ResizeEvent.RESIZE, onResize); theCanvas.systemManager.stage.addEventListener(FullScreenEvent.FULL_SCREEN, onExitFullScreen); } /** *Use this method to exit full screen * all cleanup and child parenting will be done automatically */ public static function exitFullScreen():void{ isFullScreen = false; if(!theCanvas)return; if(null != displayObjectArr){ vdFitWindow(960, 480, displayObjectArr.length*displayObjectArr.length); } else { } (FlexGlobals.topLevelApplication as DisplayObject).removeEventListener(ResizeEvent.RESIZE, onResize); theCanvas.systemManager.stage.removeEventListener(FullScreenEvent.FULL_SCREEN, onExitFullScreen); if(theCanvas.systemManager.stage.displayState == StageDisplayState.FULL_SCREEN)theCanvas.systemManager.stage.displayState = StageDisplayState.NORMAL; PopUpManager.removePopUp(theCanvas); readdChildred(); theCanvas = null; } /** *Use this method to addchildren to the full screen instance after you‘ve called the <code>goFullScreen()</code> method * if you strech proportionally without anchoring the object will be moved to 0,0 in the canvas‘ coordinate space * @param displayObject - display object to be added * @param centerHorizontally - whether to center horizontally in the canvas space * @param centerVertically - whether to center vertically in the canvas space * @param stretchProportional - whether to stretch proportionally to cover all of the space * @param anchorLeft - left anchor * @param anchorRight - right anchor * @param anchorTop - top anchor * @param anchorBottom - bottom anchor * */ public static function addChild(arr:Array, displayObject:UIComponent, centerHorizontally:Boolean = false, centerVertically:Boolean = false, stretchProportional:Boolean = false, anchorLeft:Number = -1, anchorRight:Number = -1, anchorTop:Number = -1, anchorBottom:Number = -1 ):void{ if(!theCanvas)return; var infoObject:Object = new Object(); infoObject[‘parent‘] = displayObject.parent; infoObject[‘x‘] = displayObject.x; infoObject[‘y‘] = displayObject.y; infoObject[‘width‘] = displayObject.width; infoObject[‘height‘] = displayObject.height; infoObject[‘percentWidth‘] = displayObject.percentWidth infoObject[‘percentHeight‘] = displayObject.percentHeight; //获取组件在原先的父级上的索引 if(displayObject.parent){ if (displayObject.parent is IVisualElementContainer){ var ivec:IVisualElementContainer = IVisualElementContainer(displayObject.parent); infoObject[‘childIndex‘] = ivec.getElementIndex(displayObject); ivec.removeElement(displayObject); }else{ infoObject[‘childIndex‘] = displayObject.parent.getChildIndex(displayObject); displayObject.parent.removeChild(displayObject); } } //自定义 displayObjectArr = arr; if(null != arr){ vdFitWindow(theCanvas.width, theCanvas.height, displayObjectArr.length*displayObjectArr.length); } else { } displayObjectMap[displayObject] = infoObject; var anchorObject:Object = new Object(); anchorObject[‘stretchProportional‘] = stretchProportional; anchorObject[‘anchorLeft‘] = anchorLeft; anchorObject[‘anchorRight‘] = anchorRight; anchorObject[‘anchorTop‘] = anchorTop; anchorObject[‘anchorBottom‘] = anchorBottom; anchorObject[‘centerVertically‘] = centerVertically; anchorObject[‘centerHorizontally‘] = centerHorizontally; anchorMap[displayObject] = anchorObject; theCanvas.addChild(displayObject); onResize(); } /** *Remove a child explicitly from the full screen view * cleanup is done, and it is reparented * @param displayObject - child to be removed * */ public static function removeChild(displayObject:UIComponent):void{ var uic:UIComponent = displayObject as UIComponent; var infoObject:Object = displayObjectMap[uic]; if(!infoObject)return; if(infoObject[‘parent‘]){ // add back to original parent if (infoObject.parent is IVisualElementContainer) infoObject.parent.addElementAt(uic, infoObject[‘childIndex‘]); else infoObject.parent.addChildAt(uic, infoObject[‘childIndex‘]); if(isNaN(infoObject[‘percentWidth‘])){ uic.width = infoObject[‘width‘]; }else{ uic.percentWidth = infoObject[‘percentWidth‘]; } if(isNaN(infoObject[‘percentHeight‘])){ uic.height = infoObject[‘height‘]; }else{ uic.percentHeight = infoObject[‘percentHeight‘]; } uic.x = infoObject[‘x‘]; uic.y = infoObject[‘y‘]; delete displayObjectMap[uic]; delete anchorMap[uic]; } } /** *Readds all children to their correct containers * used when we‘re exiting full screen * */ private static function readdChildred():void{ for(var key:Object in displayObjectMap){ if(key is UIComponent){ removeChild(key as UIComponent); } } } /** *Called on resize to update the coordinates of anchored children throughout the canvas * */ private static function updateAnchorStates():void{ for(var key:Object in anchorMap){ if(key is UIComponent){ var uic:UIComponent = key as UIComponent; var anchorObject:Object = anchorMap[key]; var stretchProportional:Boolean = anchorObject[‘stretchProportional‘] as Boolean; var anchorLeft:Number = anchorObject[‘anchorLeft‘] as Number; var anchorRight:Number = anchorObject[‘anchorRight‘] as Number; var anchorTop:Number = anchorObject[‘anchorTop‘] as Number; var anchorBottom:Number = anchorObject[‘anchorBottom‘] as Number; var centerVertically:Boolean = anchorObject[‘centerVertically‘] as Boolean; var centerHorizontally:Boolean = anchorObject[‘centerHorizontally‘] as Boolean; if(stretchProportional){ var w:Number = uic.width; var h:Number = uic.height; var sw:Number = FlexGlobals.topLevelApplication.screen.width; var sh:Number = FlexGlobals.topLevelApplication.screen.height; if(w > h){ uic.width = sw; uic.validateNow(); //高直接用屏幕的高度 // uic.height *= (uic.width / w); uic.height = sh; uic.validateNow(); }else{ uic.height = sh; uic.validateNow(); uic.width *= (uic.height / h); uic.validateNow(); } } if(anchorLeft != -1){ uic.x = anchorLeft; } if(anchorRight != -1){ uic.x = FlexGlobals.topLevelApplication.screen.width - uic.width - anchorRight; } if(anchorTop != -1){ uic.y = anchorTop; } if(anchorBottom != -1){ uic.y = FlexGlobals.topLevelApplication.screen.height - uic.height - anchorBottom; } if(anchorLeft == -1 && anchorRight == -1 && stretchProportional)uic.x = 0; if(anchorTop == -1 && anchorBottom == -1 && stretchProportional)uic.y = 0; if(centerVertically)uic.y = FlexGlobals.topLevelApplication.screen.height / 2 - uic.height / 2; if(centerHorizontally)uic.x = FlexGlobals.topLevelApplication.screen.width / 2 - uic.width / 2; } } } /** *When the application is resized * @param event * */ private static function onResize(event:ResizeEvent = null):void{ if(!theCanvas)return; theCanvas.width = FlexGlobals.topLevelApplication.screen.width; theCanvas.height = FlexGlobals.topLevelApplication.screen.height; theCanvas.validateNow(); updateAnchorStates(); } /** *When full screen is exited with the escape key this will be triggered * @param e * */ private static function onExitFullScreen(e:FullScreenEvent):void{ if(e != null && !e.fullScreen)exitFullScreen(); } /** * 自己定义的方法,全屏的时候计算容器内子控件的位置 * */ private static function vdFitWindow(width:int, height:int, block:int):void{ var sumWidth:int = width; //容器宽度 var sumHeight:int = height; //容器高度 var cuttingLineWidht:int = 2; //分割线宽 var blocks:int = block; //几屏 1,4,9,16,25,36 var x:int = 2; //相对X轴的距离 var y:int = 2; //相对Y轴的距离 var sqrtBlocks:int = Math.sqrt(blocks); //取平方根 var videoHeight:int = (sumHeight - (sqrtBlocks + 1) * 2) / sqrtBlocks; //视频的高度 var videoWidth:int = (sumWidth - (sqrtBlocks + 1) * 2) / sqrtBlocks; //视频的宽度 var remainX:int = (sumWidth - (sqrtBlocks + 1) * 2) % sqrtBlocks; //X轴剩余的像素 var remainY:int = (sumHeight - (sqrtBlocks + 1) * 2) % sqrtBlocks; //Y轴剩余的像素 var vh:int; var vw:int; var hk:int = 0; for(var i:int = 0; i < sqrtBlocks; i++){ //行 var wk:int = 0; if(i >= (sqrtBlocks - remainY + 1)){ hk++; } for(var j:int = 0; j < sqrtBlocks; j++){ //列 if(remainX > 0 && j >= (sqrtBlocks - remainX)){ vw = videoWidth + 1; } else { vw = videoWidth; } if(remainY > 0 && i >= (sqrtBlocks - remainY)){ vh = videoHeight + 1; } else { vh = videoHeight } if(j >= (sqrtBlocks - remainX + 1)){ wk++; } x = 2 + 2 * j + j * videoWidth + wk; //列相距X轴的距离公式 y = 2 + 2 * i + i * videoHeight + hk; //行相距Y轴的距离公式 var vd:SVideoDisplay = SVideoDisplay(displayObjectArr[i][j]); vd.x = x; vd.y = y; vd.height = vh; vd.width = vw; } } } } }
还有一个swc包,这个是别人实现的一个hashmap
到这里来下载 http://download.csdn.net/detail/soanl/6877289