cocos creator Touch事件应用(触控选择多个子节点的实例)


Posted in Javascript onSeptember 10, 2017

最近参与了cocos creator的研究,开发小游戏,结果被一个事件坑得不行不行的。现在终于解决了,分享给大家。

原理

1.触控事件是针对节点的

2.触控事件的冒泡,是直接关系冒泡,父子可以,孙子不行,就是不能隔代冒泡

3.父节点不响应触控事件,肯定是被孩子节点遮挡了,只要孩子节点也监听一下事件,父节点就可以响应了

4.触控位置是绝对坐标,相对于整个canvas,节点位置相对于父节点,相对位置可以与绝对坐标相互转化

5.节点是否被触控到,touch start事件可以肯定被触摸到,但是一个节点触摸到必须等待其结束,另一个节点才能响应touch事件

6.判断是否框选中,根据坐标计算相互交叉即是选中。就是说我从触控起点->触控终点 构成的矩形区域,与节点的矩形存在重叠,就是被框选。本例中,采用比较粗略的算法实现,根据横坐标的范围是否包含子节点的横坐标判断是否选中。

7.计算某个数值是否在某一范围内,首先计算出范围的最大值、最小值,然后作比较即可。

核心代码

cc.Class({
 extends: cc.Component,

 properties: {
  // foo: {
  // default: null,  // The default value will be used only when the component attaching
  //       to a node for the first time
  // url: cc.Texture2D, // optional, default is typeof default
  // serializable: true, // optional, default is true
  // visible: true,  // optional, default is true
  // displayName: 'Foo', // optional
  // readonly: false, // optional, default is false
  // },
  // ...
   poker:{
    default:null,
    type:cc.Node
   },
   cardMask:{
    default:null,
    type: cc.Prefab
   }
 },

 // use this for initialization
 onLoad: function () {
   
   //牌
   this.cards = this.poker.children;

   //牌初始位置
   this.cardInitY = this.cards[0].y;

   //触摸选择到的牌
   this.touchedCards = [];

   //选中的牌
   this.selectedCards = [];

   console.info(this.cards);
  },
  
  start: function () {
   // this.cards = this.poker.children;
   // console.info(this.cards);
   
   this.addTouchEvent();
  },

  /**
   * 添加事件
   */
  addTouchEvent:function(){

   //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)
   this.poker.on(cc.Node.EventType.TOUCH_START, function (event) {
    console.log('poker TOUCH_START');
    
    //牌
    var card = event.target;
    
    //起始触摸位置(和第一张card一样,相对于poker的位置)
    this.touchStartLocation = this.cards[0].convertTouchToNodeSpace(event);
    console.log('touch start Location:'+ JSON.stringify(this.touchStartLocation));
    
    //计算牌位置
    var index = 0;
    for(var i=0;i<this.cards.length;i++){
     var c = this.cards[i];
     if(c.name == card.name){
      index = i;
      break;
     }
    }

    //暂存第一次触摸到的牌
    var touchedCard = {
     index:index,
     card:card
    };
    this.firstTouchedCard = touchedCard;
    //暂存
    this.pushTouchedCards(touchedCard.index,touchedCard.card);

   }, this);
  
   //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)
   this.poker.on(cc.Node.EventType.TOUCH_MOVE, function (event) {
    console.log('poker TOUCH_MOVE');
    //先清除原先触摸到的牌
    this.clearTouchedCards();
    //保存第一张牌
    this.pushTouchedCards(this.firstTouchedCard.index,this.firstTouchedCard.card);

    //触摸点转换为card节点坐标
    var nodeLocation = this.cards[0].convertTouchToNodeSpace(event);
    console.log('touch nodeLocation:'+ JSON.stringify(nodeLocation));
    var x = nodeLocation.x;
    var y = nodeLocation.y; 

    //找到当前选中的牌
    var currentCard = null;
    for(var i=0;i< this.cards.length;i++){
     var card = this.cards[i];
     var cardX = card.x;
     var cardY = card.y;
     console.log('card x='+cardX+',y='+cardY);


     //某张牌范围包括了鼠标位置,选中此牌与触摸开头的所有牌
     var cardWidth = i==5 ? card.width:19;
     var cardHeight = card.height;
     if(cardX<=x && x <= cardX+cardWidth && cardY<=y && y<= cardY+cardHeight){
      currentCard = card;
    
      //暂存触摸到的牌
      this.pushTouchedCards(i,card);
      
      break;
     }
    }
    
    //添加开头与此牌直接的所有牌
    var startTouchLocation = this.touchStartLocation;
    for(var i=0;i< this.cards.length;i++){
     var card = this.cards[i];
     var cardX = card.x;
     //框选的范围包括了的牌
     var min,max;
     if(startTouchLocation.x < nodeLocation.x){
      min = startTouchLocation.x;
      max = nodeLocation.x;
     }else{
      min = nodeLocation.x;
      max = startTouchLocation.x;
     }
     console.log('min='+min+', max='+max);

     if(min <= cardX && cardX <= max){
      //暂存触摸到的牌
      this.pushTouchedCards(i,card);
     }
    }
    

   }, this);
  
  //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)
  this.poker.on(cc.Node.EventType.TOUCH_END, function (event) {
   console.log('poker TOUCH_END');
   this.doSelectCard();
  }, this);
  
  //父节点监听touch事件(直接子节点必须注册同样的事件方能触发)
  this.poker.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {
   console.log('poker TOUCH_CANCEL');
   this.doSelectCard();
  }, this);
  
  //给所有的牌注册事件,会自动冒泡到poker节点
  for(var i=0;i< this.cards.length;i++){
   var cards = this.cards;
   //闭包传递i值
   (function(i){
    var card = cards[i];
    card.on(cc.Node.EventType.TOUCH_START, function (event) {
     console.log('card TOUCH_START');
    }, card);
    
    card.on(cc.Node.EventType.TOUCH_MOVE, function (event) {
     console.log('card TOUCH_MOVE');
    }, card);

    card.on(cc.Node.EventType.TOUCH_END, function (event) {
     console.log('card TOUCH_END');
    }, card);
 
    card.on(cc.Node.EventType.TOUCH_CANCEL, function (event) {
     console.log('card TOUCH_CANCEL');
    }, card);

   
   })(i)
   
  }
  
 },

 /**
  * 暂存触摸到的牌
  */
 pushTouchedCards:function(index,card){
  //构造牌对象
  var cardObj = {
   index:index,
   name:card.name,
   isSelected:card.y==this.cardInitY?false:true //高度不一样,表示选中
  };
  
  //防止重复添加
  var existCard = this.touchedCards.find(function(obj){
   if(obj.name == card.name){
    return obj;
   }else{
    return null;
   }
  });
  if(!existCard){
   //添加暂存
   this.touchedCards.push(cardObj);

   //包含提示
   this.addCardMask(card);
  }
 },

 /**
  * 清除原先暂存的触摸到的牌
  */
 clearTouchedCards:function(){
  for(var i=0;i<this.touchedCards.length;i++){
   var cardIndex = this.touchedCards[i].index;
   var card = this.cards[cardIndex];
   card.removeChild(card.children[0]);
  }
  this.touchedCards = [];
 },

 /**
  * 选择牌
  */
 doSelectCard:function(){
  this.selectedCards = [];

  console.log(this.touchedCards);

  //改变牌状态
  for(var i = 0; i< this.touchedCards.length;i++){
   var cardObj = this.touchedCards[i];
   var card = this.cards[cardObj.index];
   if(cardObj.isSelected){ //如果是选中改为不选中
    card.y = card.y - 30;
   }else{ //不选中改为选中状态
    card.y = card.y + 30;
   }
  }

  //重置
  this.clearTouchedCards();

  //显示选中的牌
  this.showSelectedCards();
 },

 /**
  * 包含牌遮罩
  */
 addCardMask:function(card){
  var cardMask = cc.instantiate(this.cardMask);
  cardMask.setPosition(cc.p(0, 0));
  card.addChild(cardMask);
  },

 /**
 * 显示选中的牌
 */
 showSelectedCards:function(){
  this.selectedCards = [];
  for(var i=0;i< this.cards.length;i++){
   var card = this.cards[i];
   var isSelected = card.y==this.cardInitY?false:true;
   if(isSelected){
    this.selectedCards.push(card.name);
   }
  }
  //输出
  console.info("selected cards is: "+ JSON.stringify(this.selectedCards));
 },

 
 // called every frame, uncomment this function to activate update callback
 // update: function (dt) {

 // },
});

效果

cocos creator Touch事件应用(触控选择多个子节点的实例)

以上这篇cocos creator Touch事件应用(触控选择多个子节点的实例)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
再谈javascript 动态添加样式规则 W3C校检
Dec 25 Javascript
js 判断checkbox是否选中的实现代码
Nov 23 Javascript
Node.js:Windows7下搭建的Node.js服务(来玩玩服务器端的javascript吧,这可不是前端js插件)
Jun 27 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
Nov 14 Javascript
推荐5 个常用的JavaScript调试技巧
Jan 08 Javascript
JavaScript实现强制重定向至HTTPS页面
Jun 10 Javascript
javascript实现数组去重的多种方法
Mar 14 Javascript
Bootstrap中的Panel和Table全面解析
Jun 13 Javascript
多功能jQuery树插件zTree实现权限列表简单实例
Jul 12 Javascript
Js实现中国公民身份证号码有效性验证实例代码
May 03 Javascript
Angular 4 指令快速入门教程
Jun 07 Javascript
js实现消灭星星(web简易版)
Mar 24 Javascript
把JavaScript代码改成ES6语法不完全指南(分享)
Sep 10 #Javascript
js 发布订阅模式的实例讲解
Sep 10 #Javascript
node.js 发布订阅模式的实例
Sep 10 #Javascript
基于node.js的fs核心模块读写文件操作(实例讲解)
Sep 10 #Javascript
深入浅出webpack教程系列_安装与基本打包用法和命令参数详解
Sep 10 #Javascript
基于AngularJS的简单使用详解
Sep 10 #Javascript
JS获取字符对应的ASCII码实例
Sep 10 #Javascript
You might like
社区(php&amp;&amp;mysql)一
2006/10/09 PHP
为查询结果建立向后/向前按钮
2006/10/09 PHP
WordPress中访客登陆实现邮件提醒的PHP脚本实例分享
2015/12/14 PHP
PHP三种方式实现链式操作详解
2017/01/21 PHP
基于Laravel5.4实现多字段登录功能方法示例
2017/08/11 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
js常用代码段收集
2011/10/28 Javascript
面向对象的Javascript之一(初识Javascript)
2012/01/20 Javascript
运算符&amp;&amp;的三个不同层次
2013/04/07 Javascript
JavaScript怎么判断图片是否加载完成以便获取其尺寸
2014/05/08 Javascript
js控制多图左右滚动切换效果代码分享
2015/08/26 Javascript
jQuery手动点击实现图片轮播特效
2020/04/20 Javascript
Bootstrap每天必学之导航组件
2016/04/25 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
JavaScript toUpperCase()方法使用详解
2016/08/26 Javascript
webix+springmvc session超时跳转登录页面
2016/10/30 Javascript
Vue 表单控件绑定的实现示例
2017/08/11 Javascript
layui实现数据表格点击搜索功能
2020/03/26 Javascript
webpack + vue 打包生成公共配置文件(域名) 方便动态修改
2019/08/29 Javascript
微信小程序实现Swiper轮播图效果
2019/11/22 Javascript
Python装饰器使用示例及实际应用例子
2015/03/06 Python
Python实现感知器模型、两层神经网络
2017/12/19 Python
Python多进程并发与多线程并发编程实例总结
2018/02/08 Python
Python3.0中普通方法、类方法和静态方法的比较
2019/05/03 Python
python循环定时中断执行某一段程序的实例
2019/06/29 Python
python线程池如何使用
2020/05/28 Python
CSS实现半透明边框与多重边框的场景分析
2019/11/13 HTML / CSS
html5 利用canvas实现超级玛丽简单动画
2013/09/06 HTML / CSS
缓解脚、腿和背部疼痛:Z-CoiL鞋
2019/03/12 全球购物
Sahajan美国:阿育吠陀护肤品牌
2021/01/09 全球购物
学生打架检讨书
2014/10/20 职场文书
习近平在党的群众路线教育实践活动总结大会上的讲话
2014/10/21 职场文书
教研活动主持词
2015/07/03 职场文书
我对PyTorch dataloader里的shuffle=True的理解
2021/05/20 Python
MySQL去除重叠时间求时间差和的实现
2021/08/23 MySQL
Vue中使用import进行路由懒加载的原理分析
2022/04/01 Vue.js