效果

实现这个非常简单巧妙
源码在文末

实现思路


节点有点多,一个一个讲解下
bg是游戏背景图,主要是为了和灰黑色的遮罩区别

Btn_parent是三个按钮的父节点,加了一个layout,使每个按钮不互相挨着挤得慌
hand是白色的引导手

label是引导文字

Mask是遮挡节点,他还有一个单色精灵子节点,单色精灵子节点就是所有灰色的部分,单色精灵上加了一个widget保持和canvas上下左右为0


代码奉上~


import { _decorator, Component, Node, ButtonComponent, Vec3, SystemEventType, LabelComponent, CCFloat, CCString, error } from 'cc';
const { ccclass, property } = _decorator;@ccclass('Guide')
export class Guide extends Component {@property({displayName: "按钮", tooltip: "按钮,请按想要引导的顺序绑定", type: ButtonComponent})all_btn: ButtonComponent[] = [];@property({displayName: "遮挡节点", tooltip: "遮挡节点", type: Node})mask: Node = null!;@property({displayName: "半透明精灵", tooltip: "半透明精灵", type: Node})sprite: Node = null!;@property({displayName: "引导手", tooltip: "白色的手,用来指向按钮的", type: Node})hand: Node = null!;@property({displayName: "引导文字内容", tooltip: "引导的文字内容,绑定了多少个按钮就要有多少个文字内容,如果文字内容数量少于按钮数量会出现错误", type: CCString})label_string: string[] = [];@property({displayName: "引导的文字", tooltip: "引导的文字", type: LabelComponent})label: LabelComponent = null!;@property({displayName: "每几秒多显示一个字", tooltip: "打字机每几秒多显示一个字", type: CCFloat})label_time: number = 0.1;// 每个按钮的位置pos: Vec3[] = [];// 当前进行到了第几个按钮num: number = 0;// 引导的文字是否可以继续显示,如果用户在打字机文字全部显示出来之前点击下一个按钮,就会出现文字乱套的现象,这个变量就是防止文字乱套所做的is_string: boolean[] = [];onLoad () {let self = this;// 给每个按钮绑定onbtn方法for (let i = 0; i < this.all_btn.length; i++) {this.all_btn[i].node.on(SystemEventType.TOUCH_END, function () {self.onbtn();}, this);}// 记录每个按钮的位置for (let i = 0; i < this.all_btn.length; i++) {this.pos.push(this.all_btn[i].node.position);}// 遮罩位置到第一个按钮this.mask.position = this.pos[0];// 设置文字显示内容this.set_lable_string(this.label, this.label_string[0]);if (this.label_string.length < this.all_btn.length) {error("引导文字内容的数量少于按钮的数量,请在编辑器添加引导文字,否则会出现错误");}}update () {// 如果遮挡节点还没被销毁就往下执行if (this.mask.isValid == false) {return;}// 精灵的位置必须是负的这样才能填充整个屏幕this.sprite.position = new Vec3(-this.mask.position.x, -this.mask.position.y, 1.0);// 引导手的位置和遮挡节点的位置一样   引导手的锚点是0.5, 1this.hand.position = this.mask.position;}// 点击按钮专用函数onbtn () {// 更新进行到哪个按钮this.num ++;// console.log("num", this.num, "allbtn长度", this.all_btn.length);// 如果所有按钮都进行过了if (this.num >= this.all_btn.length) {// 销毁手和遮挡节点和引导文字this.mask.destroy();this.hand.destroy();this.label.destroy();// 点击按钮什么也不发生this.onbtn = function () {};console.log("新手引导完毕!!!mask,hand和label节点已经销毁");// 销毁本脚本this.destroy();return;}// 设置文字显示内容this.set_lable_string(this.label, this.label_string[this.num]);// 遮挡节点到按钮的位置this.mask.position = this.pos[this.num];}// 设置label显示内容   打字机效果   label为指定组件,string为显示内容set_lable_string (label: LabelComponent, string: string) {let self = this;// 文字可以继续显示this.is_string.push(true);let num = this.is_string.length - 1;// 上一次文字不可以继续显示this.is_string[num - 1] = false;// 设置显示内容为空label.string = "";// 将文本截成一个字一个字的数组let str: string[] = string.split("");// for循环利用定时器实现打字机效果for (let i = 0; i < str.length; i++) {// 文本的每个字let string = str[i];this.scheduleOnce(function () {// 如果可以显示if (self.is_string[num] == true) {// 显示给labellabel.string = label.string + string;}}, i * this.label_time);}}}

脚本随便找个节点挂上就可以

介绍完了节点也给出了代码,来讲下实现原理

在单色精灵上加了cc.BlockInputEvents,它的作用是将拦截所属节点 bounding box 内的所有输入事件(鼠标和触摸),防止输入穿透到下层节点,一般用于上层 UI 的背景。简单点说就是在它之下的(被灰黑精灵遮住的)按钮全部点不了,只有在mask遮挡节点遮住的那一小块白色不发灰暗的区域能点击按钮

不需要给button一个一个绑定事件,只需要把按钮都绑定到Guide脚本即可
在onLoad中给每个按钮绑定事件,并且记录下每个按钮的位置,之后每点击一次按钮就设置mask位置为下一个按钮的位置

灰黑色精灵的坐标必须是负的mask的坐标,这样灰黑色精灵才能填充满整个屏幕
引导的白色手位置设置成和遮挡节点一样就可以,但是一定要设置好锚点,不然会很奇怪


点击按钮会判断是否完毕引导,完毕引导会销毁遮挡节点、引导白色手节点和引导文字节点,最后销毁脚本
最重要的是设置文本的显示内容,为了达到打字机的效果我自己封装了set_label_string方法,只需要传入label组件和字符串就可以以打字机效果显示文本
最后根据进行到了哪个按钮和之前存起来的每个按钮的位置,更新mask节点位置

set_label_string方法如下

源码:https://gitee.com/propertygame/cocos-creator3.x-demos/tree/master/NoviceGuide
技术交流Q群:1130122408
更多内容请关注微信公众号

Creator新手引导 | 限制只能点击一个按钮 | 文字打字机效果相关推荐

  1. jq实现点击一个按钮,触发另一个点击事件(点击按钮触发另一个按钮的点击事件)

    jq实现点击一个按钮,触发另一个点击事件 $("#a").click(function(){$("#b").trigger('click');}) 实现点击完i ...

  2. vue 点击一个按钮触发两个事件_vue事件点击穿透解决大法

    最近在做项目的过程中遇到一个非常奇葩的bug,在h5页面点击一个按钮弹出弹窗,但是这个弹窗刚出现就会自动消失,导致屏幕出现闪动现象,关键这个bug还是偶现的.经过一番研究才发现是vue事件点击穿透引起 ...

  3. MFC 点击一个按钮去触发DATE TIME PICKER的DTN_DROPDOWN事件

    转自:https://zhidao.baidu.com/question/135291549740469005.html 我想点击一个button控件去把date time picker控件的下拉框给 ...

  4. 点击一个按钮显示div,点击div之外的地方div隐藏,点击div之内的地方div不隐藏

    <input id="btnClick" type="button" value="原生写法" class="btn-gre ...

  5. 原生JS实现点击一个按钮显示一个div,再点击按钮div隐藏,或点击除div外其它空白处div隐藏...

    <!DOCTYPE html> <html style="font-size: 24px"> <head><title>js点击按钮 ...

  6. java通过按钮打开新窗口_如何在java程序中,当点击一个按钮后,关闭当前窗口,开启一个新的窗口。...

    JButton btn=new JButton(new AbstractAction("关闭并打开") {      @Override   public void actionP ...

  7. java弹框形式输入_java中点击一个按钮弹出两个输入文本框的源代码

    展开全部 写了一个很简单的案例,可以参考和修改import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.eve ...

  8. 在页面里点击一个按钮后出来一个层,可以操作的那么一个层!

    演示:http://www.bl.gov.cn/english/invest_adv.php 这个页面里面你点一下中间那个YOUR QUESTION,出来一个层,可以操作的 <!DOCTYPE ...

  9. jquery 打开服务器文件管理,javascript - 前端js如何封装一个方法或者是jQuery的插件实现点击一个按钮打开本地文件管理系统,进行上传文件...

    世界只因有你2017-05-16 13:38:563楼 前段时间封装的一个方法,使用ajax和formData方法,实现文件上传,在上传的过程中显示上传进度 js $('#upload').on('c ...

最新文章

  1. java工程webservice的应用案例
  2. MySQL从删库到跑路
  3. 英特尔柏安娜:数据中心演进的三大推动力
  4. 模拟退火算法理论+Python解决函数极值+C++实现解决TSP问题
  5. Java集合框架上机练习题:用户分别从两个文本框输入学生的姓名和分数.............
  6. ArrayUtils的简单学习
  7. 13.简述MYSQL的权限级别_MySQL权限级别
  8. Sightseeing Cows POJ - 3621
  9. 函数分组学通MongoDB——第三天 细说高级操作
  10. 前端埋点的缺点_【埋点学习埋点质量】埋点的框架设计及其准确性
  11. 那些年,翻过山,趟过河,挖了山丘,黑了河沟,终于还是遇到了——跨服务器查询...
  12. Cocos2dx---------------- TinyXml 解析 XML
  13. element UI实现动态生成多级表头
  14. testbench的简单例子和模板
  15. 怎么在当前文件目录下打开CMD
  16. One-shot Face Reenactment(BMVC19)
  17. 个人定制ESXi安装程序(集成三方网卡驱动程序)
  18. 使用H5开发移动端app
  19. matlab相反数计数,怎么把origin表格中的数改成相反数
  20. 怎样用c语言实现CPU超频,cpu超频教程【操作流程】

热门文章

  1. 大牛手把手教你!Service有几种启动方式?吐血整理
  2. CentOS7下安装Hadoop伪分布式
  3. [经验]HP小机一次无故当机的经历总结
  4. 过拟合的原因和解决方案
  5. 手写迷你版HashMap
  6. 数字IC笔试之结绳法
  7. 想学机器学习吗?带坑的那种
  8. 比较经典的位字段例题(颜色三原色)
  9. css实现圆柱的形状
  10. 对PyramidBox的理解