canvas在startDrag()上移动而不调用set x / y或move() - startDrag()如何在as3 / flex中完全工作?

时间:2011-02-11 16:59:20

标签: flash flex actionscript-3 actionscript draggable

我有一个扩展mx.containers.Canvas的.as类(它是可调整大小的组件的可拖动边框),它在MOUSE_DOWN上变得可拖动,并且在MOUSE_UP MOUSE_OUT上停止拖动}和ROLL_OUT
在调用startDrag()之前我创建一个Rectangle来定义拖动区域,我还有一个_dragging: Boolean变量来控制它是否可以拖动。

问题是,当我点击此边框时,它会跳转到负坐标,不会调用startDrag或将_dragging切换为true

我已经覆盖get xset xget yset ymove()方法以解决它,但我唯一得到的是< strong>位置更改而不调用coords setter或move(),但是当它被更改时,调用getter并返回新的(负)值

所以我的问题是 startDrag()上会发生什么以及如何过滤不需要的传入coords值?

4 个答案:

答案 0 :(得分:1)

这只是一个黑暗中的镜头,但考虑到我最近一直在使用类似的flex部分,这可能就是答案:变换矩阵正在被修改。这将允许对象显示在不同的位置而不修改它的本地位置。因为我还没有测试过,请用大量的盐来回答我的答案。但是,您可以通过观察对象中transform.matrix对象中的变量来检查它是否存在。

答案 1 :(得分:1)

startDrag的进程不会调用x和y setter,因此必须调整transform或transform.matrix。如果要更改转换,则可以覆盖该属性并监视更改。另一方面,如果正在更改transform.matrix子属性,那么您将无法通过覆盖transform属性来检测它。您唯一可能做的就是不使用startDrag并使用鼠标事件移动对象,或者您可以继承Transform类。如果您继承了Transform类并为矩阵属性实现了覆盖,该覆盖属性在更改时通知父级,那么您还必须覆盖任何您要拖动的转换属性以将任何Transform实例转换为子类型并将其与转换后的对象关联,以通知矩阵属性更改。将鼠标按下/移动/向上事件用于移动而不是startDrag将更容易。

理论上这一切都很好,除非它在实施时似乎不起作用。例如:

转换类的子类:

package
{
    import flash.geom.Transform;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.display.DisplayObject;

    public class TransformNotify extends Transform
    {
        public var owner:DisplayObject;

        public function TransformNotify( owner:DisplayObject )
        {
            super( owner );
            this.owner = owner;
        }

        public override function get matrix():Matrix
        {
            trace( "acquiring matrix" );
            return super.matrix;
        }

        public override function set matrix( m:Matrix ):void
        {
            trace( "matrix changing: " + m.tx + "," + m.ty );
            super.matrix = m;
            //Here you could actually alter some property of the owner to notify it that the matrix has changed
            //if (owner != null)
            //{
            //  owner.x = m.tx;
            //  owner.y = m.ty;
            //}
        }
    }   
}

使用子类转换的MovieClip子类:

package
{
    import flash.display.MovieClip;
    import flash.geom.Transform;

    public dynamic class MovieClipTransformed extends MovieClip
    {
        public function MovieClipTransformed()
        {
            super();
            transform = convertToTransformNotify( super.transform );
        }

        public override function get transform( ):Transform
        {
            trace("acquiring transform" );
            if (!(super.transform is TransformNotify))
            {
                var tn:TransformNotify = convertToTransformNotify( super.transform );
                super.transform = tn;
                return tn;
            }
            else
                return super.transform;
        }

        public override function set transform( tf:Transform ):void
        {
            trace( "assigning new transform" );
            if (!(tf is TransformNotify))
                tf = convertToTransformNotify( tf );
            else
                (tf as TransformNotify).owner = this; //take ownership of transform
            super.transform = tf;
        }

        function convertToTransformNotify( tf:Transform ):TransformNotify
        {
            var tfn:TransformNotify = new TransformNotify( this );
            tfn.colorTransform = tf.colorTransform;
            tfn.matrix = tf.matrix;
            tfn.matrix3D = tf.matrix3D;
            tfn.perspectiveProjection = tf.perspectiveProjection;
            return tfn;
        }
    }   
}

并尝试使用该课程:

//Main timeline code
import flash.display.Graphics;
import flash.events.MouseEvent;

var mct:MovieClipTransformed = new MovieClipTransformed();
var g:Graphics = mct.graphics;
g.moveTo( 0, 0 );
g.beginFill( 0xff0000 );
g.drawRect( 0, 0, 100, 100 );
g.endFill();

addChild( mct );
//Make sure override system is functioning properly; should trace that a change has occurred when transform.matrix is modified like so:
mct.transform.matrix = new Matrix( 1,0, 0, 1, 300, 10 ); //seems to function correctly

mct.addEventListener( flash.events.MouseEvent.MOUSE_DOWN, md, false, 0, true );

function md( m:MouseEvent ):void
{
    mct.startDrag( false );
    stage.addEventListener( flash.events.MouseEvent.MOUSE_UP, stageMouseUp, true );
}

function stageMouseUp(e:MouseEvent ):void
{
    stage.removeEventListener( flash.events.MouseEvent.MOUSE_UP, stageMouseUp, true );
    mct.stopDrag();
}

当您在屏幕上拖动红色方块时,请注意没有任何内容被跟踪,因此转换属性不会被更新,并且转换实例的矩阵属性也不会更改。

transform.matrix痕迹的手动设置&#34;矩阵变换:300,10&#34;正如预期的那样,虽然它也跟踪了#矩阵变化:0,0&#34;首先,建议在获得之后将其设置两次,原因不明。我甚至用不同的值重复了这一行,并且再次设置了两次,所以它不仅仅是一些初始化步骤。似乎每次设置transform.matrix属性时,它都会将自身设置为当前值,然后再将自身设置为新值。奇怪。

同样有趣的是,如果我尝试覆盖matrix3D属性,它会给我一个&#34;不兼容的覆盖&#34;错误,即使我确定它的覆盖签名完全匹配。它必须是某种错误或特殊限制。

startDrag的工作方式非常非常错误。没有办法在发生变化时被动地检测到变化;它们只能通过计时器主动观察或在事后检查变化。 startDrag真是太可怕了。

相关问题,尽管有相反的说法,仍然没有解决问题。 How to override the transform.matrix setter

答案 2 :(得分:0)

添加矩形时,请检查注册点(即左上角的位置)。听起来好像是在全局坐标和拖动区域的坐标之间混合。

如果你可以在这里粘贴你的代码,它将帮助人们进一步剖析你。

答案 3 :(得分:0)

从这个开始

var bounds:Rectangle = new Rectangle( 0,0,this.width,this.height)
this.dragBar.startDrag( false,bounds );

并删除您添加的所有覆盖;

我有一种感觉,你的界限是不正确的,它正在“跳跃”,因为边界将它锁定在那里。 你不能拖出界限。 你可以尝试的另一件事是在它“跳了”之后拖动它。这肯定会告诉你这是一个界限问题。