tags:

views:

325

answers:

1

Hello, I want to replicate the standard startDrag/stopDrag events with my own routine to alter things a bit, and I run into some kind of event propagation or bubbling problem. Here is my code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
                mouseDown="mouseDown = true" mouseUp="mouseDown = false"
                mouseMove="mouseMove(event)">

  <mx:Script>
    <![CDATA[
        private var mouseDown:Boolean = false;
        private var oldMouseX:int = 0, oldMouseY:int = 0;

        private function mouseMove(e:MouseEvent):void {
            if (mouseDown) {
                object.x += (e.localX - oldMouseX);
                object.y += (e.localY - oldMouseY);
            }

            oldMouseX = e.localX;
            oldMouseY = e.localY;

            trace(e.localX);
        }
    ]]>
  </mx:Script>  

  <mx:Label id="object" text="Drag me" />

</mx:Application>

The problem with this code is that as you drag the object to the right, you will see in the trace that occasionally some random localX values arrive there, resulting in the object jerking from side to side.

I don't understand how to fix that part, I do think it's the label which bubbles the mousemove event, but I don't understand how to stop it from doing that.
Any suggestions are greatly appreciated!

+2  A: 

Track which target you're concerned about and only listen to events directly from it. So in your mousemove function, check e.target == your object. In this case, the application. You will get stray events bubbling from sub components.

 public static function smoothDrag(pressEvent:MouseEvent, dragTarget:DisplayObject = null, done:Function=null, move:Function = null, parent:DisplayObject = null):void {
  var target:DisplayObject = dragTarget;
  parent = parent || target.parent;
  var eventParent:EventDispatcher = target.stage || parent;

  var moveFunc:Function = move;
  var doneFunc:Function = done;

  var startPoint:Point = MouseHelpers.pointTo(pressEvent.localX, pressEvent.localY, pressEvent.target as DisplayObject, parent);
  startPoint.x -= target.x
  startPoint.y -= target.y;

  var setPosition:Function = function(e:MouseEvent):void 
  {
   e.stopImmediatePropagation();
   var p:Point = MouseHelpers.pointTo(e.localX,e.localY, e.target as DisplayObject, parent);
   target.x = p.x - startPoint.x;
   target.y = p.y - startPoint.y;

   if (moveFunc != null) {
    moveFunc();
   }
  }

  var stopMove:Function = function(e:MouseEvent):void {
   e.stopImmediatePropagation();
   eventParent.removeEventListener(MouseEvent.MOUSE_MOVE, setPosition, true);
   eventParent.removeEventListener(MouseEvent.MOUSE_UP, stopMove, true);
   eventParent.removeEventListener(MouseEvent.ROLL_OVER, EventHelpers.stop, true);
   eventParent.removeEventListener(MouseEvent.MOUSE_OVER, EventHelpers.stop, true);

   if (doneFunc != null) {
    doneFunc(e);
   }
  }
  eventParent.addEventListener(MouseEvent.ROLL_OVER, EventHelpers.stop, true, 0, true);
  eventParent.addEventListener(MouseEvent.MOUSE_OVER, EventHelpers.stop, true, 0, true);
  eventParent.addEventListener(MouseEvent.MOUSE_MOVE, setPosition, true, 0, true);
  eventParent.addEventListener(MouseEvent.MOUSE_UP, stopMove, true, 0, true);
 }


 /**
  * Translate a point from one object's reference into another. Best used when you have a descendant object x/y and you
  *  want to get that position relative to an ancestor. Uses the localToGlobal/globalToLocal style. 
  **/
 public static function pointTo(fromX:Number, fromY:Number, src:DisplayObject, dest:DisplayObject):Point {
  var p:Point = new Point(fromX, fromY);
  if(src != dest) {
   p = src.localToGlobal(p);
   p = dest.globalToLocal(p);
  }
  return p;
 }
Glenn
You mean I should add if (e.target != object) return; on the top of the function? If I do so, the object can't be dragged at all.Otherwise, if I add if (e.target != this) return; then I can drag by moving over the background and not by the object.
melfar
Slight misunderstanding. I've added the code that I use to do a similar thing.
Glenn
You need to use the "pointTo" function to translate the co-ords from the stray events. e.g., the TextField child of Label control.
Glenn
pointTo did fix this, thank you! Although I can see that using stageX instead of localX in this example does the same thing. I think I've totally lost track of the original problem while working on this contrived example. :D Thanks for the source code of your smoothDrag function, I think I am going to be able to scale it to the real-world situation now.
melfar