Unity UGUI 效果 之 鼠标拖拽UI实现放大缩小,实时调整UI大小
前言
Unity UGUI 效果 之 鼠标拖拽UI实现放大缩小,实时调整UI大小(上)
上一篇我们设置的UI的拖拽功能,这一篇我们通过对UI的anchoredPosition和sizeDelta的设置实现单方向的放大缩小功能。
一、实现原理
1、默认设置
2、改变时状态
当改变图片的大小时,Unity会对图片进行整体的缩放,如果要在视觉上保持单方向变化,需在改变图片的宽高时同时改变位置坐标,满足单方向缩放的效果。
当宽度从600—》800时变化状态
二、实现代码
1、图片位置大小控制代码
/*
*FileName: KeepFixed.cs
*Author: SSW
*Date: 2024/08/02 08:52:07
*UnityVersion: 2020.3.40f1
*Description:
*/
using SSWTools;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KeepFixed : MonoBehaviour
{
[SerializeField]
private UI_Edge uI_Edge;
RectTransform panelRectTransform;
/// <summary>
/// 位置
/// </summary>
private Vector2 originalLocalPointerPosition;
/// <summary>
/// 大小
/// </summary>
private Vector2 originalSizeDelta;
// Start is called before the first frame update
void Start()
{
panelRectTransform=this.GetComponent<RectTransform>();
originalLocalPointerPosition=panelRectTransform.anchoredPosition;
originalSizeDelta = panelRectTransform.sizeDelta;
}
/// <summary>
/// 通过传入缩放的方向和大小,动态改变图片的位置和大小
/// </summary>
/// <param name="pEdge"></param>
/// <param name="v2"></param>
public void SetPanelFixed(UI_Edge pEdge,Vector2 v2)
{
uI_Edge=pEdge;
switch (pEdge)
{
case UI_Edge.None:
break;
case UI_Edge.Top:
originalLocalPointerPosition = panelRectTransform.anchoredPosition;
originalSizeDelta = panelRectTransform.sizeDelta;
if (v2.y> originalSizeDelta.y)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.y += ((v2.y - originalSizeDelta.y) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else if (v2.y< originalSizeDelta.y)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.y -= ((originalSizeDelta.y - v2.y) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else
{
// Debug.Log("达到 最大值");
}
break;
case UI_Edge.Down:
originalLocalPointerPosition = panelRectTransform.anchoredPosition;
originalSizeDelta = panelRectTransform.sizeDelta;
if (v2.y > originalSizeDelta.y)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.y -= ((v2.y - originalSizeDelta.y) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else if (v2.y < originalSizeDelta.y)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.y += ((originalSizeDelta.y - v2.y) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else
{
// Debug.Log("达到 最大值");
}
break;
case UI_Edge.Left:
originalLocalPointerPosition = panelRectTransform.anchoredPosition;
originalSizeDelta = panelRectTransform.sizeDelta;
if ( v2.x> originalSizeDelta.x)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.x -= ((v2.x - originalSizeDelta.x) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else if (v2.x < originalSizeDelta.x)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.x += ((originalSizeDelta.x-v2.x) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else
{
// Debug.Log("达到 最大值");
}
break;
case UI_Edge.Right:
originalLocalPointerPosition = panelRectTransform.anchoredPosition;
originalSizeDelta = panelRectTransform.sizeDelta;
if (v2.x > originalSizeDelta.x)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.x += ((v2.x - originalSizeDelta.x) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else if (v2.x < originalSizeDelta.x)
{
panelRectTransform.sizeDelta = v2;
originalLocalPointerPosition.x -= ((originalSizeDelta.x - v2.x) / 2);
panelRectTransform.anchoredPosition = originalLocalPointerPosition;
}
else
{
//Debug.Log("达到 最大值");
}
break;
default:
break;
}
}
// Update is called once per frame
void Update()
{
}
}
2、添加代码关联
对文章(一)中的代码进行修改
在Ondrag()方法中添加
//下面采取了固定某个边的方式,单边改变宽和高
KeepFixed.SetPanelFixed(ui_edge, new Vector2(Mathf.Clamp(x, minSize.x, maxSize.x), Mathf.Clamp(y, minSize.y, maxSize.y)));
类中添加
[RequireComponent(typeof(KeepFixed))]
3、完整代码
/*
*FileName: ResizePanel2.cs
*Author: SSW
*Date: 2024/08/01 10:34:58
*UnityVersion: 2020.3.40f1
*Description:
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
namespace SSWTools
{
public enum UI_Edge
{
None,
Top,
Down,
Left,
Right,
TopLeft,
TopRight,
BottomLeft,
BottomRight
}
/// <summary>
/// 拖动边缘,调整UI大小
/// 使用说明
/// 1、鼠标移动到UI的边缘,点击鼠标向内或向外拖动,实现调整UI大小
/// 2、这里变化的 UI 的比例,你可以根据需要需改为 UI 宽高
/// </summary>
[RequireComponent(typeof(KeepFixed))]
public class ResizePanel2 : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerEnterHandler, IPointerExitHandler, IPointerUpHandler
{
[Header("检测边距百分比")]
[Range(0f,1f)]
public float MonitorPercent=0.8f;
/// <summary>
/// 画布变化的大小限制值
/// </summary>
[Header("调整的最小值")]
public Vector2 minSize = new Vector2(50, 50);
[Header("调整的最大值")]
public Vector2 maxSize = new Vector2(500, 500);
[Header("边缘图片")]
// 边缘图片
public Transform Right_Image;
public Transform Down_Image;
public Transform Top_Image;
public Transform Left_Image;
// UI RectTransform
private RectTransform panelRectTransform;
// UI原始位置
private Vector2 originalLocalPointerPosition;
// UI原始大小
private Vector2 originalSizeDelta;
/// <summary>
/// 鼠标刚进入时位置
/// </summary>
private Vector2 v2PointEnter;
// 鼠标是否按下
private bool isPointerDown = false;
// 当前操作方向
public UI_Edge ui_edge;
public KeepFixed KeepFixed;
void Awake()
{
KeepFixed = GetComponent<KeepFixed>();
ui_edge = UI_Edge.None;
// 初始化
panelRectTransform = transform.GetComponent<RectTransform>();
// 隐藏边缘图标
SetActiveEdgeImage(false);
}
private void Start()
{
}
/// <summary>
/// 鼠标在UI上按下的事件
/// </summary>
/// <param name="data"></param>
public void OnPointerDown(PointerEventData data)
{
// Debug.Log("OnPointerDown-----------"+ ui_edge.ToString());
if (ui_edge==UI_Edge.None)
{
return;
}
// 鼠标按下
isPointerDown = true;
StopCoroutine("edgeJudge");
}
float x, y;
/// <summary>
/// 拖拽实现Resize
/// </summary>
/// <param name="data"></param>
public void OnDrag(PointerEventData data)
{
if (panelRectTransform == null || ui_edge == UI_Edge.None || !isPointerDown)
return;
switch (ui_edge)
{
case UI_Edge.None:
break;
case UI_Edge.Top:
x = panelRectTransform.sizeDelta.x;
y = panelRectTransform.sizeDelta.y + data.delta.y;
break;
case UI_Edge.Down:
x = panelRectTransform.sizeDelta.x;
y = panelRectTransform.sizeDelta.y - data.delta.y;
break;
case UI_Edge.Left:
x = panelRectTransform.sizeDelta.x - data.delta.x;
y = panelRectTransform.sizeDelta.y;
break;
case UI_Edge.Right:
x = panelRectTransform.sizeDelta.x + data.delta.x;
y = panelRectTransform.sizeDelta.y;
break;
default:
break;
}
//直接进行赋值,这样会整体改变宽和高
// panelRectTransform.sizeDelta = new Vector2(Mathf.Clamp(x, minSize.x, maxSize.x), Mathf.Clamp(y, minSize.y, maxSize.y));
//下面采取了固定某个边的方式,单边改变宽和高
KeepFixed.SetPanelFixed(ui_edge, new Vector2(Mathf.Clamp(x, minSize.x, maxSize.x), Mathf.Clamp(y, minSize.y, maxSize.y)));
}
/// <summary>
/// 鼠标抬起事件
/// </summary>
/// <param name="eventData"></param>
public void OnPointerUp(PointerEventData eventData)
{
// Debug.Log("OnPointerUp-----------");
isPointerDown = false;
ui_edge = UI_Edge.None;
SetActiveEdgeImage(false);
StopCoroutine("edgeJudge");
}
/// <summary>
/// 鼠标进入UI的事件
/// </summary>
/// <param name="eventData"></param>
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("OnPointerEnter-----------");
//Debug.Log(" eventData.position:" + eventData.position);
if (isPointerDown)
{
return;
}
// 开启边缘检测
StartCoroutine("edgeJudge");
}
/// <summary>
/// 鼠标退出UI的事件
/// </summary>
/// <param name="eventData"></param>
public void OnPointerExit(PointerEventData eventData)
{
if (isPointerDown)
{
return;
}
Debug.Log("OnPointerExit-----------");
isPointerDown=false;
StopCoroutine("edgeJudge");
SetActiveEdgeImage(false);
}
/// <summary>
/// 设置边缘画的显隐
/// </summary>
/// <param name="isActive"></param>
private void SetActiveEdgeImage(bool isActive)
{
Right_Image.gameObject.SetActive(isActive);
Down_Image.gameObject.SetActive(isActive);
Left_Image.gameObject.SetActive(isActive);
Top_Image.gameObject.SetActive(isActive);
}
/// <summary>
/// 边缘判断协程
/// </summary>
/// <returns></returns>
IEnumerator edgeJudge()
{
yield return new WaitForEndOfFrame();
while (true)
{
RectTransformUtility.ScreenPointToLocalPointInRectangle(panelRectTransform,
Input.mousePosition, null,
out v2PointEnter);
// Debug.Log("_pos:" + v2PointEnter);
ui_edge = GetCurrentEdge(v2PointEnter);
SetActiveEdgeImage(false);
switch (ui_edge)
{
case UI_Edge.None:
SetActiveEdgeImage(false);
break;
case UI_Edge.Left:
Left_Image.gameObject.SetActive(true);
Left_Image.localPosition = new Vector3(Left_Image.localPosition.x, Mathf.Clamp(v2PointEnter.y, -panelRectTransform.rect.height / 2, panelRectTransform.rect.height / 2),
Left_Image.localPosition.z);
break;
case UI_Edge.Right:
Right_Image.gameObject.SetActive(true);
Right_Image.localPosition = new Vector3(Right_Image.localPosition.x, Mathf.Clamp(v2PointEnter.y, -panelRectTransform.rect.height / 2, panelRectTransform.rect.height / 2),
Right_Image.localPosition.z);
break;
case UI_Edge.Down:
Down_Image.gameObject.SetActive(true);
Down_Image.localPosition = new Vector3(Mathf.Clamp(v2PointEnter.x, -panelRectTransform.rect.width / 2, panelRectTransform.rect.width / 2),
Down_Image.localPosition.y, Down_Image.localPosition.z);
break;
case UI_Edge.Top:
Top_Image.gameObject.SetActive(true);
Top_Image.localPosition = new Vector3(Mathf.Clamp(v2PointEnter.x, -panelRectTransform.rect.width / 2, panelRectTransform.rect.width / 2),
Top_Image.localPosition.y, Top_Image.localPosition.z);
break;
default:
SetActiveEdgeImage(false);
break;
}
yield return new WaitForEndOfFrame();
}
}
/// <summary>
/// 判断鼠标在 Panel 的那个边缘
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
private UI_Edge GetCurrentEdge(Vector2 pos)
{
if (pos.x < 0 && pos.x < -panelRectTransform.sizeDelta.x / 2 * MonitorPercent)
{
return UI_Edge.Left;
}
else if (pos.x > 0 && pos.x > panelRectTransform.sizeDelta.x / 2 * MonitorPercent)
{
return UI_Edge.Right;
}
else
{
if (pos.y < 0 && pos.y < -panelRectTransform.sizeDelta.y / 2 * MonitorPercent)
{
return UI_Edge.Down;
}
else if (pos.y > 0 && pos.y > panelRectTransform.sizeDelta.y / 2 * MonitorPercent)
{
return UI_Edge.Top;
}
}
return UI_Edge.None;
}
private void SetWidthHeight(UI_Edge tuI_Edge,Vector2 wh)
{
Vector2 V2Pos = panelRectTransform.anchoredPosition;
Vector2 V2Size = panelRectTransform.sizeDelta;
}
}
}
总结
以上就是本次功能设计实现的全部内容了,满足图片能够在单方向上进行拖动缩放,制作不易,多多支持。