说明:这个例子包括了上一篇的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