代码改变世界

Flex倒映效果组件

2008-10-11 17:11  宝宝合凤凰  阅读(1072)  评论(0)    收藏  举报

Flex倒映效果组件

不错的倒映效果,忘记了从哪里的代码抄过来的,和大家分享一下
复制内容到剪贴板
代码:
package com.earthplayer.ui.util
{
        import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.GradientType;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BitmapFilter;
    import flash.filters.BlurFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
   
    import mx.core.UIComponent;
    import mx.events.DragEvent;
    import mx.events.FlexEvent;
    import mx.events.MoveEvent;
    import mx.events.ResizeEvent;
    import mx.states.RemoveChild;
    import mx.controls.Alert;
    import mx.rpc.Fault;
   
    public class ReflectionManager extends UIComponent {
        private static const _rPoint:Point = new Point(0, 0);
        private static const _rMatrix:Matrix = new Matrix();
               
        private var _bitmap:Bitmap = new Bitmap(new BitmapData(1, 1, true, 0));
        private var _targetBMData:BitmapData;
        private var _alphaGrBMData:BitmapData;
        private var _combinedBMData:BitmapData;
        private var _alphaGradient:Matrix = new Matrix();
        private var _blur:Number = 0;
        private var _blurFilter:BitmapFilter;
        private var _fadeFrom:Number = 0.3;
        private var _fadeTo:Number = 0;
        private var _matrix:Matrix;
        private var _point:Point;
        private var _rectangle:Rectangle;
        private var _shape:Shape;
        private var _target:UIComponent;
        
        // this offset is needed because of the drop shadow
        //private var _yshadowOffset:Number = -14;
        private var _yshadowOffset:Number = 2;
        
        public function ReflectionManager():void {
            this.addChild(this._bitmap);
            this.invalidateDisplayList();            
        }
        
        public function get fadeFrom():Number {
            return this._fadeFrom;
        }
        
        public function set fadeFrom(value:Number):void {
            this._fadeFrom = value;
            this.invalidateDisplayList();
        }
        
        public function get fadeTo():Number {
            return this._fadeFrom;
        }
        
        public function set fadeTo(value:Number):void {
            this._fadeTo = value;
            this.invalidateDisplayList();
        }
        
        public function get blur():Number {
            return this._blur;
        }
        
        public function set blur(value:Number):void {
            this._blur = value;
            this.invalidateDisplayList();
        }
        
        public function set target(value:UIComponent):void {               
               
            if (this._target != null) {
                this._target.removeEventListener(FlexEvent.UPDATE_COMPLETE, targetUpdateHandler, true);
                this._target.removeEventListener(Event.REMOVED_FROM_STAGE, targetRemovedHandler);
                this._target.removeEventListener(MoveEvent.MOVE,targetMoveHandler);               
                this._target.removeEventListener(ResizeEvent.RESIZE, targetResizeHandler);
                this.clearBMData();
            }
            
            this._target = value;
            
            if (this._target) {
                this._target.addEventListener(FlexEvent.UPDATE_COMPLETE, targetUpdateHandler, true);
                this._target.addEventListener(Event.REMOVED_FROM_STAGE, targetRemovedHandler);
                this._target.addEventListener(MoveEvent.MOVE,targetMoveHandler);               
                this._target.addEventListener(ResizeEvent.RESIZE, targetResizeHandler);
                this.invalidateDisplayList();
            }
        }
               
        public function targetUpdateHandler(event:*=null):void {
            this.invalidateDisplayList();
        }
        
        private function targetMoveHandler(event:MoveEvent):void {
            this._bitmap.x = this._target.x;
            this._bitmap.y = this._target.y + this._target.height + _yshadowOffset;
        }
        
        private function targetResizeHandler(event:ResizeEvent):void {
            this.clearBMData();
            this.width = _target.width;
            this.height = (_target.height / 100) * 50; //this.parentDocument.distance.value;
            this.invalidateDisplayList();
        }
        
        private function targetRemovedHandler(event:Event):void {
            this.parent.removeChild(this);
        }
      
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
            if (_target != null) {                   
                      this.drawReflection(_target);                    
                this._bitmap.bitmapData.dispose();
                this._bitmap.bitmapData = this._combinedBMData;
                // do it here
                this._bitmap.x = _target.x;
                this._bitmap.y = _target.y + _target.height + _yshadowOffset;  
            } else {
                this.clearBMData();
            }            
        }
        
        private function drawReflection(target:UIComponent):void {
            if (this.width > 0 && this.height > 0) {
                this._matrix = new Matrix(1, 0, 0, -1, 0, target.height);
                this._point = this._matrix.transformPoint(new Point(0, target.height));
                this._matrix.tx = this._point.x * -1 ;
                this._matrix.ty = (this._point.y - target.height) * -1;
               
                this._targetBMData = new BitmapData(this.width, this.height, true, 0);
                this._targetBMData.draw(target, this._matrix);                 
               
                this._rectangle = new Rectangle(0, 0, this.width, this.height);
               
                if (this._blur > 0) {
                    this._blurFilter = new BlurFilter(this._blur * 5, this._blur * 10, 1.0);
                    this._targetBMData.applyFilter(this._targetBMData, this._rectangle, this._point, this._blurFilter);
                }
               
                if (this._alphaGrBMData == null) {
                    this._alphaGradient.createGradientBox(this.width, this.height, Math.PI / 2);
                    
                    this._shape = new Shape();
                    this._shape.graphics.beginGradientFill(GradientType.LINEAR, new Array(0, 0), new Array(this._fadeFrom, this._fadeTo), new Array(0, 0xFF), this._alphaGradient);
                    this._shape.graphics.drawRect(0, 0, this.width, this.height);
                    this._shape.graphics.endFill();
                    
                    this._alphaGrBMData = new BitmapData(this.width, this.height, true, 0);
                    this._alphaGrBMData.draw(this._shape, _rMatrix);   
                }
               
                this._combinedBMData = new BitmapData(this.width, this.height, true, 0);
                this._combinedBMData.copyPixels(this._targetBMData, this._rectangle, _rPoint, this._alphaGrBMData);
            }
        }
        
        public function clearBMData():void {
            this._targetBMData = null;
            this._alphaGrBMData = null;
            this._combinedBMData = null;
        }
    }
}
调用方法如下
复制内容到剪贴板
代码:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:widget="com.earthplayer.ui.widget.*"
         backgroundColor="#111111" xmlns:util="com.earthplayer.ui.util.*" resize="show(event)" >
         <mx:Script>
                
                 <![CDATA[
                         import mx.events.FlexEvent;
                                                 
                         private function show(event:*=null):void{
                                 reflection.invalidateDisplayList();               
                         }
                        
                        
                 ]]>
         </mx:Script>
         <util:ReflectionManager id="reflection" target="{panel1}" width="{panel1.width}"
        height="{(panel1.height / 100) * 50}"
        fadeFrom="0.35"
        fadeTo="0"
        blur="0.3"/>
         <widget:SelfConfigureWindow dropShadowEnabled="false" id="panel1" y="100" x="100" />
</mx:Canvas>
样例图片

附件

sample.jpg (83.73 KB)

2008-1-30 11:36

sample.jpg

_______________________________________________________________________________________________

package
{
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.GradientType;
        import flash.display.Shape;
        import flash.events.Event;
        import flash.filters.BitmapFilter;
        import flash.filters.BlurFilter;
        import flash.filters.GlowFilter;
        import flash.geom.Matrix;
        import flash.geom.Point;
        import flash.geom.Rectangle;
        
        import mx.core.UIComponent;
        import mx.events.FlexEvent;
        import mx.events.MoveEvent;
        import mx.events.ResizeEvent;//当Flex组件变化时触发的事件
   
    //派生自UIComponent的ReflectionManager类
    public class ReflectionManager extends UIComponent {
        private static const _rPoint:Point = new Point(0, 0);//定义一个坐标常量
        private static const _rMatrix:Matrix = new Matrix();//矩阵常量,默认为Matrix(1,0,0,1,0,0)
               
        private var _bitmap:Bitmap = new Bitmap(new BitmapData(1, 1, true, 0));//存放位图图像数据变量
        private var _targetBMData:BitmapData;//存放目标物体的原始位图数据
        private var _alphaGrBMData:BitmapData;//存放目标物体的有透明度的渐变的原始位图数据
        private var _combinedBMData:BitmapData;//存放绑定的原始位图数据
        private var _alphaGradient:Matrix = new Matrix();//存放透明度的渐变的矩阵
        private var _blur:Number = 0;//存放模糊度,初始化为0
        private var _blurFilter:BitmapFilter;//存放位图滤镜
        private var _fadeFrom:Number = 0.3;//变淡的开始数据,默认为0.3
        private var _fadeTo:Number = 0;//变淡的最后数据,为0
        private var _matrix:Matrix;//变换矩阵
        private var _point:Point;//坐标
        private var _rectangle:Rectangle;//矩形
        private var _shape:Shape;//轻量级形状
        private var _target:UIComponent;//变量存放需要设置倒影的组件
        private var _glowFilter:GlowFilter;
        
        // this offset is needed because of the drop shadow
        //private var _yshadowOffset:Number = -14;
        private var _yshadowOffset:Number = 2;//y轴上的阴影偏移量
        
        //构造函数,添加了_bitmap到可视列表
        //调用invalidateDisplayList()导致在可视表单渲染之前先调用组件的validateDisplayList()方法确认其有效性
        //调用它也意味着调用了updateDisplayList()方法,更新显示列表数据
        public function ReflectionManager():void {
            this.addChild(this._bitmap);
            this.invalidateDisplayList();            
        }
        //得到淡出值
        public function get fadeFrom():Number {
            return this._fadeFrom;
        }
        //由用户输入淡出值,设置淡出属性
        public function set fadeFrom(value:Number):void {
            this._fadeFrom = value;
            this.invalidateDisplayList();
        }
        //得到淡入值
        public function get fadeTo():Number {
            return this._fadeFrom;
        }
        //有用户输入淡入值,设置淡入属性
        public function set fadeTo(value:Number):void {
            this._fadeTo = value;
            this.invalidateDisplayList();
        }
        //得到模糊值
        public function get blur():Number {
            return this._blur;
        }
        //由用户输入模糊值,设置模糊属性,这些属性都可以在组件中当成属性来赋予值
        public function set blur(value:Number):void {
            this._blur = value;
            this.invalidateDisplayList();
        }
        //设置加以阴影效果的目标属性
        public function set target(value:UIComponent):void {               
             //如果没有目标,就把指定的value值赋予目标target,然后添加一系列事件侦听器   
            if (this._target != null) {
                this._target.removeEventListener(FlexEvent.UPDATE_COMPLETE, targetUpdateHandler, true);
                this._target.removeEventListener(Event.REMOVED_FROM_STAGE, targetRemovedHandler);
                this._target.removeEventListener(MoveEvent.MOVE,targetMoveHandler);               
                this._target.removeEventListener(ResizeEvent.RESIZE, targetResizeHandler);
                this.clearBMData();
            }
            
            this._target = value;
            //UPDATE_COMPLETE当updateDisplayList()方法被调用时产生的事件,添加了弱引用,并添加了弱引用机制
            if (this._target) {
                this._target.addEventListener(FlexEvent.UPDATE_COMPLETE, targetUpdateHandler, true);
                this._target.addEventListener(Event.REMOVED_FROM_STAGE, targetRemovedHandler);
                this._target.addEventListener(MoveEvent.MOVE,targetMoveHandler);               
                this._target.addEventListener(ResizeEvent.RESIZE, targetResizeHandler);
                this.invalidateDisplayList();
            }
        }
        //更新显示列表        
        public function targetUpdateHandler(event:*=null):void {
            this.invalidateDisplayList();
        }
        //移动_bitmap到被倒影的目标的下面
        private function targetMoveHandler(event:MoveEvent):void {
            this._bitmap.x = this._target.x;
            this._bitmap.y = this._target.y + this._target.height + _yshadowOffset;
        }
        //组件大小改变后先清除所有的原始图像数据,然后重新设置倒影的宽高
        private function targetResizeHandler(event:ResizeEvent):void {
            this.clearBMData();
            this.width = _target.width;
            this.height = (_target.height / 100) * 50; //this.parentDocument.distance.value;
            this.invalidateDisplayList();
        }
        
        private function targetRemovedHandler(event:Event):void {
            this.parent.removeChild(this);
        }

//重载updateDisplayList方法
       //当被倒影的目标存在时,开始绘制关于目标的倒影
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
            if (_target != null) {                    
                      this.drawReflection(_target);                     
                this._bitmap.bitmapData.dispose();
                this._bitmap.bitmapData = this._combinedBMData;
                // do it here
                this._bitmap.x = _target.x;
                this._bitmap.y = _target.y + _target.height + _yshadowOffset;  
            } else {
                this.clearBMData();
            }            
        }
        //绘制目标的倒影
        /*关于matrix的属性
         a:Number
                 Matrix 对象的第一行和第一列中的值,它影响在缩放或旋转图像时沿 X 轴的像素定位。
                 b:Number
                 Matrix 对象的第一行和第二列中的值,它影响在旋转或倾斜图像时沿 Y 轴的像素定位。
                 c:Number
                 Matrix 对象的第二行和第一列中的值,它影响在旋转或倾斜图像时沿 X 轴的像素定位。
                 d:Number
                 Matrix 对象的第二行和第二列中的值,它影响在缩放或旋转图像时沿 Y 轴的像素定位。
                 tx:Number
                 沿 X 轴平移每个点的距离。
                 ty:Number
                 沿 Y 轴平移每个点的距离。
                */
        private function drawReflection(target:UIComponent):void {
            if (this.width > 0 && this.height > 0) {//如果目标宽高都大于0
                this._matrix = new Matrix(1, 0, 0, -1, 0, target.height);//矩阵
                this._point = this._matrix.transformPoint(new Point(0, target.height));//将_matrix代表的几何转换应用到了那点,得到了新的点(0,0)
                trace(_point);
                this._matrix.tx = this._point.x * -1 ;
                this._matrix.ty = (this._point.y - target.height) * -1;
                trace(_matrix);
                this._targetBMData = new BitmapData(this.width, this.height, true, 0);
                this._targetBMData.draw(target, this._matrix);//将矩阵_matrix的几何转换应用到目标物体上
                //此时_matrix=(1,0,0,-1,0,target.height)                 
               
                this._rectangle = new Rectangle(0, 0, this.width, this.height);//在0,0处画了个和目标物体一样大小的矩形
               
                if (this._blur > 0) {
                    this._blurFilter = new BlurFilter(this._blur * 5/*水平模糊程度0-225*/, this._blur * 10/*垂直模糊程度*/, 1.0/*滤镜运行次数*/);//模糊滤镜
                    this._glowFilter = new GlowFilter(0xFF00FF,0.5,3,6);
                    //下面这话的意思是给保存影音原始图像数据添加滤镜
                    /*applyFilter方法的参数详解
                    sourceBitmapData:BitmapData — 要使用的输入位图图像。 源图像可以是另一个 BitmapData 对象,也可以引用当前 BitmapData 实例。  
                                               sourceRect:Rectangle — 定义要用作输入的源图像区域的矩形。  
                                                destPoint:Point — 目标图像(当前 BitmapData 实例)中与源矩形的左上角对应的点。  
                                                filter:BitmapFilter — 用于执行过滤操作的滤镜对象
                                                */
                    this._targetBMData.applyFilter(this._targetBMData, this._rectangle, this._point, this._blurFilter);
                    this._targetBMData.applyFilter(this._targetBMData, this._rectangle, this._point, this._glowFilter);
                }
                //矩阵创建渐变盒子的方法的属性width:Number, height:Number, rotation:Number = 0, tx:Number = 0, ty:Number = 0
                //特别为beginGradientFill() and lineGradientStyle()准备
                if (this._alphaGrBMData == null) {
                    this._alphaGradient.createGradientBox(this.width, this.height, Math.PI / 2);
                }
                /*beginGradientFill方法属性详解
                type:String — 用于指定要使用哪种渐变类型的 GradientType 类的值:GradientType.LINEAR 或 GradientType.RADIAL。  
                                 colors:Array — 要在渐变中使用的 RGB 十六进制颜色值数组(例如,红色为 0xFF0000,蓝色为 0x0000FF,等等)。 可以至多指定 15 种颜色。 对于每种颜色,请确保在 alphas 和 ratios 参数中指定对应的值。  
                                 alphas:Array — colors 数组中对应颜色的 alpha 值数组;有效值为 0 到 1。 如果值小于 0,则默认值为 0。 如果值大于 1,则默认值为 1。  
                                 ratios:Array — 颜色分布比例的数组;有效值为 0 到 255。 该值定义 100% 采样的颜色所在位置的宽度百分比。 值 0 表示渐变框中的左侧位置,255 表示渐变框中的右侧位置。
                                注意:该值表示渐变框中的位置,而不是最终渐变的坐标空间,坐标空间可能比渐变框宽或窄。 为 colors 参数中的每个值指定一个值。
                                例如,对于包括蓝和绿两种颜色的线性渐变,下例显示了基于不同 ratios 数组值的渐变中的颜色配比:
                                ratios 渐变
                                [0, 127]  
                                [0, 255]  
                                [127, 255]  
                                数组中的值必须持续增加;例如,[0, 63, 127, 190, 255]。
                                 matrix:Matrix (default = null) — 一个由 flash.geom.Matrix 类定义的转换矩阵。 flash.geom.Matrix 类包括 createGradientBox() 方法,通过该方法可以方便地设置矩阵,以便与 beginGradientFill() 方法一起使用。  
                                 spreadMethod:String (default = "pad") — 用于指定要使用哪种 spread 方法的 SpreadMethod 类的值:SpreadMethod.PAD、SpreadMethod.REFLECT 或 SpreadMethod.REPEAT。  
*/
                this._shape = new Shape();
                this._shape.graphics.beginGradientFill(GradientType.LINEAR, new Array(0, 0), new Array(this._fadeFrom, this._fadeTo), new Array(0, 0xFF), this._alphaGradient);
                this._shape.graphics.drawRect(0,0,this.width,this.height);//画矩形
                this._shape.graphics.endFill();
                this._alphaGrBMData = new BitmapData(this.width,this.height,true,0);
                this._alphaGrBMData.draw(this._shape,_rMatrix);
                /*copyPixels参数详解
                 sourceBitmapData:BitmapData — 要从中复制像素的输入位图图像。 源图像可以是另一个 BitmapData 实例,也可以指当前 BitmapData 实例。  
                                 sourceRect:Rectangle — 定义要用作输入的源图像区域的矩形。  
                                 destPoint:Point — 目标点,它表示将在其中放置新像素的矩形区域的左上角。  
                                 alphaBitmapData:BitmapData (default = null) — 第二个 Alpha BitmapData 对象源。  
                                 alphaPoint:Point (default = null) — Alpha BitmapData 对象源中与 sourceRect 参数的左上角对应的点。  
                                 mergeAlpha:Boolean (default = false) — 若要使用 Alpha 通道,请将该值设置为 true。 若要复制不含 Alpha 通道的像素,请将该值设置为 false。  
*/
                                //这个原始图像数据结合之前的目标倒影原始图像数据和后来的透明度原始图像数据从而称为了最终的阴影
                this._combinedBMData = new BitmapData(this.width,this.height,true,0);
                this._combinedBMData.copyPixels(this._targetBMData,this._rectangle,_rPoint,this._alphaGrBMData);
            }
        }
        
        public function clearBMData():void{
                        this._targetBMData = null;
                        this._alphaGrBMData = null;
                        this._combinedBMData = null;        
        }
    }
}