版本:2.4.3

 

一 事件模型

二 事件阻挡

三 事件穿透

四 currentTarget和Target

 

一 事件模型

点击后依次进入捕获,目标和冒泡阶段。

 

 

 

二 事件阻挡

如下图,现在实现只让白色响应事件,不让红色响应事件。(注意层级关系,红色包含着白色)

 

 给红色和白色添加点击事件

this.white.on(cc.Node.EventType.TOUCH_END, ()=>{console.log("white click")},this);
this.red.on(cc.Node.EventType.TOUCH_END, ()=>{console.log("red click")},this);

 

 

 

点击红色 (捕获阶段,目标阶段红色,冒泡阶段到canvas节点)

点击白色  (捕获阶段,目标阶段白色,冒泡阶段到红色节点,所以红白都能响应)

点击白色和红色重叠区域(同上)

 

给在上方的白色挂上一个Block Input Events组件

 

 

事件会被阻挡,点击白色或红白重叠区域只有白色响应事件,红色不会响应点击事件。 (捕获阶段,目标阶段白色,禁止传递,于是没有冒泡到红色节点)

 

在白色绑定了blockInputEvents组件的情况下,红色监听使用useCapture=true,在捕获阶段生效。则点击红白重叠区域,红色和白色都能响应。

因为捕获阶段到红色节点生效,目标阶段白色生效,白色阻止事件传播,所以冒泡不到红色节点。因为捕获阶段就生效,所以冒泡阻挡不阻挡无所谓。

this.red.on(cc.Node.EventType.TOUCH_END, () => { console.log("red click") }, this, true);
this.white.on(cc.Node.EventType.TOUCH_END, () => { console.log("white click") }, this);

 

 

看一下BlockInputEvents源码,使用了stopPropagation阻止了事件的传递。

 

 

 

三 事件穿透

现在实现让红色和白色都能响应事件。 (注意red和white的层级关系,事件阻挡例子里是包含关系,这里是上下层关系)

点击白色

 

 点击红色

 

点击白红色重叠区域,默认情况下只有上方的白色响应事件,红色不会响应点击事件。

 

编写一个穿透事件组件,并给上层的白色添加该组件。

const { ccclass, property } = cc._decorator;

/**
 * 该组件将所属节点内的所有输入事件穿透到下层节点,一般用于上层 UI 的背景。
 * 该组件没有任何 API 接口,直接添加到场景即可生效。
 */
@ccclass
export class ThroughInputEvents extends cc.Component {
    onLoad(): void {
        (this.node as any)._touchListener.setSwallowTouches(false);
    }
}

  

添加穿透事件组件后,再次点击红白重叠区域,则白色和红色都能响应事件

 

这是白色物体设置setSwallowTouches不能吞噬事件,会保持事件的传递。

 

四 currentTarget和Target

 

 

        this.red.on(cc.Node.EventType.TOUCH_END, (e)=>{console.log("red:",e)},this);
        this.white.on(cc.Node.EventType.TOUCH_END, (e)=>{console.log("white:",e)},this);

 

点击白色后,事件经过捕获阶段,目标阶段target是白色节点,然后冒泡currentTarget到红色节点。

 

 

 

点击红色,通过捕获阶段,到达目标阶段target红色,冒泡后因为没有其他节点在监听,所以冒泡阶段currentTarget仍然是红色节点。

如果canvas也监听点击的话,冒泡后currentTarget会是canvas。

 

利用currentTarget和Target,可以简化一下按钮监听。例如3个按钮使用同一个响应函数处理,用target来区别点击了哪一个按钮。

 

 

    start() {
        this.red.on(cc.Node.EventType.TOUCH_END, this.onBtnTap, this);
        this.white.on(cc.Node.EventType.TOUCH_END, this.onBtnTap, this);
        this.green.on(cc.Node.EventType.TOUCH_END, this.onBtnTap, this);
    }

    private onBtnTap(e: cc.Event.EventTouch) {
        switch (e.target) {
            case this.red:
                console.log("red touch");
                break;
            case this.white:
                console.log("white touch");
                break;
            case this.green:
                console.log("green touch");
                break;
        }
    }

  

 也可以只监听buttonNode,需要设置useCapture=true

    start() {
        this.buttonNode.on(cc.Node.EventType.TOUCH_END, this.onBtnTap, this, true);
    }
    private onBtnTap(e: cc.Event.EventTouch) {
        switch (e.target) {
            case this.red:
                console.log("red touch");
                break;
            case this.white:
                console.log("white touch");
                break;
            case this.green:
                console.log("green touch");
                break;
        }
    }

  

posted on 2020-11-12 11:22  gamedaybyday  阅读(4707)  评论(0编辑  收藏  举报