绕点旋转(老问题)

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

 

转载于:https://www.cnblogs.com/ddw1997/archive/2009/10/06/1578612.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值