Unity3D UGUI 使用ScrollRect实现地图拖放及多点缩放

UGUI中ScrollRect本来是用来做水平和垂直的滑动列表的。并且内置了惯性滑动和边界弹性限制。但经过一些设置,完全可以用来做一个可以拖动的地图功能。首先,介绍一下属性的意思。


Content:                   这是ScrollRect显示内容的实际区域。

Horizontal:              是否可以水平滚动

Vertical:                   是否可以垂直滚动

MovementType:     运动到边界的限制类型, 有不限制,弹性,限制三种

Inertia:                  是否有 滑动的惯性

DecelerationRate: 惯性减速率

ScrollSensitivity:     滚动敏感度

ViewPort:                 可是区域的大小

还有2个是水平和垂直的滚动条,做地图的话不需要显示。



如果用来制作地图,基本思路是。让ScroolRect可以水平和垂直滑动,惯性衰减运动和滑动敏感度可以直接使用,边界限制使用Clamped就是边界严格限制。最重要的是,Content设置为地图的真实大小比如 3000 * 30000的组件,而可视区域的大小就是屏幕的大小。这样地图就能够在屏幕区域内容易拖动。


如果还需要给地图增加多点触摸缩放的功能,就需要复写ScrollRect来处理。如下一个完整可以使用的封装:

[csharp]  view plain  copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using UnityEngine.UI;  
  4. using UnityEngine.EventSystems;  
  5.   
  6. namespace Framework  
  7. {  
  8.     public class MyScrollRect : ScrollRect   
  9.     {  
  10.         private int touchNum = 0;  
  11.         public override void OnBeginDrag (PointerEventData eventData)  
  12.         {  
  13.             if(Input.touchCount > 1)   
  14.             {  
  15.                 return;  
  16.             }  
  17.   
  18.             base.OnBeginDrag(eventData);  
  19.         }  
  20.   
  21.         public override void OnDrag (PointerEventData eventData)  
  22.         {  
  23.             if (Input.touchCount > 1)  
  24.             {  
  25.                 touchNum = Input.touchCount;  
  26.                 return;  
  27.             }  
  28.             else if(Input.touchCount == 1 && touchNum > 1)  
  29.             {  
  30.                 touchNum = Input.touchCount;  
  31.                 base.OnBeginDrag(eventData);  
  32.                 return;  
  33.             }  
  34.   
  35.             base.OnDrag(eventData);  
  36.         }  
  37.   
  38.   
  39.   
  40.         private float preX;  
  41.         private float preY;  
  42.   
  43.         void Update()  
  44.         {  
  45.             if (Input.touchCount == 2)  
  46.             {  
  47.                 Touch   t1   = Input.GetTouch(0);  
  48.                 Touch   t2   = Input.GetTouch(1);  
  49.     
  50.                 Vector3 p1   = t1.position;  
  51.                 Vector3 p2   = t2.position;  
  52.   
  53.                 float   newX = Mathf.Abs(p1.x - p2.x);  
  54.                 float   newY = Mathf.Abs(p1.y - p2.y);  
  55.   
  56.                 if (t2.phase == TouchPhase.Began)  
  57.                 {  
  58.                     preX = newX;  
  59.                     preY = newY;  
  60.                 }  
  61.                 else if (t1.phase == TouchPhase.Moved && t2.phase == TouchPhase.Moved)  
  62.                 {     
  63.                     RectTransform rt    = base.content;  
  64.                     float         scale = (newX + newY - preX - preY) / (rt.rect.width * 0.9f) + rt.localScale.x;  
  65.   
  66.                     if (scale > 1 && scale < 3)  
  67.                     {         
  68.                         rt.localScale = new Vector3(scale, scale, 0);  
  69.   
  70.                         float maxX    = base.content.rect.width  * scale / 2 - base.viewport.rect.width  / 2;  
  71.                         float minX    = -maxX;  
  72.   
  73.                         float maxY    = base.content.rect.height * scale / 2 - base.viewport.rect.height / 2;  
  74.                         float minY    = -maxY;  
  75.   
  76.                         Vector3 pos   = rt.position;  
  77.   
  78.                         if (pos.x > maxX)  
  79.                         {  
  80.                             pos.x = maxX;  
  81.                         }  
  82.                         else if (pos.x < minX)  
  83.                         {  
  84.                             pos.x = minX;  
  85.                         }  
  86.   
  87.                         if (pos.y > maxY)  
  88.                         {  
  89.                             pos.y = maxY;  
  90.                         }  
  91.                         else if (pos.y < minY)  
  92.                         {  
  93.                             pos.y = minY;  
  94.                         }  
  95.   
  96.                         rt.position = pos;  
  97.                     }  
  98.                 }  
  99.   
  100.                 preX = newX;  
  101.                 preY = newY;  
  102.             }  
  103.         }  
  104.     }  
  105. }  


思路是,多点触摸我们使用系统的Input来获得数值,在update函数中不断的检测触摸。 然后重写父类的OnBeginDrag和OnDrag,在多点触摸的时候不触发,单点拖动的时候在调用父类的函数。


多点触摸缩放,主要使用两个触摸点的变化量,来给地图内容区域做缩放,并且注意在边界的时候缩放需要同步检测最大最小编辑位置,放置出现地图区域小于屏幕的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值