手势缩放功能实现
在这篇教程中我们来实现一个手势缩放功能。
运行效果如下:
Cocos Creator版本:2.2.0
后台回复"手势缩放",获取该项目完整文件:
创建节点
在层级管理器中我们只创建了两个节点:
1. maskNode为空节点,不过我们在上面加了一个mask组件用于遮罩。
2. luffy节点就是一张图片(海贼王路飞图)。
maskNode和luffy节点大小一样(也就是说图片正好完全显示):
编写脚本
创建一个Zoom.js脚本,将该脚本挂到Canvas节点上。
现在在properties中添加如下属性:
// Zoom.js
properties: {
maskNode: cc.Node,
picNode: cc.Node,
},
然后在onLoad方法中添加触摸监听相关代码:
// Zoom.js
onLoad () {
// 触摸监听
this.node.on('touchstart', this.onTouchStart, this);
this.node.on('touchmove', this.onTouchMove, this);
},
onTouchStart方法编写如下:
// Zoom.js
onTouchStart (event) {
let touches = event.getTouches();
if (touches.length == 1) {
// 一根手指是移动,这里不用写任何代码
}
else if (touches.length == 2) {
this.startPos1 = this.node.convertToNodeSpaceAR(touches[0].getLocation());
this.startPos2 = this.node.convertToNodeSpaceAR(touches[1].getLocation());
this.pointsDis = this.startPos1.sub(this.startPos2).mag();
}
},
在该方法中我们判断玩家使用的是一根手指还是多根。一根表明只是移动图片,两根手指表明是缩放图片。当手指数量等于1时,我们这里其实不用做什么操作(在onTouchMove方法中会有相关操作代码);当数量等于2时,我们记录下手指们的初始坐标,并计算出这两根手指的距离,后续会用到。
onTouchMove方法如下:
// Zoom.js
onTouchMove (event) {
let touches = event.getTouches();
if (touches.length == 1) {
// 一根手指是移动
let delta = event.getDelta();
this.picNode.setPosition(this.picNode.position.add(delta));
this.restrictPic();
}
else if (touches.length == 2) {
// 两根手指是缩放
let touchPoint1 = this.node.convertToNodeSpaceAR(touches[0].getLocation());
let touchPoint2 = this.node.convertToNodeSpaceAR(touches[1].getLocation());
let newPointsDis = touchPoint1.sub(touchPoint2).mag();
if (newPointsDis > this.pointsDis) {
// 表明两根手指在往外划
this.pointsDis = newPointsDis;
this.picNode.scale += 0.05;
}
else if (newPointsDis < this.pointsDis) {
// 表明两根手指在往内划
if (this.picNode.scale <= 1) {
this.picNode.scale = 1;
return;
}
this.pointsDis = newPointsDis;
this.picNode.scale -= 0.05;
}
this.restrictPic();
}
},
若手指数量为1,我们只用求出手指移动的距离,然后给图片加上这段距离即可(restrictPic方法用于限制图片移动,防止出现黑边,这个我们在最后会讲)。若手指数量为2,我们求出两根手指移动后的新距离,如果该新距离newPointsDis大于初始距离pointsDis,也就是说两根手指在往外划(因为手指间的距离在变大),那么玩家就是想要放大图片。而如果新距离newPointsDis小于初始距离pointsDis,则表明玩家想要缩小图片,但要注意图片scale值最小为1。
放大
缩小
最后我们来看下restrictPic方法:
// Zoom.js
restrictPic () {
// 限制移动,放置出现黑边
let picWidth = this.picNode.getBoundingBox().width;
let picHeight = this.picNode.getBoundingBox().height;
if (this.picNode.x>0 && this.picNode.x-0>picWidth/2-this.maskNode.width/2)
this.picNode.x = picWidth/2-this.maskNode.width/2;
if (this.picNode.x<0 && this.picNode.x-0<this.maskNode.width/2-picWidth/2)
this.picNode.x = this.maskNode.width/2-picWidth/2;
if (this.picNode.y>0 && this.picNode.y-0>picHeight/2-this.maskNode.height/2)
this.picNode.y = picHeight/2-this.maskNode.height/2;
if (this.picNode.y<0 && this.picNode.y-0<this.maskNode.height/2-picHeight/2)
this.picNode.y = this.maskNode.height/2-picHeight/2;
}
注:改变节点的scale值并不会改变节点width和height的实际值。如果要获取节点缩放后能够影响碰撞的width和height值,我们需要调用getBoundingBox方法。
为方便理解以上代码,请大家看下图:
蓝色框为picNode,红色框为maskNode,这里picNode大于maskNode表示玩家已经进行了放大操作。绿点为中心原点(0, 0)。
从图片可以看出,如果向右移动,为了不让画面出现黑边,picNode移动的最大距离就是picWidth/2-this.maskNode.width/2。如果一旦超出,那我们就让picNode的x坐标值等于picWidth/2-this.maskNode.width/2。
向左向上和向下移动时同理。
好了,本期就成就到此为止,希望大家有所收获~