AS3:使用actionscript设置DisplayObject的注册点?

时间:2009-03-16 14:07:13

标签: flex flash actionscript-3

如何通过动作脚本在Sprite或Shape上设置注册点(我知道使用Flash很简单,但我需要在动作脚本中完成它)

5 个答案:

答案 0 :(得分:12)

Flash Player API不会公开此内容。我相信这是因为Flash在创建SWF时实际上将注册点烘焙到形状数据中。因此,没有实际的注册点可以移动(相反,您可以移动形状数据......如果Flash Player允许您编辑形状数据!)。

我总是通过简单地将我的精灵/形状变为另一个DisplayObject来解决这个问题。所以,如果我有spriteA并希望将其注册点设置为(15,35),我会这样做:


var spriteB:Sprite = new Sprite();
spriteB.addChild(spriteA);
spriteA.x = 15;
spriteA.y = 35;

然后从那时开始,在我之前提到spriteA的地方引用spriteB。

答案 1 :(得分:5)

使用变换矩阵这是可能的。以下是this site上的一个很好的实现。

public function setRegistrationPoint(s:Sprite, regx:Number, regy:Number, showRegistration:Boolean )
{
    //translate movieclip 
    s.transform.matrix = new Matrix(1, 0, 0, 1, -regx, -regy);

    //registration point.
    if (showRegistration)
    {
        var mark:Sprite = new Sprite();
        mark.graphics.lineStyle(1, 0x000000);
        mark.graphics.moveTo(-5, -5);
        mark.graphics.lineTo(5, 5);
        mark.graphics.moveTo(-5, 5);
        mark.graphics.lineTo(5, -5);
        s.parent.addChild(mark);
    }
}

答案 2 :(得分:2)

指的是索引?

跟进评论,你可以像下面这样快速实施。 这不完全是您想要的,因为您无法为每个孩子设置不同的对齐方式。 我只是不想让它太复杂,它更像是'工作伪代码'来给你一个想法...

package  
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;    


    public class SpriteWithRegistration extends Sprite 
    {

        private var _regV:String = "T";
        private var _regH:String = "L";

        private var _width:Number = 0;
        private var _height:Number = 0;


        public function SpriteWithRegistration(width:Number, height:Number, registrationPoint:String = "TL")
        {
            this.width  = height;
            this.height = width;
            this.registrationPoint = registrationPoint;
        }

        public function set registrationPoint(p:String):void
        {
            if(p.length != 2) return;

            var regV:String = p.toUpperCase().substr(0, 1);
            var regH:String = p.toUpperCase().substr(1, 1);

            _regV = (regV == "T" || regV == "C" || regV == "B" ) ? regV : _regV;
            _regH = (regH == "L" || regH == "C" || regH == "R" ) ? regH : _regH;

            alignChildren();
        }

        override public function addChild(child:DisplayObject):DisplayObject
        {
            alignChild(child);
            super.addChild(child);
            return child;
        }

        override public function set width(value:Number):void
        {
            _width = value;
            alignChildren();
        }

        override public function get width():Number
        {
            return _width;
        }

        override public function set height(value:Number):void
        {
            _height = value;
            alignChildren();
        }

        override public function get height():Number
        {
            return _height;
        }

        private function alignChildren():void
        {
            for(var index:int = 0;index < numChildren; index++ )
                alignChild(getChildAt(index));
        }

        private function alignChild(disp:*):void
        {
            switch(_regH)
            {
                case "L":   disp.x = 0;                             break;
                case "C":   disp.x = _width*.5 - disp.width * .5;   break;
                case "R":   disp.x = _width - disp.width;           break;
            }

            switch(_regV)
            {
                case "T":   disp.y = 0;                             break;
                case "C":   disp.y = _height*.5 - disp.height * .5; break;
                case "B":   disp.y = _height - disp.height;         break;
            }
        }
    }
}

答案 3 :(得分:1)

我希望这会对某人有所帮助。 Starling框架有一个很棒的方法叫做#34; alignPivot()&#34;。我采用了他们的概念并将其改编为Flash DisplayList。你基本上告诉一个精灵将它的注册改为左,右,中,上和下。此代码将您的精灵放入容器精灵中并适当地定位自己。它返回包含内部原始精灵的容器精灵。

代码存储在一个单独的名为,&#34; Position&#34;中。

    public static function alignPivot(s:DisplayObject, horizontalAlign: String = "center", verticalAlign: String = "center", showRegistration: Boolean = false, _color: uint = 0x000000): Sprite {

        //create a container sprite to house the sprite you'd like to move
        var _container: Sprite = new Sprite();
        //add your sprite to the continer sprite (the container sprite is what will be returned)
        _container.addChild(s);
        //using getBounds(), find the x,y,width,and height of your sprite within the continer.
        var bounds:Rectangle = _container.getBounds(s);
        //create variables for x and y cooridnates
        var xVal: Number;
        var yVal: Number;

        //I have a separate class called Align which contains public static constants for positiong.
        //Check the values passed above and get the correct x value;
        if (horizontalAlign == Align.LEFT) xVal = -bounds.x;
        else if (horizontalAlign == Align.CENTER) xVal = -bounds.x - bounds.width * .5;
        else if (horizontalAlign == Align.RIGHT) xVal = -bounds.x - bounds.width;
        else throw new ArgumentError("Invalid horizontal alignment: " + horizontalAlign);

        //Check the values passed above and get the correct y value;
        if (verticalAlign == Align.TOP) yVal = -bounds.y;
        else if (verticalAlign == Align.CENTER) yVal = -bounds.y - bounds.height * .5;
        else if (verticalAlign == Align.BOTTOM) yVal = -bounds.y - bounds.height;
        else throw new ArgumentError("Invalid vertical alignment: " + verticalAlign);

        //apply the new x and y cooridnates to your sprite (the one moving within the container we created above)
        s.x = xVal;
        s.y = yVal;

        //optional - this will create a small X at the 0,0 position of the container.
        //This is helpful if you want to see where your registration points are
        if (showRegistration) {
            var mark: Sprite = new Sprite();
            mark.graphics.lineStyle(1, _color);
            mark.graphics.moveTo(-5, -5);
            mark.graphics.lineTo(5, 5);
            mark.graphics.moveTo(-5, 5);
            mark.graphics.lineTo(5, -5);
            _container.addChild(mark);
        }
        //return your contianer sprite
        //This will replace the sprite that you passed in the first parameter.
        //That sprite is inside the container, so you won't notice
        return _container;


    }

实现:

//Create your sprite
        var _holder: Sprite = new Sprite();
    //Create a shape to put in your sprite
        var my_shape: Shape = new Shape();
        my_shape.graphics.beginFill(0x000000);
        my_shape.graphics.drawRect(0, 0, 200, 100);
        my_shape.graphics.endFill();
    //Add the shape to your sprite
        _holder.addChild(my_shape);
    //Align the holder (must be done AFTER all children have been added)
    //This will put the registration point at the top-center of the sprite. 
    //_holder is replaced by a sprite (container) that contains _holder.
    //The _holder inside the container is positioned appropriately.
    _holder = Position.alignPivot(_holder,Align.CENTER, Align.TOP);
    //Add the new sprite to your stage.
    this.addChild(_holder);

常量列表,因此您不必自己编写它们:

    public static const CENTER:String = "center";
    public static const LEFT:String = "left";
    public static const RIGHT:String = "right";
    public static const TOP:String = "top";
    public static const BOTTOM:String = "bottom";

答案 4 :(得分:0)

根据您的需要,可以使用DisplayObject。transformmatrix来解决,它会返回Matrix个对象。

例如,如果你想改变旋转点,那么你可以使用变换矩阵来做到这一点。