Flex3.0 图片浏览器(平移、光标中心点放缩、任意角度旋转)

    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    
    import mx.containers.Canvas;
    import mx.controls.Image;
    import mx.events.ResizeEvent;
    
    /**
     * 图片浏览器
     * 利用仿射变矩阵实现图片的平移、放缩和旋转
     * 其中放缩和平移已经集成在滚轮事件中,放缩调用zoom方法,旋转调用roll方法,居中复位调用reset方法
     * @author lijy 20160114
     * */
    public class ImageViewer extends Canvas
    {
        //图片对象
        private var _image:Image = null;
        //鼠标按下时记录的位置信息,用于平移时计算平移量
        private var _mouseDownPoint:Point = null;
        //记录总放缩比
        private var _totalScaleRatio:Number = 1;
        
        /**
         * 最大放缩比,最大放缩量由放缩比确定
         * */
        public var maxScaleRatio:Number = 5;
        
        /**
         * 最小放缩边长,最小放缩量由最小边长确定
         * */
        public var minScaleLength:Number = 50;
        
        /**
         * 加载图像或 SWF 文件
         * */
        public function load(url:Object=null):void{
            this._image.load(url);
        }
        
        /**
         * 获取作为内容加载的 URL、对象、类或类的字符串名称
         * */
        public function get source():Object{
            return this._image.source;
        }
        
        /**
         * 设置作为内容加载的 URL、对象、类或类的字符串名称
         * */
        public function set source(value:Object):void{
            this._image.source=value;
        }
        
        /**
         * 构造函数初始化图片对象
         * */
        public function DistImageViewer(){
            this._image = new Image();
        }
        
        /**
         * 添加Image到Canvas中,并添加鼠标事件监听
         * */
        override protected function createChildren():void{
            this.addChild(this._image);
            this._image.addEventListener(MouseEvent.MOUSE_DOWN,imgMouseDown);
            this._image.addEventListener(MouseEvent.MOUSE_MOVE,imgMouseMove);
            this._image.addEventListener(MouseEvent.MOUSE_WHEEL,imgMouseWheel);
            this._image.addEventListener(ResizeEvent.RESIZE,imgSizeChanged);
            this._image.addEventListener(Event.COMPLETE,imgLoadComplete);
            super.createChildren();
        }
        
        /**
         * 设置滚轮策略,但是貌似不起作用,需要在调用处重新设置
         * */
        override protected function updateDisplayList(w:Number, h:Number):void{
            this.setStyle('verticalScrollPolicy','off');
            this.setStyle('horizontalScrollPolicy','off');
            super.updateDisplayList(w,h);
        }
                
        /**
         * 鼠标滚轮事件处理用于放缩图片
         * 图片默认的放缩是以左上角为中心点的,要实现以光标位置为中心放缩,需要在放缩后平移图片以保持光标点位置不变
         * */
        private function imgMouseWheel(e:MouseEvent):void{
            //本次放缩比
            var scaleRatio:Number = e.delta>0?1.1:0.9;
            this.zoom(scaleRatio);
            e.stopPropagation();
        }
        
        /**
         * 鼠标点击时,记录点击位置信息,用于在平移时计算平移量
         * */
        private function imgMouseDown(e:MouseEvent):void{
            var matrix:Matrix = this._image.transform.matrix;
            var x:Number = matrix.tx-this.contentMouseX;
            var y:Number = matrix.ty-this.contentMouseY;
            _mouseDownPoint = new Point(x,y);
        }
        
        /**
         * 鼠标移动,使用鼠标按下时记录的位置信息平移图片
         * */
        private function imgMouseMove(e:MouseEvent):void{
            if(e.buttonDown && _mouseDownPoint!=null){            
                var matrix:Matrix = this._image.transform.matrix;                    
                matrix.tx = _mouseDownPoint.x+this.contentMouseX;
                matrix.ty = _mouseDownPoint.y+this.contentMouseY;
                this._image.transform.matrix = matrix;
            }
        }
        
        /**
         * 重新加载新的图片后会引起尺寸改变,此事件用于重新加载图片后居中图片
         * 对于尺寸一样的两个图片,参见imgLoadComplete
         * */
        private function imgSizeChanged(e:Event):void{
            this.reset();
        }
        
        /**
         * 图片加载完成时会触发该事件,但如果此时获取图片的尺寸仍然会得到上一个图片的尺寸
         * 因此在该事件仅能用于居中前后两个尺寸一样的图片,对于尺寸不一样的两个图片,参见imgSizeChanged
         * */
        private function imgLoadComplete(e:Event):void{
            this.reset();
        }
        
        /**
         * 图片放缩
         * @scaleRatio 图片放缩比,通常放大用1.1,缩小用0.9
         * */
        public function zoom(scaleRatio:Number):void{
            //如果超出放缩比则直接返回
            if(_totalScaleRatio*scaleRatio>maxScaleRatio 
                || _totalScaleRatio*scaleRatio*_image.width<minScaleLength
                || _totalScaleRatio*scaleRatio*_image.height<minScaleLength)
                return;
            //获取图片变换矩阵
            var matrix:Matrix = this._image.transform.matrix;
            //把图片参照系上的鼠标点转换为父容器屏幕参照系坐标
            var mousePoint:Point = matrix.transformPoint(new Point(this._image.contentMouseX,this._image.contentMouseY));                                
            //计算图片放缩后光标所在点位置的偏移量,用于放缩后把平移图片,使得放缩后光标所在点位置不变
            var dx:Number=(mousePoint.x-matrix.tx)*(1-scaleRatio)+matrix.tx;
            var dy:Number=(mousePoint.y-matrix.ty)*(1-scaleRatio)+matrix.ty;
            //放缩图片
            matrix.scale(scaleRatio,scaleRatio);
            //重置图片平移量
            matrix.tx=dx;
            matrix.ty=dy;
            //应用变换矩阵
            this._image.transform.matrix = matrix;
            _totalScaleRatio*=scaleRatio;
        }
        
        /**
         * 图片旋转,先平移图片使图片中心点与参照系原点重叠,然后旋转图片,最后把图片平移回原位
         * @angle 旋转角度,正数顺时针,负数逆时针
         * */
        public function roll(degree:Number = 90):void{
            var angle:Number = degree * (Math.PI / 180);
            var matrix:Matrix = this._image.transform.matrix;
            var centerPoint:Point = matrix.transformPoint(new Point(this._image.width/2, this._image.height/2));
            matrix.translate(-centerPoint.x, -centerPoint.y);
            matrix.rotate(angle);
            matrix.translate(centerPoint.x, centerPoint.y);
            this._image.transform.matrix = matrix;
        }
        
        /**
         * 图片居中复位
         * 其中tx和ty的偏移量中额外添加了一个像素的负偏移量,用于强制图片在初始化状态的时候被Canvas容器压盖
         * 否则图片将浮与Canvas上面,而无法被Canvas边框裁剪,(似乎是Flex的Bug)
         * */
        public function reset():void{
             var wScale:Number = this.width/this._image.width;
            var hScale:Number = this.height/this._image.height;
            var scale:Number = wScale<hScale?wScale:hScale;
            var offsetX:Number = (this.width-this._image.width*scale)/2-1;
            var offsetY:Number = (this.height-this._image.height*scale)/2-1;
            var matrix:Matrix = new Matrix(scale,0,0,scale,offsetX,offsetY);
            this._image.transform.matrix=matrix; 
            _totalScaleRatio = scale;
        }
    }
原文地址:https://www.cnblogs.com/ArtofDesign/p/5132978.html