cocos-js,Widget的addTouchEventListener改善

本文介绍了一个基于ccui.Widget的触摸事件处理方法的改进方案,通过增加不同类型的触摸事件响应方式来解决连续点击导致的问题,包括及时响应、延时响应、一次性响应等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基本使用


addTouchEventListener是属于Widget下的触摸事件相关的操作,基本使用规则如下:

var button = new ccui.Button()
button.addTouchEventListener(this.touchEvent, this)

touchEvent: function (sender, type) {
    switch (type) {
        case ccui.Widget.TOUCH_BEGAN:
            this._topDisplayLabel.setString("Touch Down");
            break;

        case ccui.Widget.TOUCH_MOVED:
            this._topDisplayLabel.setString("Touch Move");
            break;

        case ccui.Widget.TOUCH_ENDED:
            this._topDisplayLabel.setString("Touch Up");
            break;

        case ccui.Widget.TOUCH_CANCELED:
            this._topDisplayLabel.setString("Touch Cancelled");
            break;

        default:
            break;
    }
}

二、为何改善


现在的触摸事件只做监听,并没有相关逻辑上的判断,我们游戏在开发的过程中遇到一些不正常点击而导致的问题。例如:在场景跳转的时候,连续点击两次后,会push两场同样的场景,正常逻辑应该是只push一次。

三、如何改善


先看我在基于原事件基础上添加的一些类型:

ccui.Widget.TOUCH_TYPE_TIMELY                    = 1  //及时:随时点击,随时响应
ccui.Widget.TOUCH_TYPE_DELAY_AFTER               = 2  //延时:随时点击,点击后马上响应,延时一段时间后,响应下次点击
ccui.Widget.TOUCH_TYPE_DELAY_FRONT               = 3  //延时:每次onEnter时,延时一段时间后,才能响应点击
ccui.Widget.TOUCH_TYPE_ONCE                      = 4  //一次:只有一次点击机会,点击后对象触摸禁止,当onExit后恢复
ccui.Widget.TOUCH_TYPE_ALL_BAN                   = 5  //所有:只有一次点击机会,点击后全屏触摸禁止,当onExit后恢复
ccui.Widget.TOUCH_TYPE_DELAY_FRONT_AND_ALL_BAN   = 11 //兼具:DELAY_FRONT和ALL_BAN

代码如下:

ccui.Widget.prototype.addTouch = function(_func,_type,_time){
    var __type = _type || ccui.Widget.TOUCH_TYPE_TIMELY
    var __time = _time || 1

    switch (__type){

        case ccui.Widget.TOUCH_TYPE_TIMELY:
            this.addTouchEventListener(_func)
            break

        case ccui.Widget.TOUCH_TYPE_DELAY_AFTER:
            //当触发点击事件时,将按钮的可触性设置为false,用delayTime延迟1秒后再设置为true
            var that = this
            var __func = function(_sender,_type){
                switch(_type){
                    case ccui.Widget.TOUCH_ENDED:
                        that.setTouchEnabled(false)
                        _func(_sender,_type)
                        that.runAction(cc.sequence(cc.delayTime(__time),cc.callFunc(function(){
                            that.setTouchEnabled(true)
                        }.bind(that))))

                        break
                }
            }
            this.addTouchEventListener(__func)
            break

        case ccui.Widget.TOUCH_TYPE_DELAY_FRONT:
            //在onEnter事件中,将按钮的可触性设置为false,然后delayTime延迟1秒后再设置为true
            this.setOnEnterCallback(function(){
                this.setTouchEnabled(false)
                this.runAction(cc.sequence(cc.delayTime(__time),cc.callFunc(function(){
                    this.setTouchEnabled(true)
                }.bind(this))))
            }.bind(this))

            if (_func == null){
                return
            }

            var __func = function(_sender,_type){
                switch(_type){
                    case ccui.Widget.TOUCH_ENDED:
                        _func(_sender,_type)
                        break
                }
            }

            this.addTouchEventListener(__func)
            break

        case ccui.Widget.TOUCH_TYPE_ONCE:
            //当触发点击事件时,将按钮的可触性设置为false,在onExit事件中设置为true
            var that = this
            var __func = function(_sender,_type){
                switch(_type){
                    case ccui.Widget.TOUCH_ENDED:
                        that.setTouchEnabled(false)
                        _func(_sender,_type)
                        that.setOnExitCallback(function(){
                            that.setTouchEnabled(true)
                        }.bind(that))
                        break
                }
            }
            this.addTouchEventListener(__func)
            break

        case ccui.Widget.TOUCH_TYPE_ALL_BAN:
            //当触发点击事件时,在最上层添加一层遮罩,吞噬掉所有触摸,在onExit事件中移除遮罩
            var that = this
            var __func = function(_sender,_type){
                switch(_type){
                    case ccui.Widget.TOUCH_ENDED:
                        gAddMask()
                        _func(_sender,_type)
                        that.setOnExitCallback(function(){
                            gRemoveMask()
                        }.bind(that))
                        break
                }
            }
            this.addTouchEventListener(__func)
            break

        case ccui.Widget.TOUCH_TYPE_ALL_BAN_AND_DELAY_FRONT:
            //组合,DELAY_FRONT和ALL_BAN
            this.setOnEnterCallback(function(){
                this.setTouchEnabled(false)
                this.runAction(cc.sequence(cc.delayTime(__time),cc.callFunc(function(){
                    this.setTouchEnabled(true)
                }.bind(this))))
            }.bind(this))

            var that = this
            var __func = function(_sender,_type){
                switch(_type){
                    case ccui.Widget.TOUCH_ENDED:
                        gAddMask()
                        _func(_sender,_type)
                        that.setOnExitCallback(function(){
                            gRemoveMask()
                        }.bind(that))
                        break
                }
            }
            this.addTouchEventListener(__func)
            break

        default:
            this.addTouchEventListener(_func)
            break
    }

}

遮罩层的实现:

function gAddMask(){
    var __scene = cc.director.getRunningScene()
    var __mask_layer = __scene.getChildByName("MaskLayer")
    if(!__mask_layer){
        __mask_layer = new MaskLayer()
        __scene.addChild(__mask_layer,99999)
        __mask_layer.setName("MaskLayer")
    }else{
        __mask_layer.setSwallowTouches(true)
    }
}

function gRemoveMask(){
    var __scene = cc.director.getRunningScene()
    var __mask_layer = __scene.getChildByName("MaskLayer")
    if(__mask_layer){
        __mask_layer.setSwallowTouches(false)
    }
}

var MaskLayer = cc.Layer.extend({

    ctor:function(){
        this._super()

        cc.log("wade MaskLayer ctor")

        this.listener = cc.EventListener.create({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,

            onTouchBegan: function (touch, event) {
                cc.log("wade MaskLayer onTouchBegan")
                return true
            },

            onTouchMoved:function (touch, event){
                cc.log("wade MaskLayer onTouchMoved")
            },

            onTouchEnded:function (touch, event){
                cc.log("wade MaskLayer onTouchEnded")
            },
        })

        cc.eventManager.addListener(this.listener, this);

    },

    setSwallowTouches:function(_bool){
        this.listener.setSwallowTouches(_bool)
    }

})

### CocosUI 界面设计教程 Cocos Creator 的 UI 设计工具提供了一个直观的编辑器环境以及强大的脚本扩展能力,使开发者能够轻松构建高质量的游戏界面。以下是关于如何使用 CocosUI 进行界面设计的相关内容。 #### 1. **Canvas 和屏幕适配** Canvas 是所有 UI 元素的根容器,在场景中起到承载整个用户界面的作用。为了适应不同的设备分辨率,可以通过调整 `Canvas` 组件中的属性来设置适配策略。具体来说,可以配置 `Design Resolution` 来指定设计稿尺寸,并启用 `Fit Height` 或 `Fit Width` 实现高度或宽度的比例缩放[^3]。 ```javascript // 设置 Canvas 的适配模式 (示例代码) let canvas = cc.find('Canvas').getComponent(cc.Canvas); canvas.fitHeight = true; canvas.fitWidth = false; ``` #### 2. **Widget 对齐机制** Widget 是一种挂件组件,用于定义 UI 节点相对于其父节点或其他兄弟节点的位置关系。通过设置上下左右四个方向的距离参数,可以精确控制 UI 元素的对齐方式。例如,可以让某个按钮始终位于屏幕右下角并保持固定距离[^3]。 ```javascript // 获取 Widget 并修改对其属性 let widget = node.getComponent(cc.Widget); widget.bottom = 20; // 下边缘偏移量设为 20px widget.right = 20; // 右边缘偏移量设为 20px widget.updateAlignment(); // 更新对齐效果 ``` #### 3. **基础 UI 组件介绍** Cocos Creator 提供了一系列内置的基础 UI 组件,满足大多数常见的界面需求: - **Label**: 显示纯文本信息。 - **Button**: 创建可点击区域,绑定事件响应函数。 - **Sprite**: 渲染静态图像或动态动画帧序列。 - **EditBox**: 支持玩家输入文字的内容框。 - **Layout**: 自动排列多个子项(水平、垂直或网格分布)[^3][^4]。 ##### 示例:创建一个简单的登录窗口 下面是一个综合运用这些基本构件的例子——制作带有用户名密码字段及提交按键的小型表单页面。 ```lua -- Lua 版本实现样例 local function onLoginClick() local username = editUsername.string local password = editPassword.string -- TODO: 添加实际验证逻辑... end -- 初始化控件实例化 editUsername = ccui.EditBox:create(...) editPassword = ccui.EditBox:create(...) btnSubmit = ccui.Button:create("login_button.png", "pressed_login_button.png") btnSubmit:addTouchEventListener(function(sender, eventType) if eventType == ccui.TouchEventType.ended then onLoginClick() end end) ``` #### 4. **高级功能拓展** 如果项目规模较大或者追求更复杂的视觉表现力,则可能需要用到第三方插件如 FairyGUI-CocosCreator 。该库允许导入由 FUISkinEditor 制作好的资源文件 (.fui),从而极大简化了跨平台移植工作流程[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值