Creator双指缩放和拖动无黑边

Creator双指缩放和拖动无黑边

源码在文末
效果
请添加图片描述
因为PC端不可以双指操作,所以这是现在手机上录屏再到电脑录GIF的结果

节点结构
在这里插入图片描述
遮挡节点
在这里插入图片描述
目标节点,也就是需要缩放和拖动的奥利给图片
在这里插入图片描述
创建一个脚本挂在canvas上

需要在组件里面定义的属性

	@property(UITransformComponent)
    canvas: UITransformComponent = null!;

    @property({displayName: "相机", tooltip: "相机", type: CameraComponent})
    camera: CameraComponent = null!;

    @property({displayName: "目标节点", tooltip: "目标节点", type: Node})
    target: Node = null!;

    @property({displayName: "文字数组", tooltip: "文字数组", type: [LabelComponent]})
    label: LabelComponent[] = [];

    @property({displayName: "遮挡的节点", tooltip: "遮挡的节点,目标节点的父节点", type: UITransformComponent})
    mask: UITransformComponent = null!;

    @property({displayName: "最小缩放倍数", tooltip: "最小缩放倍数", type: CCFloat})
    min_scale: number = 1.00;

    
    // 缩放灵敏度
    SPL: number = 0.5;

    // 上次缩放缩放时两个手指触点连线的长度
    length: number = null!;
    // 上次缩放的时候目标节点的位置,这个除以了缩放倍数,再次用这个值需要重新乘缩放倍数
    pos: Vec2 = null!;

拖动和双指缩放的实现

	onLoad () {
        let self = this;

        // 给遮挡节点绑定移动事件   负责移动目标节点
        this.mask.node.on(SystemEventType.TOUCH_MOVE, function (event: EventTouch) {
            // 获取触点在上一次事件时的位置对象,对象包含 x 和 y 属性
            let last_pos = event.getPreviousLocation();
            // 获取触点位置
            let pos = event.getLocation();
            // 做向量减法
            let dir = last_pos.subtract(pos);
            // 获取目标节点坐标
            let node_pos = self.target.getPosition();
            // 设置目标节点坐标
            self.target.setPosition(new Vec3(node_pos.x - dir.x, node_pos.y - dir.y));

            console.log("移动了目标节点");
        }, this);

        // 给canvas绑定移动事件   负责两个手指缩放
        this.canvas.node.on(Node.EventType.TOUCH_MOVE, function (event: EventTouch) {

            // 获取触点
            let touches = event.getTouches();
            
            // 如果有两个以上触点
            if (touches.length >= 2) {
                // 获取第一个和第二个触点
                let touch1 = touches[0];
                let touch2 = touches[1];

                // 把通过触摸得到的点转到节点坐标,先用camera转为世界坐标再转到canvas节点空间坐标系
                let point1 = self.camera.screenToWorld(new Vec3(touch1.getLocation().x, touch1.getLocation().y));
                let point2 = self.camera.screenToWorld(new Vec3(touch2.getLocation().x, touch2.getLocation().y));
                let touchPoint1 = self.canvas.convertToNodeSpaceAR(point1);
                let touchPoint2 = self.canvas.convertToNodeSpaceAR(point2);
                // 最后转换成vec2
                let tp1 = new Vec2(touchPoint1.x, touchPoint1.y);
                let tp2 = new Vec2(touchPoint2.x, touchPoint2.y);
                // 两触点之差
                let tp_dis = tp1.subtract(tp2);
                // 两触点连线的长度
                let length = tp_dis.length();


                // 如果手指第一次触碰到屏幕
                if (self.length == null) {
                    // 设置两手指触点连线距离
                    self.length = length;
                    console.log("初始化");
                } else {

                    self.label[0].string = "两触点连线长度" + length;

                    // 算出灵敏度
                    let SPL = self.SPL * 1000;

                    // 放大了   本次两触点连线长度大于上次,也就是手指正在做放大动作
                    if (length > self.length) {
                        console.log("放大了");
                        
                        // 算出本次长度和上次长度差
                        let dis = length - self.length;
                        let scale = self.target.getScale();
                        self.target.setScale(scale.x + dis / SPL, scale.y + dis / SPL);
                    }
                    // 缩小了   本次两触点连线长度小于上次,也就是手指正在做缩小动作
                    else if (length < self.length) {
                        console.log("缩小了");

                        // 算出上次长度和本次长度差
                        let dis = self.length - length;
                        let scale = self.target.getScale();
                        self.target.setScale(scale.x - dis / SPL, scale.y - dis / SPL);
                    }
                }


                // 获取目标节点的缩放
                let scale = self.target.getScale();
                // 限制目标节点的缩放,目标节点缩到多小就不能缩了
                if (scale.x <= self.min_scale || scale.y <= self.min_scale) {
                    self.target.setScale(self.min_scale, self.min_scale, 1.0);
                }

                
                
                // 更新label
                self.label[1].string = "目标节点当前缩放:" + self.target.getScale();
                let sc_n = Math.floor(self.target.scale.x / 1.0 * 100) + "%";
                self.label[2].string = "当前缩放:" + sc_n;


                // 更新上次触摸时两触点连线长度
                self.length = length;


                // 获取目标节点缩放
                let sc = self.target.scale.x;
                
                // 如果第一次缩放
                if (self.pos == null!) {
                    // 设置上次目标节点位置   结果为目标节点的位置除以缩放倍数
                    self.pos = new Vec2(self.target.position.x / sc, self.target.position.y / sc);
                } else {
                    // 获取上次目标节点的位置并且乘缩放倍数
                    let pos = new Vec3(self.pos.x * sc, self.pos.y * sc);
                    // 设置目标节点的位置
                    self.target.setPosition(pos);

                    // 设置上次目标节点的位置   结果为目标节点的位置除以缩放倍数
                    self.pos = new Vec2(self.target.position.x / sc, self.target.position.y / sc);
                }
            }
        }, this.node);


        // 给canvas绑定结束触摸事件
        this.canvas.node.on(Node.EventType.TOUCH_END, function () {
            // 设置触点连线长为null,下次手指缩放时再次初始化,如果不写这句代码下一次手指缩放时会因为手指位置与上次距离过大而出现突然放大或缩小的问题
            self.length = null!;
            // 设置目标节点位置为null,下次手指缩放时再次初始化,如果不写这句代码会导致下一次手指缩放时图片位置锁定
            self.pos = null!;
        }, this);
    }

限制目标节点上下左右拖动范围的代码

刚开始做的时候在遮挡节点下创建了一个和目标节点一样大小的纯黑精灵当背景,辅助写限制拖动范围的代码,如果没有限制拖动范围的代码拖动时就会出现纯黑色的黑边,做完之后因为不需要再用就把纯黑精灵节点删掉了,注释和标题写的黑边就是这个意思

	update () {
        // 获取目标节点
        let target = this.target.getComponent(UITransformComponent)!;

        // 获取缩放倍数
        let sc = this.target.scale.x;

        // 获取目标节点和mask的上下左右
        let left_tg = target.node.position.x - (target.width * sc / 2);
        let right_tg = target.node.position.x + (target.width * sc / 2);
        let top_tg = target.node.position.y + (target.height * sc / 2);
        let up_tg = target.node.position.y - (target.height * sc / 2);

        let left = -this.mask.width / 2;
        let right = this.mask.width / 2;
        let top = this.mask.height / 2;
        let up = -this.mask.height / 2;


        // 获取目标节点位置,因为位置会发生变化,下面每个if语句后面都要再获取一次位置
        let pos = this.target.getPosition();
        

        // 检测目标节点不超出规定范围,防止出现黑边
        if (left_tg >= left) {
            this.target.setPosition(new Vec3(left + target.width * sc / 2, pos.y, pos.z));
            // console.log("左边缘");
        }

        pos = this.target.getPosition();

        if (right_tg <= right) {
            this.target.setPosition(new Vec3(right - target.width * sc / 2, pos.y, pos.z));
            // console.log("右边缘");
        }

        pos = this.target.getPosition();

        if (top_tg <= top) {
            this.target.setPosition(new Vec3(pos.x, top - target.height * sc / 2, pos.z));
            // console.log("上边缘");
        }

        pos = this.target.getPosition();

        if (up_tg >= up) {
            this.target.setPosition(new Vec3(pos.x, up + target.height * sc / 2, pos.z));
            // console.log("下边缘");
        }
    }

节点的绑定
文字数组随便新建三个label绑定上就可以,主要为了更方便直观地看目标节点的具体变化
在这里插入图片描述

双指缩放实现思路

如何判断手指是在做缩小动作还是放大动作?

只需要知道每次两指接触屏幕时,两指触点连线的长度即可。就是图中红线画的部分长度
只要知道第一次接触屏幕的长度,就可以了,用第二次接触时长度和上一次也就是第一次进行大小比较,第二次比第一次大就是在做放大动作,反之就是缩小。

举个例子理解,两手指刚接触屏幕时红线长度是10,手指移动一段距离后长度变成了20,因为20大于10,所以判断两手指正在向外扩张,在做放大动作。手指又移动了一段距离长度变成了15,判断为缩小,15大于10为什么还判断为缩小呢,第一次是10,第二次是20,第三次是15,第三次需要和上一次的长度20比较,而不是和第一次比较,因为15小于20,所以手指在向内收缩,做缩小的动作
在这里插入图片描述
length属性就是上一次缩放时两指触点连线的长度
在这里插入图片描述
来看看代码里面是怎么实现的,先获取动态触点列表,判断触点数量,如果有两个以上触点就计算出两触点连线长度,再判断是不是第一次触碰屏幕,如果是第一次就把连线长度赋值给length属性
在这里插入图片描述
如果不是第一次触碰屏幕就判断手指的动作,用本次长度和上次长度比大小,最后用本次长度减去上次长度求出手指移动的距离,处理后对目标节点进行缩放

还要限制目标节点缩放的范围,缩到多小就不能缩放了
在这里插入图片描述
判断完手指动作一定要更新上次触碰时两触点连线长度,不然下一次缩放时的判断就不对了
在这里插入图片描述
触摸结束把length设为null,下一次触碰时重新初始化
在这里插入图片描述
还需要注意一个问题,双指放大的时候目标节点的大小不断的在变化,放大之后显示的部分就不是之前看的部分中心所放大后的样子了,就像下面这样
请添加图片描述
我通过一个很巧妙的办法解决了这个问题,下图就是解决后的效果
请添加图片描述
需要用到pos属性,pos属性是上次缩放时目标节点的位置,这个位置是目标节点的位置除以了倍数得到的结果
在这里插入图片描述
手指缩放时进行判断,和length的处理办法有点像
如果是第一次缩放就初始化设置pos
如果不是第一次缩放就把目标节点的位置设为上次目标节点的位置乘现在的缩放倍数
在这里插入图片描述
同样在结束触摸的时候设为null,下次双指缩放再初始化
在这里插入图片描述

源码:https://gitee.com/propertygame/cocos-creator3.x-demos/tree/master/HandsScaling
技术交流Q群:1130122408
更多内容请关注微信公众号

请添加图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt Creator是一个集成开发环境(Integrated Development Environment,IDE),用于开发Qt应用程序。CPU和内存是计算机硬件的两个重要组成部分。 CPU(中央处理器)是计算机的核心部件,可以执行指令、运算和控制计算机的工作。在Qt Creator中,CPU的重要作用是执行程序代码,包括编译和调试应用程序。高性能的CPU可以提高Qt Creator的编译速度和应用程序的运行速度。因此,选择一款高性能的CPU可以提高开发效率和程序的执行效果。 内存是计算机存储数据的部分,用于临时存储程序运行时所需的数据和指令。在Qt Creator中,内存的大小会影响编译和运行程序的能力。较大的内存可以提供更多的存储空间,从而支持更复杂的应用程序开发。此外,较大的内存还可以减少由于内存不足而引起的程序崩溃或运行缓慢的问题。 综上所述,对于Qt Creator的使用,CPU和内存都是重要的因素。选择一款高性能的CPU可以提高开发速度和程序运行效果,而较大的内存可以支持更复杂的应用程序开发,并减少运行过程中的问题。因此,在购买计算机时,可以考虑选择高性能的CPU和较大的内存来支持Qt Creator的开发和编译工作。 ### 回答2: Qt Creator 是一个集成开发环境,用于开发基于 Qt 框架的应用程序。虽然 Qt Creator 本身并不会占用很多 CPU 和内存资源,但在使用 Qt Creator 时,可能会运行一些中大型的项目,并且使用一些调试和分析工具,这可能会导致 CPU 和内存的使用增加。 首先,Qt Creator 使用 CPU 来运行各种任务,如编译代码、执行调试器、运行应用程序等。这些任务可能会占用一定的 CPU 资源,特别是在项目规模较大时。此外,Qt Creator 还可以执行静态代码分析、版本控制等操作,这些都需要一定的计算资源来完成。 其次,Qt Creator 在开发过程中会加载和处理大量的代码文件、资源文件和图形化界面等。这些操作会占用一定的内存资源。特别是在打开大型项目或者使用一些内存密集型工具时,内存的使用会更加明显。 然而,Qt Creator 也可以通过一些优化措施来减少 CPU 和内存的占用。例如,可以在编译时使用优化选项来减少生成的可执行文件的大小和运行时的资源占用。同时,关闭不需要的插件和工具,以及优化代码结构和算法,都可以减少资源的占用。 总的来说,Qt Creator 在正常使用时,会使用一定的 CPU 和内存资源。但通过合理的优化和配置,可以降低资源的占用,提高开发效率。 ### 回答3: Qt Creator 是一种集成开发环境,用于开发基于 Qt 框架的应用程序。CPU 和内存是计算机的两个重要组成部分。 首先,谈到 CPU(中央处理器),它是计算机的核心部件之一。CPU 负责执行程序指令,处理数据并控制其他硬件设备。在 Qt Creator 中,CPU 的性能直接影响了编译和调试应用程序的速度。如果 CPU 性能较低,那么编译大型项目可能会较为缓慢,影响开发效率。因此,在选择计算机硬件时,建议选择一款具有较高 CPU 频率、多核心的处理器,以提升 Qt Creator 的性能。 其次,内存是计算机存储数据的关键。在 Qt Creator 中,内存的大小直接决定了能否同时打开大量的源文件和依赖库,并且影响了应用程序在编译和调试过程中的运行效率。如果内存不足,系统可能会频繁地进行内存交换,导致编译速度变慢。因此,建议选择一台内存较大的计算机来进行 Qt Creator 的开发,特别是对于较大型项目的开发。 此外,Qt Creator 本身也具有一些优化选项,以提高在不同硬件配置下的性能。通过合理配置编译器、调试器和构建设置,可以将 CPU 和内存的利用率最大化。 综上所述,CPU 和内存是 Qt Creator 中重要的考虑因素。选择一台具有较高 CPU 频率和多核心的处理器,以及配置足够大的内存,可以改善 Qt Creator 的性能,提高开发效率。同时,合理进行软件优化也是必要的,以确保在不同硬件配置下的良好运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值