Kerberos
Kerberos

Reputation: 1266

remove a movieclip then reposition rest with flash as3

i would like to remove one or more object at runtime.

After each removed movieclip rest movieclips should be reposition as below. (Removed moviclip is 4 at representative figure)

Movieclips can be more.

Thank you for your help already now.

Upvotes: 3

Views: 664

Answers (6)

Amy Blankenship
Amy Blankenship

Reputation: 6961

Try something like

var top:int = 0;
for (var i:int=0;i<numChildren;i++) {
    var child:Sprite=getChildAt(i);
    child.y = top;
    top += child.height;
}

Edit for explanation

Let's say that you are removing the movice clip when it is clicked. In your main document Class, you might have something like this (assumes all instances are present in frame 1, and nothing else is there):

//constructor
public function MainDocumentClass() {
   for (var i:int; i<numChildren; i++) {
     var child:Sprite = getChildAt(i) as Sprite;
     child.addEventListener(MouseEvent.Click, deleteMe);
   }
}

protected function deleteMe(e:MouseEvent):void {
    var child:Sprite = e.currentTarget as Sprite;
    child.removeEventListener(MouseEvent.Click, deleteMe);
    rearrange();
}

protected function rearrange():void {
   var top:int = 0; 
   for (var i:int=0;i<numChildren;i++) {     
       var child:Sprite=getChildAt(i);     
       child.y = top;     
       top += child.height; 
    }   
}

Upvotes: 6

Jacksonkr
Jacksonkr

Reputation: 32207

var stack:Array = [];

function render():void {
  while(this.numChildren) this.removeChildAt(0); // removes all existing children
  for(var i = 0; i < stack.length; ++i) {
    var c = stack[i];
    c.y = this.height;
    this.addChild(c);
  }
}

stack.push(num1);
stack.push(num2);
stack.push(num3);
render();

stack.splice(1,1); // removes the second item from [stack]
render();

Plenty of good examples already, I just wanted to add a short one. Enjoy.

Upvotes: 2

Taurayi
Taurayi

Reputation: 3207

You could create a custom DisplayObjectContainer class and override the addChild(), addChildAt(), removeChild(), removeChildAt() methods so that they not only add or remove a display object but also rearrange all the child display objects positions too. I made an example to demonstrate this:

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.text.TextField;

    public class Main extends Sprite 
    {
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);

        }// end function

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            var vGroup:VGroup = new VGroup();
            var blocks:Vector.<Sprite> = new Vector.<Sprite>();

            for (var i:uint = 0; i < 5; i++)
            {
                blocks.push(getBlock(i + 1, 100, 100));
                vGroup.addChild(blocks[i]);

            }// end for

            addChild(vGroup);

            vGroup.removeChild(blocks[3]);
            vGroup.removeChildAt(0);
            vGroup.addChildAt(getBlock(6, 100, 100),1);

        }// end function

        private function getBlock(id:int, width:Number, height:Number):Sprite
        {
            var sprite:Sprite = new Sprite();
            sprite.graphics.lineStyle(1, 0x000000);
            sprite.graphics.beginFill(0xFFFF00);
            sprite.graphics.drawRect(0, 0, width, height);
            sprite.graphics.endFill();

            var textField:TextField = new TextField();
            textField.text = id.toString();
            sprite.addChild(textField);
            return sprite;

        }// end function

    }// end class

}// end package

import flash.display.DisplayObject;
import flash.display.Sprite;

internal class VGroup extends Sprite
{
    override public function addChild(child:DisplayObject):DisplayObject
    {
        var displayobject:DisplayObject = super.addChild(child);

        arrange();

        return displayobject;

    }// end function

    override public function addChildAt(child:DisplayObject, 
                                        index:int):DisplayObject
    {
        var displayobject:DisplayObject = super.addChildAt(child, index);

        arrange();

        return displayobject;

    }// end function

    override public function removeChild(child:DisplayObject):DisplayObject
    {
        var displayobject:DisplayObject = super.removeChild(child);

        arrange();

        return displayobject;

    }// end function

    override public function removeChildAt(index:int):DisplayObject
    {
        var displayobject:DisplayObject = super.removeChildAt(index);

        arrange();

        return displayobject;

    }// end function

    private function arrange():void
    {
        if (numChildren > 0)
        {
            for (var i:uint = 0; i < numChildren; i++)
            {
                getChildAt(i).y = (i > 0) ? getChildAt(i - 1).y + getChildAt(i - 1).height : 0;

            }// end for

        }// end if

    }// end function

}// end class

[UPDATE]

Each line of the following code:

vGroup.removeChild(blocks[3]); // removes block 4
vGroup.removeChildAt(0); // removes block 1
vGroup.addChildAt(getBlock(6, 100, 100),1); // adds block 6

produces the following respective outputs(except the first which is the initial output):

enter image description here

Upvotes: 3

Exort
Exort

Reputation: 1075

You don't need to reposition everything. Start from previous index.

EDIT : I added the click handlers logic following Amy's post logic

//constructor
public function MainDocumentClass() 
{
    for (var i:int; i<numChildren; i++) 
    {
        var child:DisplayObject = getChildAt(i) as DisplayObject ;
        child.addEventListener(MouseEvent.Click, deleteMe);
   }
}

//click handler
protected function deleteMe(e:MouseEvent):void 
{
    //generic line to remove a listener
    IEventDispatcher(event.target).removeEventListener(event.type, arguments.callee);

    var pos:int = container.getChildIndex(e.target as DisplayObject);

    if(pos<0)
        return;

    container.removeChildAt(pos);
    rearrange(pos);
}

protected function rearrange(pos:int = 0):void
{
    for(; pos< container.numChildren; pos++) 
    {
        if(pos == 0) 
        {
            //this is the first, so position at 0
            container.getChildAt(pos).y = 0;
        } 
        else 
        {
            //position based on previous child
            var prev:DisplayObject = container.getChildAt(pos-1);
            container.getChildAt(pos).y = prev.y + prev.height;
        }
    }
}

Upvotes: 1

Benny
Benny

Reputation: 2228

var count:Number = 0;
var mc:Sprite;
var i:uint;
var pattern:RegExp = /\d+/;
btn_mc.addEventListener(MouseEvent.CLICK, action);
container_mc.addEventListener(MouseEvent.CLICK, action);
function action(e:MouseEvent):void 
{
    var str:String = e.target.name;
    if(str == "btn_mc")
    {
        mc = new Sprite();
        mc.graphics.beginFill(Math.random() * 0xffff00,1);
        mc.graphics.drawRect(0,0,20,20);
        mc.graphics.endFill();
        mc.buttonMode = true;
        container_mc.addChild(mc);
            mc.y = mc.width * count * 1.1;
        mc.name = "item" + count;
        count++;
        mc.addEventListener(MouseEvent.CLICK, action0);
    }
}
function action0 (e:MouseEvent):void 
{
    container_mc.removeChild(container_mc.getChildByName(e.target.name));
    var no:Number = e.target.name.match(pattern);
    var diff:Number = count - no;
    for( i = no+1; i< no+diff; i++)
    {
        container_mc.getChildByName("item"+i).y -= mc.width * 1.1;
    }
    count --;
    for(i = 0; i< container_mc.numChildren - 1; i++)
    {
        mc.name = "";
        container_mc.getChildAt(i+1).name = "item"+i;
    }
    trace(container_mc.numChildren);
}

u needs to create container_mc and btn_mc in your stage.

Upvotes: 0

shanethehat
shanethehat

Reputation: 15560

If we can assume that these movieclips are added to their own container (as in, a container that contains only these moveclips), and that they are added sequentially, then this is quite easy.

container.removeChild(someMC);
for(var i:int = 0; i < container.numChildren; i++) {
    if(i == 0) {
        //this is the first, so position at 0
        container.getChildAt(i).y = 0;
    } else {
        //position based on previous child
        var prev:DisplayObject = container.getChildAt(i-1);
        container.getChildAt(i).y = prev.y + prev.height;
    }
}

Upvotes: 2

Related Questions