手勢縮放功能實現
在這篇教程中我們來實現一個手勢縮放功能。
運行效果如下:
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。
向左向上和向下移動時同理。
好了,本期就成就到此爲止,希望大家有所收穫~