cc.Node emit 的Touch 事件有 Begin,Move,End,Cancel。
拖拽 Drag 操作可以使用 Begin 和 Move 来触发。
我想实现 Drop 操作(类似背包中拖拽起一个件物品,放置到空物品槽)。
根据测试,在Node_A 上TouchBegin,手指不松,Move 到 Node_B 区域内 再松手,无法触发Node_B 的 TouchEnd 和 TouchCancel 事件。
所以背包拖拽,换位置的操作无法实现。
有没有其他实现方案?
cc.Node emit 的Touch 事件有 Begin,Move,End,Cancel。
拖拽 Drag 操作可以使用 Begin 和 Move 来触发。
我想实现 Drop 操作(类似背包中拖拽起一个件物品,放置到空物品槽)。
根据测试,在Node_A 上TouchBegin,手指不松,Move 到 Node_B 区域内 再松手,无法触发Node_B 的 TouchEnd 和 TouchCancel 事件。
所以背包拖拽,换位置的操作无法实现。
有没有其他实现方案?
你用的是什么版本?我这边是没有问题的,你还是先检查一下,或者把代码贴出来看看
使用的 2.0.5
// Learn cc.Class:
// - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/class.html
// - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/class.html
// Learn Attribute:
// - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
// - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
// - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/life-cycle-callbacks.html
cc.Class({
extends: cc.Component,
ctor: function () {
this._dragTesting = false;
this._inDrag = false;
},
properties: {
dragable: {
default: true,
},
dropable: {
default: true,
},
dragStartEvents: {
default: [],
type: cc.Component.EventHandler,
},
dragStopEvents: {
default: [],
type: cc.Component.EventHandler,
},
dropEvents: {
default: [],
type: cc.Component.EventHandler,
},
interactable: {
default: true,
}
},
start() {
},
onEnable() {
this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this);
this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this);
this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
},
onDisable() {
this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this);
this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMove, this);
this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this);
this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
},
_onTouchBegan(event) {
if (!this.interactable || !this.enabledInHierarchy) return;
if(this.dragable) {
this._dragTesting = true;
}
// cc.log(`[drag] start testing`);
event.stopPropagation();
},
_onTouchMove(event) {
if (!this.interactable || !this.enabledInHierarchy) return;
if(this._dragTesting && !this._inDrag) {
if(this.dragable){
let start = event.getStartLocation();
let cur = event.getLocation();
cur.subSelf(start);
if (cur.magSqr() > 20) {
cc.Component.EventHandler.emitEvents(this.dragStartEvents, event);
this.node.emit('drag', this);
this._inDrag = true;
cc.log(`[drag] start drag`);
}
}
}
event.stopPropagation();
},
_onTouchEnded(event) {
cc.log(`touch end`);
if (!this.interactable || !this.enabledInHierarchy) return;
this._dragTesting = false;
if (this._inDrag) {
cc.Component.EventHandler.emitEvents(this.dragStopEvents, event);
this.node.emit('stop', this);
cc.log(`[drag] stop drag`);
}
if(this.dropable) {
cc.Component.EventHandler.emitEvents(this.dropEvents, event);
this.node.emit('drop', this);
cc.log(`[drop]`);
}
this._inDrag = false;
event.stopPropagation();
},
_onTouchCancel(event) {
if (!this.interactable || !this.enabledInHierarchy) return;
if (this._inDrag) {
cc.Component.EventHandler.emitEvents(this.dragStopEvents, event);
this.node.emit('stop', this);
cc.log(`[drag] stop drag`);
}
this._inDrag = false;
event.stopPropagation();
}
});
这是我的脚本, 挂载到两个 Node 上,从 A 拖到 B,松开,touch end 是打印不出来的
没有实际写过这部分代码 touchEnd是在Node范围内离开才会触发的 touchCancel是Node范围外离开触发 你可以用touchCancel监听,判断手指离开位置是否存在其它节点。或者用碰撞检测来判断是否碰撞到其它节点。
你的层级是什么样的?A在上面还是B在上面
没有层级关系,我新建的New Project 两个Node都放在 canvas 下。
所有你是可以 Touch Begin 从 A触发,到 B 触发 TouchEnded 吗?
这是 engine 里 CCEventManager.js 代码,
只有在监听的 Node 上触发 begin,才会在 line 499 行 listener._claimedTouches.push(selTouch);
这样这个 Node 之后的 touchEnd 和 Cancel 才会触发。 (line 501, 502) 分支
因为 Touch Begin 从 NodeA 触发, NodeB 的touch End 在 同一 Touch 移动到 NodeB 上松手, NodeB 不会触发 TouchEnd 事件。
没说nodea事件可以在nodeb触发,你用了event.stopPropagation();所以如果你没有设置zindex,正好B是在A之后创建的,有可能是接受不到的
所以要么你把A的zindex设置大一点,要不A在B之后创建
用Cancel事件不行吗
找到了解决办法
如果有人也需要这个功能,可以参考下。
NodeA 触发拖拽后 当 TouchEnd 和 TouchCancel,触发 NodeA的drop事件,用全局消息 cc.systemEvent.emit(“drop”, event) 往外分发事件。
NodeB 监听全局的 drop 事件,然后 this.node._hitTest() 检测手指松开的点是否在自己的区域内,如果成功就知道有东西drop了。
你有一个例子吗?
因为触发的是a的toucancle事件!
._hitTest() ;这个方法怎么找不到啊?
hitTest 这是 CCNode.js 里面没有开放API的方法
请问咋调用呢,刚刚接触creator