如何防止拖动操作影响 MovieClip 的子项

How to prevent a drag action to affect the childrens of a MovieClip

我的问题是:我有一个 MovieClip (obj),用户可以将其拖动到两侧进行导航,我为此使用的代码:

import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import flash.geom.Rectangle;

var destination: Point = new Point();
var dragging: Boolean = false;
var speed: Number = 10;
var offset: Point = new Point();
var bounds: Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);

obj.addEventListener(MouseEvent.MOUSE_DOWN, startdrag);
stage.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
obj.addEventListener(Event.ENTER_FRAME, followmouse);

function startdrag(e: MouseEvent): void {
    offset.x = obj.mouseX * obj.scaleX;
    dragging = true;
}

function stopdrag(e: MouseEvent): void {
    dragging = false;
}

function followmouse(e: Event): void {
    if (obj) {
        if (dragging) {
            destination.x = mouseX;
        }

        obj.x -= (obj.x - (destination.x - offset.x)) / speed;

        if (obj.x > bounds.left) {
            obj.x = bounds.left;
        }

        if (obj.x < -obj.width + bounds.right) {
            obj.x = -obj.width + bounds.right;
        }
    }
}

到目前为止一切顺利,当我在 MovieClip (obj) 中放置一些可点击元素时出现问题,这是可点击元素的代码:

objA.addEventListener(MouseEvent.CLICK, objATrigger);
objB.addEventListener(MouseEvent.CLICK, objBTrigger);
objC.addEventListener(MouseEvent.CLICK, objCTrigger);

function objATrigger(event: MouseEvent): void {
    MovieClip(this.parent).gotoAndPlay(1, "Main");
}

function objBTrigger(event: MouseEvent): void {
    MovieClip(this.parent).gotoAndPlay(1, "Main");
}

function objCTrigger(event: MouseEvent): void {
    MovieClip(this.parent).gotoAndPlay(1, "Main");
}

问题是:当我拖动MovieClip(obj)时和事件有冲突,当拖动后松开鼠标时,MovieClip(Click里面的MovieClips事件Click obj) 被解雇了,我该如何解决这个问题?它们应该只在没有拖动操作时触发。

在 objATrigger 函数中添加条件以检查拖动是否为 false

function objATrigger(event: MouseEvent): void {
    if(!MovieClip(root).dragging){
        MovieClip(this.parent).gotoAndPlay(1, "Main");
    }
}

我不知道这是否是最好的方法,但可以使用以下代码进行检查:

stage.addEventListener(MouseEvent.MOUSE_DOWN, setmousepos);
brose_trigger.addEventListener(MouseEvent.MOUSE_UP, broseTrigger);
denso_trigger.addEventListener(MouseEvent.MOUSE_UP, densoTrigger);
honda_trigger.addEventListener(MouseEvent.MOUSE_UP, hondaTrigger);

var mousePos: Point = new Point();

function setmousepos(e:MouseEvent): void {
    mousePos.x = mouseX;
}

function broseTrigger(e:MouseEvent): void {
    if(mousePos.x == mouseX){
        MovieClip(this.parent).gotoAndPlay(1, "Main");
    }
}

function densoTrigger(event:MouseEvent): void {
    if(mousePos.x == mouseX){
        MovieClip(this.parent).gotoAndPlay(1, "Main");
    }
}

function hondaTrigger(event:MouseEvent): void {
    if(mousePos.x == mouseX){
        MovieClip(this.parent).gotoAndPlay(1, "Main");
    }
}

MOUSE_DOWN事件被触发时,我将mouse.x位置存储在一个变量中,然后在MOUSE_UP事件中,我将存储的位置与实际位置进行比较,如果等于,TÃDÃ!

这就是我如何处理拖动具有可点击 children 的 parent。这种方法的好处是,您不需要对 children 做任何事情(在他们的点击处理程序中没有额外的条件等),点击事件根本不会到达他们。

您还可以希望从下面的 code/comments 中获得一些效率提示:

var wasDragged:Boolean = false;
var dragThreshold:Point = new Point(10,10); 
// ^ how many pixels does it need to move before it's considered a drag
//this is good especially on touchscreens as it's easy to accidentally drag the item a couple pixels when clicking.

var dragStartPos:Point = new Point(); //to store drag origin point to calculate whether a drag occured
var dragOffset:Point = new Point(); //to track the gap between the mouse down point and object's top left corner

obj.addEventListener(MouseEvent.MOUSE_DOWN, startdrag);
obj.addEventListener(MouseEvent.CLICK, dragClick, true); //listen on the capture phase of the event. 

//the only reason we listen for click on the draggable object, is to cancel the click event so it's children don't get it
function dragClick(e:Event):void {
    //if we deemed it a drag, stop the click event from reaching any children of obj
    if(wasDragged) e.stopImmediatePropagation();
}

function startdrag(e: MouseEvent): void {
    //reset all dragging vars
    wasDragged = false;
    dragStartPos.x = obj.x;
    dragStartPos.y = obj.y;

    //set the offset so the object doesn't jump when first clicked
    dragOffset.x = stage.mouseX - obj.x;
    dragOffset.y = stage.mouseY - obj.y;

    //only add the mouse up listener AFTER the mouse down
    stage.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
    //mouse_move is more efficient that enter_frame, and only listen for it when dragging
    stage.addEventListener(MouseEvent.MOUSE_MOVE, followmouse); 
}

function stopdrag(e:MouseEvent = null): void {
    //remove the dragging specific listeners
    stage.removeEventListener(MouseEvent.MOUSE_UP, stopdrag);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, followmouse); 
}

function followmouse(e:MouseEvent): void {
    if (obj) {
        //do what you need to move the object
        obj.x = stage.mouseX - dragOffset.x;
        obj.y = stage.mouseY - dragOffset.y;

        //check if the obj moved far enough from the original position to be considered a drag
        if(!wasDragged 
            && (Math.abs(obj.x - dragStartPos.x) > dragThreshold.x
            || Math.abs(obj.y - dragStartPos.y) > dragThreshold.y)
        ){
            wasDragged = true;
        }
    }
}