UGUI 之窗口拖拽,以及焦点界面

注释很详细,不多做介绍了!

using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.EventSystems;

/// <summary>
/// UGUI 之 界面拖动 以及 焦点界面
/// </summary>
public class UI_DragObject : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IPointerDownHandler, IDragHandler
{
    private RectTransform m_Target;  //获取拖拽对象,
    private RectTransform m_CanvasRectTransform; //父对象,画布 canvas, canvas的大小刚好就是整个屏幕.

    private Vector2 m_MouseStartPosition = Vector2.zero;  //鼠标起点位置
    private Vector2 m_TargetStartPosition = Vector2.zero;  //面板起点位置

    private bool m_Dragging = false;                //拖拽状态的判断
 
    private static int siblingIndex;   //UI显示层级

    void Awake()
    {
        //先获取对象
        m_Target = transform.parent as RectTransform;
        m_CanvasRectTransform = m_Target.parent as RectTransform;
        siblingIndex = m_Target.transform.GetSiblingIndex(); //获取层级
    }

    /// <summary>
    /// 保证当前UI 要显示在其他UI上面
    /// </summary>
    /// <param name="data"></param>
    public void OnPointerDown(PointerEventData data) 
    {
        siblingIndex++;
        m_Target.transform.SetSiblingIndex(siblingIndex);
    }

    /// <summary>
    /// 拖拽开始
    /// </summary>
    ///     ScreenPointToLocalPointInRectangle(RectTransform rect, Vector2 screenPoint, Camera cam, out Vector2 localPoint); 方法
    ///     屏幕空间点转换为矩形变换内部的本地位置,该点在它的矩形平面上。 
    /// <param name="data"></param>
    public void OnBeginDrag(PointerEventData data)
    {
        //判空
        if(m_Target == null)  
        {
            Debug.Log("m_Target is null");
            return;
        }
        //鼠标起点坐标
        RectTransformUtility.ScreenPointToLocalPointInRectangle(this.m_CanvasRectTransform, data.position, data.pressEventCamera, out this.m_MouseStartPosition);
        //面板起点坐标 
        this.m_TargetStartPosition = this.m_Target.anchoredPosition;    //锚点坐标 
        //拖拽中
        this.m_Dragging = true; 
    }

    /// <summary>
    /// 拖拽结束
    /// </summary>
    /// <param name="data"></param>
    public void OnEndDrag(PointerEventData data)
    {
        //拖拽结束
        this.m_Dragging = false;       
    }

    /// <summary>
    /// 拖拽中
    /// </summary>
    /// <param name="data"></param>
    public void OnDrag(PointerEventData data)
    {
        if (m_Target == null || this.m_CanvasRectTransform == null)
        {
            Debug.Log(m_Target);
            Debug.Log(m_CanvasRectTransform);
            return;
        }
        //当前鼠标坐标转换
        Vector2 mousePos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(this.m_CanvasRectTransform, data.position, data.pressEventCamera, out mousePos);

        //是否在拖拽中
        if (this.m_Dragging) 
        {
            mousePos = this.ClampToCanvas(mousePos); //限制鼠标不得在画布外
        }
         // 移动位置 =  起点 + 鼠标当前位置 - 鼠标起点位置
        Vector2 newPosition = this.m_TargetStartPosition + (mousePos - this.m_MouseStartPosition);

        // 位置更改
        this.m_Target.anchoredPosition = newPosition;
     
    }
    
    /// <summary>
    /// 限制在画布内
    /// </summary>
    /// 这里使用了  GetLocalCorners( Vector3[] for conersArray)   方法   获取当前物体的 四个顶点 在 父物体坐标系 的坐标  顺序 从左下 -> 右下
    /// 同理:       GetWorldCorners( Vector3[] for conersArray)   方法   获取当前物体的  四个顶点 在 世界坐标系 的坐标  顺序 从左下 -> 右下
    /// <param name="position"></param>
    /// <returns></returns>
    protected Vector2 ClampToCanvas(Vector2 position)
    {
        if (this.m_CanvasRectTransform != null)
        {
            //先创建数组存放四个顶点坐标 
            Vector3[] corners = new Vector3[4];

            //获取顶点坐标
            this.m_CanvasRectTransform.GetLocalCorners(corners);

            //限制其坐标 X,Y  在 min.X / Y  -  max.X / Y 之间 
            float clampedX = Mathf.Clamp(position.x, corners[0].x, corners[2].x);  // Clamp(Value,min,max)  if (value > max)  return max ; 反之
            float clampedY = Mathf.Clamp(position.y, corners[3].y, corners[1].y);

            //返回
            return new Vector2(clampedX, clampedY);  
        }
        return position;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值