NGUI的双点触摸缩放UI(模拟Camera变焦)

2023-10-21 18:50

本文主要是介绍NGUI的双点触摸缩放UI(模拟Camera变焦),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  在很多的Unity游戏开发中,会使用NGUI来做界面的开发。现在很多游戏的界面上会有小地图,当小地图的内容比较多,就需要能缩放,放大能看具体信息,缩小能看大概内容。但由于这地图是用NGUI做的,不是场景的东西,无法使用Camera进行变焦来达到缩放的效果。
  要实现这个功能,我们要解决两个问题,一如何模拟Camera的变焦缩放,二是如何实现双指操作,在这里,我分两个部分来说明。

一、模拟Camera变焦

  我们先来看看Camera变焦缩放的效果是怎么样的。

     

  可以看到上面的左右两图,这里使用的是正交投影,当设置Camera的size(orthographicSize)时,实际上是控制了显示区域的大小,当size变小时,能看到的东西是变少了,但由于屏幕的尺寸是不变的,所以我们看到图片的左下角预览,场景中的UISprite变大了。相反,当size变大时,能看到的东西变多了,而由于屏幕尺寸不变,预览中的UISprite变小。所以,我们要在UI上模拟这种效果,其实改变UI的localSize就可以了。
  但是,设置Camera的size时,显示区域的缩放,是改屏幕中心点来缩放的。可以看到上面两张图,Camera的size变小时,预览中的UISprite变大了,但是图片中的红点,还是对齐着屏幕中心点。要达到这种效果,其实不用去在意UI的锚点,简单的方法的改变UI的localSize后,再对UI做偏移操作,使图片红点再次对齐屏幕中心点。步骤如下:
  1.计算出当前UI的实际显示size1(即当前localSize乘以UI原size)
  2.计算出屏幕中心点相对于UI中心点的坐标pos1
  3.计算出pos1与显示size1的比例ratio
  4.缩放
  5.计算出缩放后新的UI显示size2,乘以ratio即为相对于UI中心点的pos2
  6.对UI做偏移(pos1-pos2)
  以下为实现的核心代码:

    void CaculateScale(float delta){Vector3 scale = mTrans.localScale;Vector3 position = mTrans.position;radio.x = -position.x / curSize.x;radio.y = -position.y / curSize.y;///scale.x += delta;scale.y += delta;if (scale.x > maxScale){scale.x = maxScale;scale.y = maxScale;}else if (scale.x < minScale){scale.x = minScale;scale.y = minScale;}//保持是屏幕中心点的缩放Vector2 size = new Vector2(widget.width * scale.x, widget.height * scale.y);position.x =  -size.x * radio.x;position.y =  -size.y * radio.y;curSize = size;mTrans.position = position;///mTrans.localScale = scale;CaculatePosition();}

二、实现双点触摸

NGUI在3.6版本后,陆续增加了多点触摸的实现,在UICamera的注释中,就有多触点的说明,如下:

/// * OnHover (isOver) is sent when the mouse hovers over a collider or moves away.
/// * OnPress (isDown) is sent when a mouse button gets pressed on the collider.
/// * OnSelect (selected) is sent when a mouse button is first pressed on an object. Repeated presses won't result in an OnSelect(true).
/// * OnClick () is sent when a mouse is pressed and released on the same object.
///   UICamera.currentTouchID tells you which button was clicked.
/// * OnDoubleClick () is sent when the click happens twice within a fourth of a second.
///   UICamera.currentTouchID tells you which button was clicked.

从注释我们可以知道UICamera.currentTouchID,可以获取到当前屏幕操作事件函数是哪个TouchID触发的,这个TouchID,在手机上时,就是手指的触摸ID即FingerID,具体的描述可以参考这里。现在我们可以用UICamera.currentTouchID来区分是哪个手指来触发UICamera事件函数的。

要实现双点的触摸操作,那就要用到UICamera的OnPress与OnDrag事件函数,OnPress用来计数多少手指按下,OnDrag来计算两点之间的滑动距离。在这里,要注意下两点间距离的计算,我们可以用UICamera.lastTouchPosition来获取当前手指触摸点的屏幕坐标,但这个坐标不能直接使用,要转换到UICamera的世界坐标,可以用ScreenToWorldPoint()来转换。这样,我们的思路就很清晰了,以下为实现的核心代码:

    void OnPress(bool isPressed){if (isPressed){int touchID = UICamera.currentTouchID;if (touchID < 0){touchID = 0;}if (touchID < 2){isPress[touchID] = true;posArray[touchID] = UICamera.mainCamera.ScreenToWorldPoint(UICamera.lastTouchPosition);preDis = Vector2.Distance(posArray[0], posArray[1]);}}else{if (UICamera.activeTouches.Count < 2){isPress[0] = false;isPress[1] = false;return;}}}void OnDrag(Vector2 delta){int touchID = UICamera.currentTouchID;if (touchID < 0){touchID = 0;}if (touchID >= posArray.Length){return;}posArray[touchID] = UICamera.mainCamera.ScreenToWorldPoint(UICamera.lastTouchPosition);if (isPress[0] && isPress[1]){// 两点之间的距离。float curDis = Vector2.Distance(posArray[0], posArray[1]);OnScale(curDis - preDis);preDis = curDis;}}

至此,我们就可以实现UI的双点触摸缩放了,当然,我们还能添加更多点的触摸操作。



这篇关于NGUI的双点触摸缩放UI(模拟Camera变焦)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/256278

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

【算法专场】模拟(下)

目录 前言 38. 外观数列 算法分析 算法思路 算法代码 1419. 数青蛙 算法分析 算法思路 算法代码  2671. 频率跟踪器 算法分析 算法思路 算法代码 前言 在前面我们已经讲解了什么是模拟算法,这篇主要是讲解在leetcode上遇到的一些模拟题目~ 38. 外观数列 算法分析 这道题其实就是要将连续且相同的字符替换成字符重复的次数+

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

Golang GUI入门——andlabs ui

官方不提供gui标准库,只好寻求第三方库。 https://github.com/google/gxui 这个gui库是谷歌内部人员提供的,并不是谷歌官方出品,现在停止维护,只好作罢。 第三方gui库 找了好多,也比较了好多,最终决定使用的是还是 https://github.com/andlabs/ui 相信golang gui还会发展的更好,期待更优秀的gui库 由于andlabs