Unity UGUI 效果 之 鼠标拖拽UI实现放大缩小,实时调整UI大小(上)

Unity UGUI 实现UI拖拽缩放

Unity UGUI 效果 之 鼠标拖拽UI实现放大缩小,实时调整UI大小


前言

项目中想自定义编辑一个图片进行编辑展示,涉及到需要放大缩小的功能,看了一些资料很多都是拖拽的时候整体的放大缩小,所以自己在方法思路上进行改进功能。


一、简单介绍

本节使用 UGUI 通过代码实现鼠标点击拖拽UI实现动态调整图片大小的功能,共上下两篇,方法不唯一,欢迎指正。


二、实现原理

1、OnPointerEnter进入图片时检测鼠标在图片的区域位置;
2、OnPointerDown鼠标按下时,关闭检测并设置为拖拽状态;
3、OnDrag拖拽时,根据鼠标的位置进行图片大小的设置;
4、OnPointerUp鼠标抬起时,关闭拖拽状态;
5、OnPointerExit鼠标离开图片时关闭掉所有的检测以及拖拽判断

通过鼠标进入图片后所处的橙色区域位置判断拖拽的方向
在这里插入图片描述


三、效果预览

在这里插入图片描述

四、实现步骤

1、UI设置

面板基本结构设置
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
对四周拖拽箭头的预设位置以及锚点设置
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


2、代码编辑

1、边缘判断

 /// <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();
     }

 }

2、拖拽改变大小

  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));

  }

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>
    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));

        }


        /// <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;

        }
    }
}



总结

通过以上这些设置已经能够对图片的拖拽方向和拖拽缩放功能有了一个基本的设置,下面我们对拖拽时的整体变化做一些限制,使之能够在单个方向上进行拖动。

五、最新更新

对单方向的缩放控制进行了完善

Unity UGUI 效果 之 鼠标拖拽UI实现放大缩小,实时调整UI大小(下)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰尼杰尼丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值