前言
可以对UGUI 进行拖拽和缩放
一、代码
namespace SZL
{
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// UI操作
/// </summary>
public class LoadDll : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IScrollHandler
{
[Header("是否拖拽")] public bool Drag = true;
[Header("是否聚焦")] public bool Zoom = true;
[Header("是否限制")] public bool Limit = true;
[Header("移动限制区域")] public RectTransform Container;
[Header("最小缩放值"), SerializeField] private float MinScale;
[Header("最大缩放值"), SerializeField] private float MaxScale;
[Header("缩放速度"), SerializeField] private float ZoomSpeed;
public Vector2 DragOffset { get; private set; }
private RectTransform rectTransform;
private float minX, minY, maxX, maxY, scale = 1;
protected override void Awake()
{
base.Awake();
rectTransform = gameObject.GetComponent<RectTransform>();
if (Container == null) Container = transform.parent as RectTransform;
}
public void OnBeginDrag(PointerEventData eventData)
{
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
Container,
Input.mousePosition,
eventData.enterEventCamera,
out var input))
{
DragOffset = (Vector2)(rectTransform.localPosition) - input;
}
if (Limit) SetLimitRect();
}
public void OnDrag(PointerEventData eventData)
{
if (!Drag)
return;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
Container,
Input.mousePosition,
eventData.enterEventCamera,
out var input))
{
Vector3 target = input + DragOffset;
if (Limit)
{
target = ClampPos(target);
}
transform.localPosition = Vector3.Lerp(transform.localPosition, target,
Time.deltaTime * 100);
}
}
public void OnEndDrag(PointerEventData eventData)
{
DragOffset = Vector3.zero;
}
public void OnScroll(PointerEventData eventData)
{
if(!Zoom)
return;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
Container,
Input.mousePosition,
eventData.enterEventCamera,
out Vector2 input))
{
float delX = input.x - transform.localPosition.x;
float delY = input.y - transform.localPosition.y;
float scaleX = delX / rectTransform.rect.width / transform.localScale.x;
float scaleY = delY / rectTransform.rect.height / transform.localScale.y;
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
scale += Time.deltaTime * ZoomSpeed;
scale = Mathf.Min(MaxScale, scale);
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
scale -= Time.deltaTime * ZoomSpeed;
scale = Mathf.Max(MinScale, scale);
}
transform.localScale = Vector3.one * scale;
rectTransform.pivot += new Vector2(scaleX, scaleY);
transform.localPosition += new Vector3(delX, delY, 0);
}
}
/// <summary>
/// 判断移动区域
/// </summary>
private void SetLimitRect()
{
//获取容器边界世界坐标
Vector3[] corner = new Vector3[4];
Container.GetWorldCorners(corner);
//转换容器和目标对象同一坐标系 ----> 限制目标对象的移动范围
var minVector = Container.InverseTransformPoint(corner[0]);
var maxVector = Container.InverseTransformPoint(corner[2]);
//图形超出 视口
if (rectTransform.rect.width * rectTransform.localScale.x >=
Container.rect.width)
{
maxX = minVector.x + rectTransform.rect.width * rectTransform.pivot.x *
rectTransform.localScale.x;
minX = maxVector.x - rectTransform.rect.width * (1 - rectTransform.pivot.x) *
rectTransform.localScale.x;
}
else //图形未超出视口
{
minX = minVector.x + rectTransform.rect.width * rectTransform.pivot.x *
rectTransform.localScale.x;
maxX = maxVector.x - rectTransform.rect.width * (1 - rectTransform.pivot.x) *
rectTransform.localScale.x;
}
if (rectTransform.rect.height * rectTransform.localScale.x >=
Container.rect.height)
{
minY = maxVector.y - rectTransform.rect.height * (1 - rectTransform.pivot.y) *
rectTransform.localScale.y;
;
maxY = minVector.y + rectTransform.rect.height * rectTransform.pivot.y *
rectTransform.localScale.y;
}
else
{
minY = minVector.y + rectTransform.rect.height * rectTransform.pivot.y *
rectTransform.localScale.y;
maxY = maxVector.y - rectTransform.rect.height * (1 - rectTransform.pivot.y) *
rectTransform.localScale.y;
}
}
/// <summary>
/// 矩形约束
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
private Vector3 ClampPos(Vector3 pos)
{
pos.x = Mathf.Clamp(pos.x, minX, maxX);
pos.y = Mathf.Clamp(pos.y, minY, maxY);
return pos;
}
}
}
二、使用步骤
直接挂在需要拖拽的UI物体上。
三、测试结果展示
–