事件派发问题,求助大佬

image
做引导,事件穿透派发无法派发到scrollview子节点的子节点下面,
image
如图,所以我想拿到事件后再次手动派发一遍,但直接用node派发,会导致源码的此处出bug,导致我点击其他按钮点两三遍才能正常image
真的头痛 ,求大佬帮忙。

import * as cc from “cc”;

const { ccclass, property } = cc._decorator;

class EventTouch extends cc.EventTouch {

sham?: boolean

}

/**

  • 解决scrollView组件嵌套不能滑动问题

*直接挂在外层scrollView上

*/

@ccclass

export default class ScrollViewNest extends cc.Component {

//----------定义UI----------

//----------定义变量----------

private events: EventTouch[] = [];

onLoad() {

    this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchHandle, this, true);

    this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchHandle, this, true);

    this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchHandle, this, true);

    this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchHandle, this, true);

}

private onTouchHandle(event: EventTouch) {

    if (event.sham || event.simulate || event.target === this.node) return;

    const cancelEvent: EventTouch = new EventTouch(event.getTouches(), event.bubbles, cc.EventTouch.prototype.type);

    cancelEvent.type = event.type;

    cancelEvent.touch = event.touch;

    cancelEvent.sham = true;

    // 问:这里为啥不直接dispatchEvent

    // 答:必须让ScrollView把真的event先消耗掉,我们再发射假的才可以,

    // 可以去CCNode.js下找一个_doDispatchEvent函数,里面用到了_cachedArray这么个全局变量,

    // 先发射假的话,真的那个数据就被清空了

    this.events.push(cancelEvent);

}

update() {

    if (this.events.length === 0) return;

    for (let index = 0; index < this.events.length; index++) {

        this.node.dispatchEvent(this.events[index]);

    }

    this.events.length = 0;

}

}

把这个组件挂在scrollview上,就可以穿透了,也是论坛一个大佬的做法。

不行啊老哥,我的是3.x对代码改了一下,但是无用, 我的情况是从一个引导点击层,穿透下去,结果事件最后的currentTarget变成了scrollview, 哥你看看,孩子还有救么。
import { _decorator, Component, EventTouch, Node } from ‘cc’;

const { ccclass, property } = _decorator;

class ScrollEventTouch extends EventTouch {

sham?: boolean

}

/**

解决scrollView组件嵌套不能滑动问题

*直接挂在外层scrollView上

*/

@ccclass

export default class ScrollViewNest extends Component {

//----------定义UI----------

//----------定义变量----------

private events: ScrollEventTouch[] = [];

onLoad() {

    this.node.on(Node.EventType.TOUCH_START, this.onTouchHandle, this, true);

    this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchHandle, this, true);

    this.node.on(Node.EventType.TOUCH_END, this.onTouchHandle, this, true);

    this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchHandle, this, true);

}



private onTouchHandle(event: ScrollEventTouch) {

    if (event.sham || event.simulate || event.target === this.node) return;



    const cancelEvent: ScrollEventTouch = new ScrollEventTouch(event.getTouches(), event.bubbles, ScrollEventTouch.prototype.type);



    cancelEvent.type = event.type;



    cancelEvent.touch = event.touch;



    cancelEvent.sham = true;



    // 问:这里为啥不直接dispatchEvent



    // 答:必须让ScrollView把真的event先消耗掉,我们再发射假的才可以,



    // 可以去CCNode.js下找一个_doDispatchEvent函数,里面用到了_cachedArray这么个全局变量,



    // 先发射假的话,真的那个数据就被清空了



    this.events.push(cancelEvent);



}

update() {

    if (this.events.length === 0) return;

    for (let index = 0; index < this.events.length; index++) {

        this.node.dispatchEvent(this.events[index]);

    }

    this.events.length = 0;

}

}

如果是单纯的事件穿透 //节点事件穿透,一定要监听4个事件
if (this.clickAreaNode) {
this.clickAreaNode.on(cc.Node.EventType.TOUCH_START, (event: cc.EventTouch) => {
event.preventSwallow = true;
}, this);
this.clickAreaNode.on(cc.Node.EventType.TOUCH_MOVE, (event: cc.EventTouch) => {
event.preventSwallow = true;
}, this);
this.clickAreaNode.on(cc.Node.EventType.TOUCH_END, (event: cc.EventTouch) => {
event.preventSwallow = true;
this.hidePanel();
}, this);
this.clickAreaNode.on(cc.Node.EventType.TOUCH_CANCEL, (event: cc.EventTouch) => {
event.preventSwallow = true;
this.hidePanel();
}, this);
}

(帖子被作者删除,如无标记将在 24 小时后自动删除)