当前位置: 首页 > news >正文

cocosCreator 事件系统

概述:

DOM的输入事件通过CCInputManager转化成cocos的输入事件,由CCEventManager 分发给监听器。

监听器在通过回调函数(begin/move/end/cancel)告知事件派发对象(eventTarget)派发事件。

重要类:

event:事件信息对象,主要有触摸信息、鼠标信息、键盘信息等。

eventTarget: 是一个事件派发的对象,有注册,删除和派发等功能,等同于订阅-发布模式。

eventListener:是一个事件监听器的对象,主要用于创建触摸、鼠标、键盘等监听器。包含了类型、回调函数、优先级等。

eventManager:是一个管理监听器的类,主要是对监听器进行排序、分发等。

eventManager

属性:

了解属性可以很好的知道这个类都有做了那些操作,结合函数可以知道是监听器的存储方式,划分监听器的,对监听器都会做什么处理。

  _listenersMap: {}, //key:listenerID  value:_EventListenerVector_priorityDirtyFlagMap: {},//用来存储所有脏数据标记位的事件监听器,key:listenerID value:boolean_nodeListenersMap: {},//key:node._id,value:listeners[]  存储节点的所有事件监听器_toAddedListeners: [],//存储将要添加的事件监听器_toRemovedListeners: [],//存储将要删除的事件监听器_dirtyListeners: {},//key:listenerID  value: boolean_inDispatch: 0,//是否正在处理事件分派标记。 0 表示没有正在处理分派事件_isEnabled: false,//事件管理器是否开启_currentTouch: null,//当前正在处理的触摸事件对象_currentTouchListener: null,//当前正在处理的事件监听器对象_internalCustomListenerIDs: [],//用来存储自定义事件监听器ID

实现功能描述:

  1. 该类是监听器的管理者,因事件监听器有多种类型(总共五个),因此会对每种类型进行管理。
  2. 因事件监听器有触发的先后,所以在对事件监听器管理的时候加入了优先级概念。分为固定优先级、场景图优先级(渲染顺序)。

所以每种事件监听器类型,都有下列存储结构是:

_listenersMap:

  1. _fixedListeners 用于存储固定优先级的监听器(自定义监听器的优先级)
  2. _sceneGraphListeners 用于存储场景图优先级的监听器(就是node的)
  3. gtOIndex 用于标记固定优先级小于大于0的界限索引值。因为场景图优先级默认等于0,自定义优先级可=0

事件监听器触发顺序如下:

  1. 自定义优先级 priority<0
  2. 场景图优先级 listener 触发
  3. 自定义优先级 priority>=0的listener 最后触发。(gtOIndex的索引等于排序后监听器的priority等于0时在数组中的索引。)

自定义优先级时,priority值越小,优先级越高,值越小,优先级越低。场景图优先级_localZOrder越大,优先级越高。反之优先级越低。

  1. 为了可以管理节点上所有的事件监听器,有一个以下数据结构

_nodeListenersMap:

该数据存储着节点的所有类型的监听器,方便对节点上的所有监听器进行选择性的暂停、恢复、删除等功能。

在分发事件监听器时有个很重要的排序过程,其目的为了确定事件监听器的触发先后顺序。具体过程如下:

与排序相关的几个属性:

  1. _priorityDirtyFlagMap:这个map映射存储的是事件监听器类型与脏标记的映射。key=ListenerID;value=dirtyFlag;
  2. _dirtyListeners:暂时记录了有新的场景图优先级的监听器添加,或者是恢复了被暂停的监听器。key=Listener; value=boolean;

因为每种监听器都有固定优先级和场景图优先级之分。如果有新的事件监听器添加或者恢复,都会影响到新监听器相同类型的map数据排序顺序。

所以在每次dispatch的之前,都会对脏数据进行更新,暂时标记那种类型的监听器脏了。在具体的分发之前,会依据标记进行重新排序后再分发。

排序完成之后,_priorityDirtyFlagMap的value值都会标记位非脏数据。

同时有个optimize 点,只在真正分发时,进行一次排序,并非在加入监听器或恢复监听器时排序。

另外需要注意的是,节点的zIndex值被修改后,不单单影响渲染顺序,同时也会影响监听器的分发优先级。(sortAllchildren)

监听器的排序代码解析

  1. 自定义优先级排序算法就是根据设置的priority进行升序排序。priority 数值越小,越早被分发。
  2. 以下是场景图优先级的降序排序算法,层级越高,越早触发,与自定义优先级相反。

其主要考虑的问题又如下几个:1,祖父孙关系。2,非同父关系。3,同父关系

/**
sort的compare函数。降序
compare(a,b){if(a>b)return -1;if(a<b)return 1;return 0;
} 
**/
_sortEventListenersOfSceneGraphPriorityDes: function (l1, l2) {let node1 = l1._getSceneGraphPriority(),node2 = l2._getSceneGraphPriority();//此l1优先if (!l2 || !node2 || !node2._activeInHierarchy || node2._parent === null)return -1;//l2 优先else if (!l1 || !node1 || !node1._activeInHierarchy || node1._parent === null)return 1;/**1,如果是祖孙关系节点,则层级较浅的节点a会在查询一圈之后与层级较深节点b同时汇合在自己初始位置2,如果是非祖孙关系节点,与上述一致,层级较浅的节点a优先到达"祖父"节点为空,到达后从深层级节点初始位置开始最终循环d-s后,ab的祖父节点相同。3,如果是同父节点 直接退出循环总次数计算:node1循环次数为空次数等于a,node2循环次数为空次数等于bconst max = Math.max(a,b);const min = Math.max(a,b);第一次循环min次之后,其中一个节点开始从另一个节点的起始位置开始。接着在循环(max-min)次之后,较深节点会再循环一个差值之后与层级浅的节点 有着共同的祖父节点。总循环次数等于 max。**/let p1 = node1, p2 = node2, ex = false;while (p1._parent._id !== p2._parent._id) {p1 = p1._parent._parent === null ? (ex = true) && node2 : p1._parent;p2 = p2._parent._parent === null ? (ex = true) && node1 : p2._parent;}//node1 与node2 是祖父孙关系,//同祖父孙关系,较浅的节点a会一圈之后在自己初始位置与较深节点b重合。if (p1._id === p2._id) {if (p1._id === node2._id)// p1不等于node1(l1),p1比较深 l1优先return -1;if (p1._id === node1._id)//p1等于node1,p1比较浅,l2优先return 1;}//到这一步已经确定不是祖孙关系了,那就存在 同父或不同父//1,ex=true;p1与p2 是不同父节点,直接对比节点_localZOrder。//2,ex=false; 是同父节点,因为降序所以反向减return ex ? p1._localZOrder - p2._localZOrder : p2._localZOrder - p1._localZOrder;}

这里需要注意的是:_localZOrder 与zIndex、siblingIndex 区别

  1. _localZOrder 是一个32位的数字,前16存储着zIndex节点顺序,后16位存储着子节点相对于在父节点下的索引位置。
  2. 渲染顺序由_localZOrder 决定,节点排序是比较_localZOrder值进行升序排序。
  3. _localZOrder 前16位存储的是zIndex,后16位存储的事siblingIndex(setSiblingIndex)。
  4. zIndex权重比siblingIndex大,如果zIndex 相同,渲染顺序由siblingIndex决定。反之如果修改了zIndex,再次修改siblingIndex毫无效果。
  5. 修改zIndex时,_localZOrder值是在下一帧才会改变,当前帧并不会改变。

在事件监听器触发的过程中,可能会添加新的监听器或者删除监听器。因此有了下列属性

_toAddedListeners:当在添加新的监听器时,遇到正在触发事件监听器时,新的监听器或暂存在该数组中。

_toRemovedListeners:当在添加新的监听器时,遇到正在触发事件监听器时,新的监听器或暂存在该数组中。

_inDispatch:正在分发时>1; 不在分发时=0;

什么时候这些暂存的数据与总数据合并呢?每帧的时候都会去检测是否有暂存数据存在,如果有则与总数据合并(即添加、删除)。

监听器的吞噬与不吞噬,监听的的吞噬情况由三种条件控制

  1. 事件的stopPropagation、stopPropagationImmediate 如果事件设置了停止派发,则监听器的不吞噬也会暂停,其他监听器也不会接受到信息。
  2. 节点的hitTest 返回值 与 监听器的 swallowTouches 值设置。
  3. swallowTouches=true;吞噬 只会分发到自身监听器其他监听器不会被分发。
  4. swallowTouches=false; 不吞噬 下一个监听器也会被分发 依次循环, 直到有一个监听器设置吞噬才不会往下传

参考代码:_dispatchEventToListeners,shouldStopPropagation

eventManager 分发流程

 CCEvent、CClistener、event-target

相关文章:

cocosCreator 事件系统

概述&#xff1a; DOM的输入事件通过CCInputManager转化成cocos的输入事件&#xff0c;由CCEventManager 分发给监听器。 监听器在通过回调函数(begin/move/end/cancel)告知事件派发对象&#xff08;eventTarget&#xff09;派发事件。 重要类&#xff1a; event&#xff1…...

刷题_20:字符串反转 and 公共子串计算

一.字符串反转 题目链接&#xff1a; 字符串反转 题目描述&#xff1a; 接受一个只包含小写字母的字符串&#xff0c;然后输出该字符串反转后的字符串。&#xff08;字符串长度不超过1000&#xff09; 输入描述&#xff1a; 输入一行&#xff0c;为一个只包含小写字母的字符串…...

如何在 Linux 命令行中比较两个目录,我教你五个命令!

在 Linux 命令行中比较两个目录是一项常见的任务&#xff0c;特别是当你需要确保两个目录之间的文件完全相同时。在本文中&#xff0c;我们将介绍一些在 Linux 命令行中比较两个目录的方法。 方法一&#xff1a;使用 diff 命令比较两个目录 diff 命令可以比较两个文件或目录之…...

多元算力如何满足万千本土化场景需求,解析第四代至强核心加速器设计

作者 | 宋慧 出品 | CSDN 云计算 2023 年初&#xff0c;英特尔重磅发布了企业级芯片领域重要的产品——第四代英特尔 至强 可扩展处理器。当时报道中&#xff0c;我们就重点提到了其中重要的七大内置加速器&#xff0c;这也是英特尔为千行百业多种创新场景去提供算力支持的底气…...

SPI主模式切换为从模式

一、SPI主模式切换为从模式在SPI总线上&#xff0c;要将主设备转换为从设备或者将从设备转换为主设备&#xff0c;需要通过改变SPI控制寄存器的配置来实现。下面分别介绍SPI主模式切换为从模式的步骤&#xff1a;配置从设备的SPI控制寄存器首先需要配置从设备的SPI控制寄存器。…...

IMX6ULL学习笔记(21)——MMDC接口使用(DDR3测试)

一、MMDC简介 MMDC 接口与 STM32 的 FSMC 接口类似&#xff0c;只不过 MMDC 接口专用于外接 DDR&#xff0c;并且 MMDC 外部引脚不复用。MMDC 是一个多模的 DDR 控制器&#xff0c;可以连接 16 位宽的 DDR3/DDR3L、16 位宽的 LPDDR2。 MMDC 是一个可配置、高性能的 DDR 控制器。…...

机器学习——无监督学习

机器学习的分类一般分为下面几种类别&#xff1a;监督学习( supervised Learning )无监督学习( Unsupervised Learning )强化学习( Reinforcement Learning&#xff0c;增强学习)半监督学习( Semi-supervised Learning )深度学习(Deep Learning)Python Scikit-learn. http: // …...

python+opencv生成较真实的车牌号码图片

本文参考github代码&#xff1a;https://github.com/loveandhope/license-plate-generator 效果&#xff1a; 一、代码目录结构&#xff1a; background目录下存放各种背景图片 font目录下存放车牌中文、字符的ttf字体 images目录下存放蓝色底牌、新能源绿色底牌、污渍&#…...

3.26周报

周报 代码行数&#xff1a; 周一 581 周二 601 周三 615 周四 591 周五 570 周六 561 周日 577 遇到的问题&#xff1a; 项目启动很慢&#xff0c;要将近5分钟才能开启项目&#xff0c;对开发造成很大困扰。 断点打在奇怪的地方&#xff0c;造成启动缓慢。断点…...

从0开始学python -69

Python math 模块 Python math 模块提供了许多对浮点数的数学运算函数。 math 模块下的函数&#xff0c;返回值均为浮点数&#xff0c;除非另有明确说明。 如果你需要计算复数&#xff0c;请使用 cmath 模块中的同名函数。 要使用 math 函数必须先导入&#xff1a; import…...

HashMap中HashCode的实现原理

代码 static final int hash(Object key) {int h;return (key null) ? 0 : (h key.hashCode()) ^ (h >>> 16);}1. h >>> 16 是什么&#xff0c;有什么用? h是hashcode。h >>> 16是用来取出h的高16&#xff0c;(>>>是无符号右移) 如下展…...

Redis —Set、ZSet介绍和应用场景

Set 概念 Redis的set是一个不重复、无序并唯一的键值集合。&#xff08;方便管理无序集合&#xff09;它支持交集、并集、差集等等 set和list区别 List 可以存储重复元素&#xff0c;Set 只能存储非重复元素&#xff1b;List 是按照元素的先后顺序存储元素的&#xff0c;而…...

【产品人卫朋】内容运营:文章点击量少的可怜,该怎么做?

今天来谈谈内容运营这个话题。 随着自媒体进入视播时代&#xff0c;也就是短视频的时代。 无论你打开任何一个短视频应用&#xff0c;每一个主题下面都会有成千上万个视频。 最为致命的是&#xff0c;大家停留的时间也越来越短了。 如果你不能在2秒的时间内吸引眼球&#xff0c…...

【K8S系列】深入解析无状态服务

目录 序言 1. 无服务介绍 1.1 优点 1.2 使用场景 1.3 资源类型 1.4 总结 2 使用介绍 2.1 Deployment 使用场景&#xff1a; 2.2 ReplicaSet 使用场景 2.3 pod Pod 资源定义示例 2.4 service 创建一个Deployment&#xff1a; 创建一个Service&#xff1a; 总结…...

Node基础--命令窗口

1.Windows命令行窗口(叫做:小黑屏、cmd窗口、终端、shell) (1).如何打开命令行窗口 开始菜单 -- 运行 --- cmd --- enter win R -- cmd --- enter (2).cmd窗口常用指令 dir 列出当前目录下的所有文件 cd 目录名 进入到指定的目录 md 目录名 …...

一些有趣的项目

一个支持交互的展示卷积过程的可视化工具 https://github.com/pwwang/cnn-convoluter 一款简单易用基于 Python scikit 的推荐系统https://github.com/NicolasHug/Surprise 一个封装了 7 种启发式算法的 Python 代码库。分别是&#xff1a;差分进化算法、遗传算法、粒子群算法…...

教你精通JavaSE语法之第六章、数组的使用

一、数组的定义与使用 &#x1f601;1.1数组的概念&#x1f4cc;数组&#xff1a;可以看成是相同类型元素的一个集合。在内存中是一段连续的空间&#xff0c;可以同来存储同种数据类型的多个值。但是数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。比如&#xff1…...

基于51单片机AT89C51的小型音乐喷泉控制系统设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;单片机小喷泉 获取完整无水印论文报告&#xff08;内含电路原理图和程序&#xff09; 根据目前音乐喷泉的发展现状&#xff0c;介绍了一个以AT89C51单片机为核心的小型音乐喷泉控制系统。给出了一个简洁的单片机控制电路&a…...

【Nacos】Nacos原理详解(注册中心,配置中心)

文章目录一、背景二、CAP理论三、什么是NacosNacos 服务注册需要具备的能力&#xff1a;Nacos的实现原理&#xff1a;四、Nacos原理Nacos 服务注册与订阅的完整流程服务领域模型五、注册中心原理六、配置中心原理七、Nacos 的关键特性包括:八、 面试分析一、背景 服务注册中心…...

蓝桥杯刷题冲刺 | 倒计时11天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.质因子2.蓝桥王国1.质因子 题目 链接&#xff1a; 1545. 质因子 - AcWing题库 给定一个整数 N…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...