《Cocos Creator游戏实战》手势缩放功能实现

手势缩放功能实现

创建节点

编写脚本


在这篇教程中我们来实现一个手势缩放功能。

运行效果如下:

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。

向左向上和向下移动时同理。

好了,本期就成就到此为止,希望大家有所收获~

发布了83 篇原创文章 · 获赞 157 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/La_vie_est_belle/article/details/103778819