最近cocos开发中需要用到登陆验证滑块,之前准备在webview里嵌入一个H5的验证滑块插件,但是嵌入进来后不能用,cocos会拦截H5的触摸事件,所以就自己从cocos重写了一个。
其原理给背景图添加一个拼图形状的遮罩,作为拖动的图块,再用另一个拼图作为拖拽的目标,判断拖动图块的位置与拖拽目标的位置相同,择判定为验证通过,否则验证失败,代码如下:
import Utils from "../../../game/utils/Utils";
import CEvent from "../../event/CEvent";
import EventMgr from "../../event/EventMgr";
const { ccclass, property } = cc._decorator;
@ccclass
export default class SliderVerification extends cc.Component {
@property(cc.Node)
PieceDrag: cc.Node = null;
@property(cc.Node)
PieceTarget: cc.Node = null;
@property(cc.Sprite)
PieceDragBaseMap: cc.Sprite = null;
@property(cc.Node)
BtnDrag: cc.Node = null;
@property(cc.Sprite)
BaseMap:cc.Sprite = null;
@property(cc.Sprite)
DragEffect:cc.Sprite = null;
@property(cc.Node)
BtnRefresh:cc.Node = null;
@property(cc.Label)
label_tip:cc.Label = null;
@property(cc.Node)
targetPos1:cc.Node = null;
@property(cc.Node)
targetPos2:cc.Node = null;
@property([cc.SpriteFrame])
pic: cc.SpriteFrame[] = [];
@property([cc.SpriteFrame])
mask: cc.SpriteFrame[] = [];
private touchLocation:cc.Vec2 = null;
private config : Array<any> = [];
private lastRandom:number = 1;
private totalCount:number = 10;
onLoad() {
this.initData();
}
onEnable(){
this.BtnDrag.on(cc.Node.EventType.MOUSE_ENTER,this.onHover,this);
this.BtnDrag.on(cc.Node.EventType.MOUSE_LEAVE,this.onOut,this);
this.BtnDrag.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
this.BtnDrag.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this)
this.BtnDrag.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this)
this.BtnDrag.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this)
this.BtnRefresh.on("click",this.onRefresh,this);
EventMgr.getInstance().on(CEvent.REFRESH_PINTU_UI,this.onRefresh,this);
}
onDisable(){
this.BtnDrag.on(cc.Node.EventType.MOUSE_ENTER,this.onHover,this);
this.BtnDrag.on(cc.Node.EventType.MOUSE_LEAVE,this.onOut,this);
this.BtnDrag.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
this.BtnDrag.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this)
this.BtnDrag.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this)
this.BtnDrag.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this)
this.BtnRefresh.off("click",this.onRefresh,this);
EventMgr.getInstance().off(CEvent.REFRESH_PINTU_UI,this.onRefresh,this);
}
start() {
this.onRefresh();
}
private initData():void{
for(let i:number = 0;i<this.totalCount;i++){
let index:number = i+1;
let obj:any = {};
obj["id"] = index;
obj["pic"] = "image"+index+".jpg";
obj["mask"] = "mask"+Utils.random(1,6)+".png";
this.config.push(obj);
}
}
private reset() {
this.label_tip.node.active = true;
this.BtnDrag.x = -1 * this.BtnDrag.parent.width/2;
this.BtnDrag.y = 0;
this.PieceTarget.x = Utils.random(this.targetPos1.x,this.targetPos2.x);
this.PieceTarget.y = 18;
this.PieceDrag.x = (this.PieceDrag.width - this.BaseMap.node.width)/2;
this.PieceDrag.y = this.PieceTarget.y;
this.PieceDragBaseMap.node.x = -this.PieceTarget.x
this.PieceDragBaseMap.node.y = -this.PieceTarget.y+18;
this.DragEffect.node.width = 0;
}
public onRefresh():void{
this.reset();
let random:number = Utils.random(1,10);
if(random == this.lastRandom){
random = Utils.random(1,10);
this.lastRandom = random;
}
this.BaseMap.spriteFrame = this.pic[random-1]
this.PieceDragBaseMap.spriteFrame = this.pic[random-1]
this.PieceTarget.getComponent(cc.Sprite).spriteFrame = this.mask[random-1]
this.PieceDrag.getComponent(cc.Mask).spriteFrame = this.mask[random-1]
}
private onHover():void{
cc.game.canvas.style.cursor = "pointer";
}
private onOut():void{
cc.game.canvas.style.cursor = "default";
}
private onTouchStart(evt: cc.Event.EventTouch) {
const location = evt.getLocation();
this.touchLocation = this.BtnDrag.parent.convertToNodeSpaceAR(location);
this.DragEffect.node.color = cc.color(0,0,255,1);
}
private onTouchMove(evt: cc.Event.EventTouch) {
const location = evt.getLocation();
const touchPoint = this.BtnDrag.parent.convertToNodeSpaceAR(location);
if(touchPoint.x <= (this.BtnDrag.parent.width - this.BtnDrag.width * 2)/2 && touchPoint.x >= -1*(this.BtnDrag.parent.width - this.BtnDrag.width * 2)/2){
this.PieceDrag.x = this.BtnDrag.x = touchPoint.x;
this.DragEffect.node.width = touchPoint.x-this.touchLocation.x+this.BtnDrag.width;
// console.log("moving...",this.PieceDrag.x);
}
this.label_tip.node.active = false;
cc.game.canvas.style.cursor = "pointer";
}
private onTouchEnd(evt: cc.Event.EventTouch) {
const location = evt.getLocation();
const touchPoint = this.BtnDrag.parent.convertToNodeSpaceAR(location);
if (Math.abs(this.BtnDrag.x - this.PieceTarget.x) < 5) {
this.node.active = false;
EventMgr.getInstance().emit(CEvent.VERIFY_SUC,this.node.parent.parent);
} else {
this.PieceDrag.x = (this.PieceDrag.width - this.BaseMap.node.width)/2;
this.PieceDrag.y = this.PieceTarget.y;
this.DragEffect.node.runAction(cc.sequence(cc.tintTo(0.5,255,0,0),cc.callFunc(()=>{
this.reset()
this.onRefresh();
})))
}
cc.game.canvas.style.cursor = "default";
}
}
截图:
效果是没有H5的好看,像H5的验证插件拼图块上都有凹进去,凸出来的表现,凑合着用,后面可以慢慢优化