Unity用鼠标拖拽UI,UI跟随鼠标移动

news2024/11/24 16:23:45

Unity用鼠标拖拽UI,UI跟随鼠标移动

  • 效果
  • 一、原理
  • 二、源码
  • 总结
  • 💢💢版权声明


效果

先上效果
请添加图片描述


一、原理

继承几个拖拽的接口 IBeginDragHandler, IDragHandler,IEndDragHandler
计算下偏移量,转换下坐标系
限制下可拖拽的范围,我设置的是canvas的大小

二、源码

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.EventSystems;

namespace HHQ
{
    /// <summary>
    /// 拖拽ui(限制拖拽范围)
    /// </summary>
    public class LimitUIDrag : MonoBehaviour, IBeginDragHandler, IDragHandler,IEndDragHandler
    {
        /// <summary>
        /// 限制的区域
        /// </summary>
        private RectTransform limitContainer;

        private Canvas canvas;

        private  RectTransform rt;

        // 位置偏移量
        Vector3 offset = Vector3.zero;

        // 最小、最大X、Y坐标
        float minX, maxX, minY, maxY;

        void Start()
        {
            rt = GetComponent<RectTransform>();
            canvas = GetComponentInParent<Canvas>();
            limitContainer = canvas.GetComponent<RectTransform>();
        }

        /// <summary>
        /// 开始拖拽
        /// </summary>
        /// <param name="eventData"></param>
        public void OnBeginDrag(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left)
                return;
            if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, eventData.position, eventData.enterEventCamera, out Vector3 globalMousePos))
            {
                // 计算偏移量
                offset = rt.position - globalMousePos;
                // 设置拖拽范围
                SetDragRange();
                //EventDispatcher.GameEvent.DispatchEvent(101);
            }
        }

        /// <summary>
        /// 拖拽中
        /// </summary>
        /// <param name="eventData"></param>
        public void OnDrag(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left)
                return;
            // 将屏幕空间上的点转换为位于给定RectTransform平面上的世界空间中的位置
            if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, eventData.position, eventData.pressEventCamera, out Vector3 globalMousePos))
            {
                rt.position = DragRangeLimit(globalMousePos + offset);
            }
        }
        /// <summary>
        /// 拖拽结束
        /// </summary>
        /// <param name="eventData"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnEndDrag(PointerEventData eventData)
        {
            //EventDispatcher.GameEvent.DispatchEvent(103);
        }

        // 设置最大、最小坐标
        void SetDragRange()
        {
            // 最小x坐标 = 容器当前x坐标 - 容器轴心距离左边界的距离 + UI轴心距离左边界的距离
            minX = limitContainer.position.x
                   - limitContainer.pivot.x * limitContainer.rect.width * canvas.scaleFactor
                   + rt.rect.width * canvas.scaleFactor * rt.pivot.x;
            // 最大x坐标 = 容器当前x坐标 + 容器轴心距离右边界的距离 - UI轴心距离右边界的距离
            maxX = limitContainer.position.x
                   + (1 - limitContainer.pivot.x) * limitContainer.rect.width * canvas.scaleFactor
                   - rt.rect.width * canvas.scaleFactor * (1 - rt.pivot.x);

            // 最小y坐标 = 容器当前y坐标 - 容器轴心距离底边的距离 + UI轴心距离底边的距离
            minY = limitContainer.position.y
                   - limitContainer.pivot.y * limitContainer.rect.height * canvas.scaleFactor
                   + rt.rect.height * canvas.scaleFactor * rt.pivot.y;

            // 最大y坐标 = 容器当前x坐标 + 容器轴心距离顶边的距离 - UI轴心距离顶边的距离
            maxY = limitContainer.position.y
                   + (1 - limitContainer.pivot.y) * limitContainer.rect.height * canvas.scaleFactor
                   - rt.rect.height * canvas.scaleFactor * (1 - rt.pivot.y);
        }

        // 限制坐标范围
        Vector3 DragRangeLimit(Vector3 pos)
        {
            pos.x = Mathf.Clamp(pos.x, minX, maxX);
            pos.y = Mathf.Clamp(pos.y, minY, maxY);
            return pos;
        }

       
    }
}

总结

欢迎大佬多多来给萌新指正,欢迎大家来共同探讨。
如果各位看官觉得文章有点点帮助,跪求各位给点个“一键三连”,谢啦~

声明:本博文章若非特殊注明皆为原创原文链接
https://blog.csdn.net/Wrinkle2017/article/details/130885091
————————————————————————————————

💢💢版权声明

版权声明:本博客为非营利性个人原创
所刊登的所有作品的著作权均为本人所拥有
本人保留所有法定权利,违者必究!
对于需要复制、转载、链接和传播博客文章或内容的
请及时和本博主进行联系
对于经本博主明确授权和许可使用文章及内容的
使用时请注明文章或内容出处并注明网址
转载请附上原文出处链接及本声明

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/571638.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tensorflow2基础代码实战系列之时间序列预测任务

深度学习框架Tensorflow2系列 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark …

实时时钟 RTC

概述 实时时钟(RTC) 模块可长时间维持精确计时&#xff0c;为系统提供实时时钟和日历。该模块功耗极低&#xff0c;最大程度延长电池寿命。 RTC的主要特点&#xff1a; ⚫ BCD 时间 格式 &#xff0c;完整万年历 ⚫ 支持数字调校&#xff0c; 最高 精度可达 0. 06 ppm ⚫ 可输出…

作为996社畜,如何自学Python?一文讲清楚

作为996社畜&#xff0c;应该如何自学Python&#xff1f;今天就给大家分享一下&#xff0c;工作之余&#xff0c;应该如何学习Python&#xff1f; 1. 明确目标 对于零基础的学员而言&#xff0c;要明确你学习Python仅仅是为了满足好奇心&#xff1f;还是有工作需要&#xff0c…

如何使用ArcGIS制作气温空间分布图

本文使用ArcMap10.2&#xff0c;以湖北省为例&#xff0c;通过空间插值&#xff0c;制作湖北省1981-2010年20年平均气温空间分布图 树谷资料库资源大全 1 数据准备 可在中国气象数据网下载湖北省1981-2010共20年的各区站累年平均气温数据和各区站经纬度数据。打开为txt格式 在…

【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)

【学习难度&#xff1a;★★★★☆&#xff0c;使用频率&#xff1a;★★★★★】 3.1. 模式动机 在工厂方法模式中具体工厂负责生产具体的产品&#xff0c;每一个具体工厂对应一种具体产品&#xff0c;工厂方法也具有唯一性&#xff0c;一般情况下&#xff0c;一个具体工厂中…

【计算机网络】网络基础(一)

首先声明&#xff1a;这是开发中用到的网络的知识点&#xff0c;侧重点在于编程实践&#xff0c;不重视概念。网络基础不在于细节&#xff0c;在于构建宏观的结构。后面重点在于网络套接字编程&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 目录 1.背景知识 …

经典文献阅读之--ERASOR(栅格占用过滤动态障碍物)

0. 简介 之前作者在《激光雷达动态障碍物滤除-调研与展望》以及《3D帧间匹配-----剔除动态障碍物》中提到了如何通过各种方法来完成动态障碍物的滤波。而本文也将围绕着如何完成动态障碍物滤波来展开&#xff0c;来介绍《ERASOR: Egocentric Ratio of Pseudo Occupancy-based …

CentOS系统如何开展爬虫工作

CentOS 系统可以用于进行爬虫工作。实际上&#xff0c;很多大型网站和在线服务都运行在 Linux 系统下&#xff0c;包括 CentOS、Ubuntu、Debian 等&#xff0c;因此 CentOS 系统也常用于进行爬虫工作。 在CentOS系统上开展爬虫工作&#xff0c;可以按照以下步骤进行&#xff1a…

CESSCN安全设计与集成一级-中国通信企业协会通信网络安全服务能力评定证书

通信网络安全设计与集成服务能力评定是依据《通信网络安全防护管理办法》、《电信网与互联网第三方安全服务评定准则》YD/T2669-2013、以及《通信网络安全服务能力评定管理办法》的具体要求&#xff0c;对通信网络安全服务单位的技术能力、服务能力、质量保证能力、人员构成与素…

智能路由器开发之OpenWrt简介

智能路由器开发之OpenWrt简介 1. 引言 1.1 智能路由器的重要性和应用场景 智能路由器作为网络通信的核心设备&#xff0c;具有重要的地位和广泛的应用场景。传统的路由器主要提供基本的网络连接功能&#xff0c;但随着智能家居、物联网和大数据应用的快速发展&#xff0c;对于…

池州控股集团财务共享项目启动啦!

近日&#xff0c;由用友网络承建的池州市投资控股集团有限公司财务共享项目启动会成功举办&#xff0c;也标志着池州控股集团财务共享项目正式启动&#xff01;池州控股集团总经理刘俊、用友国资事业部总经理汪发清及其他相关专家和项目组主要成员参加了此次启动会。 池州投控集…

100种思维模型之全局观思维模型-67

全局观思维模型&#xff0c;一个教我们由点到线&#xff0c;由线到面&#xff0c;再由面到体&#xff0c;不断的放大格局去思考问题的思维模型。 01、何谓全局观思维模型 一、全局观思维 什么叫全局观&#xff1f; 世界上的所有东西&#xff0c;都是被规律作用者的&#xff0c…

Linux网络基础-5

在上一篇博客中我们对网络层的典型协议--IP进行了介绍&#xff0c;那么本篇博客作为网络方面的最后一片博客&#xff0c;我们对网络中最后内容--链路层协议进行讲解。 目录 1.链路层协议 1.1MAC地址 1.1.1类型 1.1.2作用 1.2以太网协议 1.2.1协议格式 1.2.2ARP协议 1.…

现场直击 | 沈阳新技术交流会,实景三维再“出圈”

5月19日&#xff0c;由中国测绘学会、中国地理信息产业协会指导&#xff0c;辽宁省测绘地理信息学会、辽宁省土地学会地理信息专业委员会主办&#xff0c;武汉大势智慧科技有限公司、沈阳市勘察测绘研究院有限公司承办的“全自主、全流程、全覆盖”2023实景三维新技术交流会沈阳…

QT桌面项目(日历程序)

文章目录 前言一、QCalendarWidget介绍二、日历代码实现总结 前言 本篇文章继续为大家讲解QT桌面项目&#xff0c;那么这篇文章我们将实现一个日历程序。在QT中要想实现一个简单的日历程序是非常简单的&#xff0c;使用QT中自带的QCalendarWidget类即可实现。 一、QCalendarW…

LAMP的部署(天光渐暗,暮色里遗漏了一丝蓝,星辰便从中亮起。)

一、LAMP架构概述 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词&#xff0c;具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP&#…

阻抗板是否高可靠,华秋有话说

随着高频高速电子产品的快速发展&#xff0c;信号传输过程更容易出现反射、串扰等信号完整性问题&#xff0c;且频率越高、传输速率越快&#xff0c;信号损耗越严重&#xff0c;如何降低信号在传输过程中的损耗、保证信号完整性是高频高速PCB发展中的巨大挑战。 在高速PCB设计…

USB主机枚举设备

https://space.bilibili.com/489340606/channel/collectiondetail?sid896957 以下图片来自于沁恒微电子蔡亮工程师的讲课&#xff0c;对USB开发入门很有好处。 1. USB设备的组成结构 一个设备可以有多个配置&#xff0c;但同一时刻只能有一个生效。一个配置可以有多个接口&a…

Linux——进程概念详解

目录 一.什么是进程&#xff1f; 2.PCB的含义&#xff0c;为什么会存在PCB&#xff1f; 整体解析操作系统对进程的管理方式&#xff1a; 二.对比Windows系统&#xff1a; 三.Linux——进程 学习一个新指令&#xff1a;ps ajx 四.接下来学习几个进程的系统调用函数&#xff1…

版图设计IC617 virtuoso工具使用,创建一个库

库是用于创建自己的芯片的&#xff0c;一个库可以看成一个芯片&#xff0c;一个芯片又包含各种元器件。cell就是用于定义具体的元器件的。元器件包含版图&#xff0c;原理图&#xff0c;逻辑符号&#xff0c;等各种视图。 一 创建库过程 1.1 库的创建 1. 在Library Manager下…