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
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中,UGUI的EventTrigger是一个非常有用的组件,它可以用于实现UI拖拽和位置交换的功能。 首先,需要在要实现拖拽和位置交换的UI元素上添加EventTrigger组件。可以通过代码或者在Inspector面板中进行操作。然后,需要添加相应的事件触发器,例如拖拽开始、拖拽移动、拖拽结束等事件。 接下来,需要编写拖拽的逻辑代码。可以使用Unity提供的接口来处理拖拽事件,例如OnBeginDrag、OnDrag和OnEndDrag。在OnBeginDrag事件中,可以获取到拖拽起始位置,并将拖拽中的UI元素设置为可拖拽状态。在OnDrag事件中,可以实时获取到拖拽的位置,并将UI元素跟随鼠标或手指移动。在OnEndDrag事件中,可以获取到拖拽结束位置,并将UI元素设置回初始位置。 要实现位置交换功能,可以在UI元素上添加Collider组件,并根据拖拽的起始和结束位置来计算是否需要进行位置交换。可以使用RaycastHit来判断拖拽位置是否与其他UI元素重合,并记录下交换元素的信息。然后,根据交换元素的信息,可以将两个UI元素的位置进行互换。 最后,为了保证拖拽和位置交换功能的流畅性和用户体验,还可以添加一些动画效果和交互反馈。例如,在拖拽开始时可以添加一些拖拽阴影效果,使拖拽UI元素看起来更加立体和真实。在位置交换时,可以添加一些过渡动画,使UI元素的位置变换更加平滑和自然。 总之,利用Unity中UGUI的EventTrigger组件,结合适当的逻辑代码和交互反馈,可以很方便地实现UI拖拽和位置交换功能。这种功能可以在游戏开发中广泛应用,例如拼图游戏、物品交换系统等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值