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

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;

        }
    }
}



总结

以上就是本次功能设计实现的全部内容了,满足图片能够在单方向上进行拖动缩放,制作不易,多多支持。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杰尼杰尼丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值