mheavers
mheavers

Reputation: 30158

flash as3 - getting a parent clip's position relative to the child's position

I'm trying to use an enter frame event in flash as3 to draw a line between a parent and the child clip as they are dragged or move around the screen. I actually had this working using the following code:

/*private function drawLine(childCircle,parentCircle):void
{
    parentCircle.graphics.clear();
    parentCircle.graphics.lineStyle(lineWeight,lineColor);
    parentCircle.graphics.moveTo(0,0);
    parentCircle.graphics.lineTo(childCircle.x,childCircle.y);
}*/

But the problem is multiple child circles can be created from the parent, and so the function above clears out the line from the parent to the first child in favor of drawing from the parent to the second child. So I figured I needed to add the line to the child circle instead of the parent, but when I do this I can't get the right coordinates for the parent circle relative to the child. This is my code:

private function drawLine(childCircle,parentCircle):void
{
    //trace (parentCircle.x + "|" + childCircle.x);
    childCircle.graphics.clear();
    childCircle.graphics.lineStyle(lineWeight,lineColor);
    childCircle.graphics.moveTo(0,0);
    childCircle.graphics.lineTo(parentCircle.x,parentCircle.y);
}

Anyone know how I would do this? I saw the functions for globalToLocal and localToGlobal, but I don't want the global position - just the position one level up. I tried this:

private function drawLine(childCircle,parentCircle):void
{
    trace (parentCircle.x + "|" + childCircle.x);
    childCircle.graphics.clear();
    childCircle.graphics.lineStyle(lineWeight,lineColor);
    childCircle.graphics.moveTo(0,0);
    childCircle.graphics.lineTo(-childCircle.x,-childCircle.y);
}

and it ends up in the right spot, but it causes a problem with the drag-ease equation I'm using because the line is tethered to the child clip instead of the parent.

Upvotes: 0

Views: 1234

Answers (3)

PatrickS
PatrickS

Reputation: 9572

Instead of drawing from the parent, I would consider creating a Child class that takes care of its own line drawing. I would also forget about the Enter Frame event and instead implement the line drawing only when the Child is moving... In this case it is triggered by a MouseMove event but it could be any other type of trigger.

private var container:DisplayObject;
private var line:Shape = new Shape();

public function Child()
{
      //add the Line to be drawn as a Shape
      addChild( line );

      //everything starts after the Child has been added to the Stage
      addEventListener( Event.ADDED_TO_STAGE , onAdded );
}

private function onAdded( event:Event):void
{
      // remove this listener
      removeEventListener( Event.ADDED_TO_STAGE , onAdded );

      //identify the container
      container = this.parent;

      //listen to a Mouse Down event
      addEventListener( MouseEvent.MOUSE_DOWN , onMouseDown );

      //the Stage listens to a Mouse Up event
      stage.addEventListener( MouseEvent.MOUSE_UP , onMouseUp );
}

private function onMouseDown( event:MouseEvent):void
{
     //start listening to the Mouse Move when the mouse is down
      addEventListener( MouseEvent.MOUSE_MOVE , onMouseMove );
}

private function onMouseMove( event:MouseEvent):void
{ 
     //draw the line from the parent coordinates to the child coordinates
     line.graphics.clear();
     line..graphics.lineStyle(1);
     line.graphics.moveTo( container.x , container.y );
     line.graphics.lineTo( this.x , this.y );
}

private function onMouseUp( event:MouseEvent):void
{
      removeEventListener( MouseEvent.MOUSE_MOVE , onMouseMove );
}

Upvotes: 1

kreek
kreek

Reputation: 8834

This will give you a draggable parent clip, that also contains draggable child clips connected to the parent by lines.

Circle class:

package
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;

    public class Circle extends Sprite
    {
        private var _fill:int;

        public function Circle(fill:int=0xFFFFFF)
        {
            super();

            this._fill = fill;

            this.addEventListener(MouseEvent.MOUSE_DOWN, _startDrag);
            this.addEventListener(MouseEvent.MOUSE_UP, _stopDrag);

            draw();
        }

        public function draw():void
        {
            this.graphics.lineStyle(2);
            this.graphics.beginFill(this._fill);
            this.graphics.drawCircle(0, 0, 7);
            this.graphics.endFill();
        }

        private function _startDrag(e:MouseEvent):void
        {
            e.stopPropagation()
            this.startDrag();
        }

        private function _stopDrag(e:MouseEvent):void
        {
            e.stopPropagation()
            this.stopDrag();
        }
    }
}

Main class (stage class)

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

    [SWF(backgroundColor="#EDEDED", frameRate="30", width="500", height="500")]
    public class Main extends Sprite
    {
        private var _parentCircle:Circle;
        private var _children:Array = [];

        public function Main()
        {
            _parentCircle = new Circle(0xFF0000);
            this.addChild(_parentCircle);
            _parentCircle.x = 250;
            _parentCircle.y = 250;

                    // create some children
            for (var i:int=0; i < 5; i++)
            {
                var childCircle:Circle = new Circle();
                childCircle.x = Math.random() * 500 - 250;
                childCircle.y = Math.random() * 500 - 250;
                _parentCircle.addChild(childCircle);
            }

            this.addEventListener(Event.ENTER_FRAME, _redraw);
        }

        private function _redraw(e:Event):void
        {
            _parentCircle.graphics.clear();
            _parentCircle.graphics.lineStyle(1);

            for (var i:int=0; i < _parentCircle.numChildren; i++)
            {
                var child:DisplayObject = _parentCircle.getChildAt(i);
                _parentCircle.graphics.moveTo(0, 0);
                _parentCircle.graphics.lineTo(child.x, child.y);
            }

            _parentCircle.draw();
        }
    }
}

Upvotes: 0

tolmark
tolmark

Reputation: 1816

You could do something like this:

private function drawLines():void
{
    // Clear graphics, prep line style
    parentCircle.graphics.clear();
    parentCircle.graphics.lineStyle(lineWeight,lineColor);

    // Create an array of all children to draw to, then 
    // loop through that array drawing a line to each 
    var ar:Array = [child1, child2, child3];
    var len:uint = ar.length;
    for ( var i:uint=0; i<len; i++ )
    {
        drawLine( ar[i], parentCircle );
    }
}

private function drawLine(childCircle,parentCircle):void
{
    parentCircle.graphics.moveTo(0,0);
    parentCircle.graphics.lineTo(childCircle.x,childCircle.y);
}

Upvotes: 0

Related Questions