cocos creator 实现双指缩放的两种方式

01

效果演示

Cocos Creator 版本:3.4.1

该 demo 演示了双指缩放时通过更改节点的 scale 属性或者更改摄像机的 position 属性实现场景的缩放效果

02

实现方法

两种方式都各有利弊,可以根据使用场景选择合适的方案

1开启多点触控

在项目设置中开启多点触控

2缩放节点

节点的缩放属性随着双指间距的放大缩小进行等比的变化

基本概念:

双指初始间距:双指刚触碰屏幕时的间距

双指当前间距:双指移动时的间距

节点初始缩放:双指刚触碰屏幕时节点的缩放

节点当前缩放:双指移动时节点的缩放

等比关系:

双指当前间距 / 双指初始间距 = 节点当前缩放 / 节点初始缩放

公式变换:

节点当前缩放 = 节点初始缩放 * (双指当前间距 / 双指初始间距)

完整代码:

onTouchMove(event: EventTouch) {
   
       let touches = event.getTouches();    if (touches.length >= 2) {
   
           let temp = v2();        Vec2.subtract(temp, touches[0].getLocation(), touches[1].getLocation());        // 双指当前间距        let distance = temp.length();        if (this.originalTouchDistance == -1) {
   
               // 双指初始间距            this.originalTouchDistance = distance;            // 节点初始缩放            this.originalNodeScale = this.nodeTarget.scale.clone();        }        let targetScale = v3();        // 双指当前间距 / 双指初始间距        let scale = distance / this.originalTouchDistance;        // 节点初始缩放 * (双指当前间距 / 双指初始间距)        Vec3.multiplyScalar(targetScale, this.originalNodeScale, scale);        scale = targetScale.x;        // 属于节点缩放比        scale = clamp(scale, this.minScale, this.maxScale);        this.nodeTarget.setScale(scale, scale, scale);    }}

3移动摄像机

当双指进行缩放操作时,通过移动摄像机的位置,同样可以实现场景缩放的视觉效果

摄像机到原点的距离随着双指间距的放大缩小进行等比的变化

方法和节点缩放一样,只不过是将节点的缩放变为摄像机到原点的距离的缩放

基本概念:

双指初始间距:双指刚触碰屏幕时的间距

双指当前间距:双指移动时的间距

摄像机初始距离:双指刚触碰屏幕时摄像机到原点的距离

摄像机当前距离:双指移动时摄像机到原点的距离

等比关系:

双指当前间距 / 双指初始间距 = 摄像机当前距离 / 摄像机初始距离

公式变换:

摄像机当前距离 = 摄像机初始距离 * (双指当前间距 / 双指初始间距)

求出摄像机当前的距离后,还需要根据距离计算出摄像机的坐标

将场景放大缩小,实际只是将摄像机拉近拉远,并不会改变摄像机的角度

所以可以根据 ∠A,利用三角函数求出摄像机的坐标

利用反正切函数计算 ∠A,即摄像机与水平轴的夹角:

getAngle(a: Vec2, b: Vec2) {
   
       let delta = v2();    Vec2.subtract(delta, a, b);    // http://c.biancheng.net/ref/atan2.html    // 反正切函数 atan2() 和正切函数 tan() 的功能恰好相反:    // tan() 是已知一个角的弧度值,求该角的正切值;而 atan2() 是已知一个角的正切值(也就是 y/x),求该角的弧度值    let degree = misc.radiansToDegrees(Math.atan2(delta.y, delta.x));    return degree;}

利用正弦函数计算对边 a,即摄像机的 y 坐标:

let y = Math.sin(rad) * curCameraDistance;

利用余弦函数计算临边 b,即摄像机的 z 坐标:

let z = Math.cos(rad) * curCameraDistance;

完整代码:

onTouchMove(event: EventTouch) {
   
       let touches = event.getTouches();    if (touches.length >= 2) {
   
           let temp = v2();        Vec2.subtract(temp, touches[0].getLocation(), touches[1].getLocation());        // 双指当前间距        let distance = temp.length();        if (this.originalTouchDistance == -1) {
   
               // 双指初始间距            this.originalTouchDistance = distance;            // 摄像机初始位置            this.originalCameraPosition = this.nodeCamera.position.clone();            // 摄像机初始距离            this.originalCameraDistance = this.originalCameraPosition.length();        }        let scale = this.originalTouchDistance / distance;        // 摄像机机当前距离        let curCameraDistance = this.originalCameraDistance * scale;        // 约束摄像机距离        curCameraDistance = clamp(curCameraDistance, this.minLength, this.maxLength);        // 降维 可以将 z 视作二维平面中的 x        temp = v2(this.originalCameraPosition.z, this.originalCameraPosition.y);        // 计算两点间的角度        let angle = this.getAngle(temp, Vec2.ZERO);        // 根据角度计算弧度        let rad = misc.degreesToRadians(angle);        // http://c.biancheng.net/ref/sin.html        // sinA = 对边 / 斜边 可得 对边 = sinA * 斜边        let y = Math.sin(rad) * curCameraDistance;        // http://c.biancheng.net/ref/cos.html        // cosA = 临边 / 斜边 可得 临边 = cosA * 对边        let z = Math.cos(rad) * curCameraDistance;        this.nodeCamera.position = v3(this.nodeCamera.position.x, y, z);    }}

爱意随风起,风止意难平。

落日归山海,山海藏深意。

更多教程

请扫码关注

猜你喜欢

转载自blog.csdn.net/u010799737/article/details/123181303