绕点旋转(老问题)

绕某点旋转学习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 }

 

posted @ 2009-10-06 23:12  ddw1997  阅读(3538)  评论(0编辑  收藏  举报