zoukankan      html  css  js  c++  java
  • 绕点旋转(老问题)

    绕某点旋转学习Matrix的使用,以及MatrixTransformer.rotateAroundExternalPoint方法

    圆点可以移动位置,长方形鼠标拖动,先看MatrixTransformer.rotateAroundExternalPoint的使用

    import fl.motion.MatrixTransformer;
    //-----------------初始化全局变量------------
    var m:Matrix;
    //rotateAroundExternalPoint方法的初始矩阵,在点击时初始化
    var tempY:Number 
    = point.y;//旋转初始起点,以后是上一次终点
    var tempX:Number 
    = point.x;//

    //-----------------旋转中心点的移动控制-------------------
    point.addEventListener(MouseEvent.MOUSE_DOWN,downmove);
    function downmove(e:MouseEvent) {
        e.target.startDrag();
        stage.addEventListener(MouseEvent.MOUSE_UP,up);
    }

    //-------------------当鼠标按在线上时------------------
    line.addEventListener(MouseEvent.MOUSE_DOWN,down);
    function down(e:MouseEvent) {
        tempY 
    = mouseY;//得到旋转起始点
        tempX 
    = mouseX;//
        m 
    = line.transform.matrix;//实例化旋转矩阵,不能放在旋转函数中,否则有偏移
        stage.addEventListener(MouseEvent.MOUSE_MOVE,moving_fun);
    //鼠标移动侦听
        stage.addEventListener(MouseEvent.MOUSE_UP,up);
    //鼠标松开侦听
    }

    //-------------------------当鼠标松开时--------------------------
    function up(e:MouseEvent) {
        point.stopDrag();
        stage.removeEventListener(MouseEvent.MOUSE_MOVE,moving_fun);

    }

    //--------------------------鼠标移动时旋转控制-------------------------------
    function moving_fun(e:Event ):void {
        
    //下面的new_A、old_A实际上是规范刻度,逆时针刻度由0~360,顺时针刻度由0~-360,防止由-180移到180产生
        
    //360的增加值,所以需要判断,由转换后的刻度差再累加,来实现连续的绝对值增加的角度
        var new_A:Number 
    = Math.atan2(mouseY - point.y,mouseX - point.x)* 180 / Math.PI;//;
        var old_A:Number 
    = Math.atan2(tempY - point.y,tempX - point.x)* 180 / Math.PI;// ;
        
    if (new_A * old_A < 0 && mouseX - point.x < 0) {//判断是否跨过180(-180)线,0度线不需判断
            
    if (new_A > old_A) {//由负角到正角
                old_A 
    = Math.min(new_A,old_A) + 360;//把正刻度变负
            } 
    else {//由正角到负角
                new_A 
    = Math.min(new_A,old_A) + 360;//把负刻度变正
            }
        }
        
    //把  (new_A-old_A)+  累加,可以得到从x轴开始的逆时针刻度由0~360,顺时针刻度由0~-360的变化值
        
    //MatrixTransformer.rotateAroundInternalPoint(m,e.currentTarget.mouseX,e.currentTarget.mouseY,1);
        MatrixTransformer.rotateAroundExternalPoint(m,point.x,point.y,new_A
    -old_A);//
        line.transform.matrix 
    = m;
        tempY 
    = mouseY;//下一次的起点
        tempX 
    = mouseX;

    }

    再看使用Matrix的使用

    import fl.motion.MatrixTransformer;
    //-----------------初始化全局变量------------
    var m:Matrix;
    //rotateAroundExternalPoint方法的初始矩阵,在点击时初始化
    var tempY:Number 
    = point.y;//旋转初始起点,以后是上一次终点
    var tempX:Number 
    = point.x;//

    //-----------------旋转中心点的移动控制-------------------
    point.addEventListener(MouseEvent.MOUSE_DOWN,downmove);
    function downmove(e:MouseEvent) {
        e.target.startDrag();
        stage.addEventListener(MouseEvent.MOUSE_UP,up);
    }

    //-------------------当鼠标按在线上时------------------
    line.addEventListener(MouseEvent.MOUSE_DOWN,down);
    function down(e:MouseEvent) {
        tempY 
    = mouseY;//得到旋转起始点
        tempX 
    = mouseX;//
        m 
    = line.transform.matrix.clone();//实例化旋转矩阵,不能放在旋转函数中,否则有偏移
        stage.addEventListener(MouseEvent.MOUSE_MOVE,moving_fun);
    //鼠标移动侦听
        stage.addEventListener(MouseEvent.MOUSE_UP,up);
    //鼠标松开侦听
    }

    //-------------------------当鼠标松开时--------------------------
    function up(e:MouseEvent) {
        point.stopDrag();
        stage.removeEventListener(MouseEvent.MOUSE_MOVE,moving_fun);

    }

    //--------------------------鼠标移动时旋转控制-------------------------------
    function moving_fun(e:Event ):void {
        
    //下面的new_A、old_A实际上是规范刻度,逆时针刻度由0~360,顺时针刻度由0~-360,防止由-180移到180产生
        
    //360的增加值,所以需要判断,由转换后的刻度差再累加,来实现连续的绝对值增加的角度
        var new_A:Number 
    = Math.atan2(mouseY - point.y,mouseX - point.x) * 180 / Math.PI;//这里需要角度的大小比较
        var old_A:Number 
    = Math.atan2(tempY - point.y,tempX - point.x) * 180 / Math.PI;//不能换成弧度
        
    if (new_A * old_A < 0 && mouseX - point.x < 0) {//判断是否跨过180(-180)线,0度线不需判断
            
    if (new_A > old_A) {//由负角到正角
                old_A 
    = Math.min(new_A,old_A) + 360;//把正刻度变负
            } 
    else {//由正角到负角
                new_A 
    = Math.min(new_A,old_A) + 360;//把负刻度变正
            }
        }
        
    //把  (new_A-old_A)+  累加,可以得到从x轴开始的逆时针刻度由0~360,顺时针刻度由0~-360的变化值
        m.translate(
    -point.x,-point.y);
        m.rotate((new_A
    -old_A)* Math.PI /180) ;
        
    //上面的new_A、old_A是基于角度的计算和判断,所以弧度要到这里才能转换
        m.translate(point.x,point.y);
        line.transform.matrix 
    = m;
        tempY 
    = mouseY;//下一次的起点
        tempX 
    = mouseX;

    }

    还有一个小实例

    源码如下:

    /*在flash cs3中(cs4适用),当主时间轴(stage)上有影片剪辑的实例,且该影片剪辑有实例名称,
      并且关闭了“自动声明舞台上的实例”功能时(文件
    ->发布设置->flash->ActionScript 3.0设置),
      你需要在文档类中声明类为dynamic,或者打开“自动声明舞台上的实例”
    */
    package {
        
    //作者Joel,修改了时间长后漂移旋转中心的现象
        import fl.motion.MatrixTransformer;
        import flash.display.MovieClip;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Matrix;

        
    public class rotateAroundPoint extends Sprite {//dynamic
            
    private var xshift:Number;//x方向偏移旋转中心的位移
            
    private var yshift:Number;//y方向偏移旋转中心的位移
            
    private var isMoving:Boolean;
            
    private var rotation_mc:MovieClip;//选定的旋转目标
            
    private var matrix:Matrix;//旋转目标的矩阵
            
    private var obj:Object;//存储鼠标的位置
            
    private var angularVel:Number;//矩阵旋转的角度
            
    private var decay:Number;//衰减率

            
    public function rotateAroundPoint() {
                init();
            }

            
    private function init():void {
                addEventListener(MouseEvent.MOUSE_DOWN,pressed);
                stage.addEventListener(MouseEvent.MOUSE_UP,released);
                stage.addEventListener(Event.ENTER_FRAME,run);
                isMoving 
    = false;
                decay 
    = .99;
                xshift 
    = 0;
                yshift 
    = 0;
            }
            
    private function pressed(e:Event):void {
                isMoving 
    = true;
                rotation_mc 
    = MovieClip(e.target);
                angularVel 
    = 0;
                xshift 
    = mouseX - rotation_mc.x;
                yshift 
    = mouseY - rotation_mc.y;
                matrix 
    = rotation_mc.transform.matrix;
                obj 
    = {x:mouseX,y:mouseY};

            }

            
    private function released(e:Event):void {
                isMoving 
    = false;
            }

            
    private function run(e:Event):void {
                
    if (isMoving) {
                    
    //当鼠标移动时更新旋转对象的位置,鼠标不动时不影响
                    rotation_mc.x 
    = mouseX - xshift;
                    rotation_mc.y 
    = mouseY - yshift;
                    
                    
    //计算旋转的角度
                    angularVel 
    = angularVel * decay;
                    var A:Number 
    = 0.75;//最大振幅
                    var angle:Number 
    = Math.atan2(rotation_mc.y - mouseY,rotation_mc.x - mouseX);//返回-π~+π
                    angularVel 
    += A * Math.cos(angle);
                    
                    
    //如果鼠标不移动,旋转对象就不需要从本身读取矩阵
                    obj.x!
    =mouseX||obj.y!=mouseY?matrix=rotation_mc.transform.matrix:NaN;
                    MatrixTransformer.rotateAroundExternalPoint(matrix,mouseX,mouseY,angularVel);
                    rotation_mc.transform.matrix
    =matrix;
                    
                    
    //应用矩阵旋转对象时,更新x、y方向的位移
                    xshift
    =mouseX-rotation_mc.x;
                    yshift
    =mouseY-rotation_mc.y;
                    
                    
    //便于鼠标移动时记录下位置
                    obj
    ={x:mouseX,y:mouseY};
                }
            }

        }
    }
     1 import flash.display.MovieClip;
     2 import flash.geom.Matrix;
     3 import flash.geom.Point;
     4 import flash.events.MouseEvent;
     5 import flash.events.Event;
     6 
     7 var isLoop:Boolean = false;
     8 //防止误差累计,在循环外获取一次matrix
     9 var m:Matrix = mc.transform.matrix;
    10 //x、y是mc本地坐标空间的数值
    11 function rotate( x:Number, y:Number, angleDegrees:Number):void
    12 {
    13     var point:Point = new Point(x,y);
    14     //把 point转换到 m 的坐标空间
    15     point = m.transformPoint(point);
    16     //把 m 的坐标空间换成本地坐标空间
    17     m.tx -=  point.x;
    18     m.ty -=  point.y;
    19     //把 m 的坐标空间换成本地坐标空间
    20     m.rotate(angleDegrees*(Math.PI/180));
    21     //把 m 的坐标空间又换回父坐标空间;
    22     m.tx +=  point.x;
    23     m.ty +=  point.y;
    24 
    25     mc.transform.matrix = m;
    26 
    27 }
    28 
    29 this.addEventListener(Event.ENTER_FRAME,init);
    30 function init(e:Event):void
    31 {
    32     if(mc.rotation>=90)
    33     {
    34         mc.rotation=90;
    35         this.removeEventListener(Event.ENTER_FRAME,init);
    36         cl(null)
    37         return;;
    38     }
    39     rotate(0,0,1);
    40 }
    41 stage.addEventListener(MouseEvent.CLICK,cl);
    42 function cl(e:Event):void
    43 {
    44     isLoop = ! isLoop;
    45     if (isLoop)
    46     {
    47         this.addEventListener(Event.ENTER_FRAME,loop);
    48     }
    49     else
    50     {
    51         if (this.hasEventListener(Event.ENTER_FRAME))
    52         {
    53             this.removeEventListener(Event.ENTER_FRAME,loop);
    54         }
    55     }
    56 }
    57 function loop(e:Event):void
    58 {
    59     rotate(100,50,5);
    60 }
  • 相关阅读:
    YbtOJ:NOIP2020 模拟赛B组 Day10
    洛谷11月月赛Ⅱ-div.2
    P1494 [国家集训队]小Z的袜子
    [模板]莫队/P3901 数列找不同
    P4145 上帝造题的七分钟2 / 花神游历各国
    P4109 [HEOI2015]定价
    P4168 [Violet]蒲公英
    分块
    P3378 【模板】堆(code)
    网络基础——网络层
  • 原文地址:https://www.cnblogs.com/ddw1997/p/1578612.html
Copyright © 2011-2022 走看看