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

时间:2016-07-22 13:05:40

标签: actionscript-3 flash

我的问题是:我有一个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内的MovieClip事件Click({{ 1}})被解雇了,我该如何解决这个问题?只有在没有拖动动作时才会触发它们。

3 个答案:

答案 0 :(得分:2)

这是我处理拖动具有可点击儿童的父级的方法。这种方法的好处是,您不需要对孩子做任何事情(点击处理程序中没有额外条件等),点击事件根本无法到达。

您还可以从以下代码/评论中获得一些效率提示:

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;
        }
    }
}

答案 1 :(得分:1)

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

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事件中,我将存储的位置与实际位置进行比较,如果等于, TADA!

答案 2 :(得分:0)

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

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