Unity UGUI 拖拽组件

news2025/1/18 18:43:42

效果展示

在这里插入图片描述

使用方式

拖到图片上即可用

父节点会约束它的活动范围哦~
父节点会约束它的活动范围哦~
父节点会约束它的活动范围哦~

在这里插入图片描述

源码


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

/// <summary>
/// UI DragComponent 
/// 
/// Easy ui drag and drop
/// 
/// Easy~~~
/// 
/// @anchor ChenJC
/// @time: 2023/02/28
/// </summary>
public class DragComponent : MonoBehaviour, IBeginDragHandler, IDragHandler, IDropHandler
{
    RectTransform rectTransform, parentRectTrans;
    float minX, minY, maxX, maxY;
    Vector2 offset;

    public delegate void DragHandlerEvent( Vector2 currentPos );
   
    public DragHandlerEvent dragBeginEvent;
    public DragHandlerEvent dragEvent;
    public DragHandlerEvent dropEvent;

    #region Monobehavior Methods


    private void Awake()
    {
        parentRectTrans = transform.parent as RectTransform;
        rectTransform = transform as RectTransform;
    }

    private void Start()
    {
        var parentAnchorX = parentRectTrans.pivot.x * parentRectTrans.rect.width;
        var parentAnchorY = parentRectTrans.pivot.y * parentRectTrans.rect.height;
        minX = rectTransform.rect.width * 0.5f - parentAnchorX;
        minY = rectTransform.rect.height * 0.5f - parentAnchorY;
        maxX = parentRectTrans.rect.width - rectTransform.rect.width * 0.5f - parentAnchorX;
        maxY = parentRectTrans.rect.height - rectTransform.rect.height * 0.5f - parentAnchorY;
    }

    #endregion


    #region Internal Methods

    private Vector2 ConstraintWithinParentNode( Vector2 pos )
    {
        pos.x = Mathf.Clamp( pos.x, minX, maxX );
        pos.y = Mathf.Clamp( pos.y, minY, maxY );
        return pos;
    }
    private bool Convert2local( Vector2 screenPos, out Vector2 localPos, Camera camera )
    {
        return RectTransformUtility.ScreenPointToLocalPointInRectangle( parentRectTrans, screenPos, camera, out localPos );
    }

    #endregion


    #region Drag Handler Methods

    public void OnBeginDrag( PointerEventData eventData )
    {
        Vector2 localPos;
        if ( Convert2local( eventData.position, out localPos, eventData.pressEventCamera ) )
        {
            Vector2 src = rectTransform.localPosition;
            offset = src - localPos;
            dragBeginEvent?.Invoke( src );
        }
    }

    public void OnDrag( PointerEventData eventData )
    {
        Vector2 localPos;
        if ( Convert2local( eventData.position, out localPos, eventData.pressEventCamera ) )
        {
            Vector2 dest = ConstraintWithinParentNode( localPos + offset );
            rectTransform.localPosition = dest;
            dragEvent?.Invoke( dest );
        }
    }


    public void OnDrop( PointerEventData eventData )
    {
        Vector2 localPos;
        if ( Convert2local( eventData.position, out localPos, eventData.pressEventCamera ) )
        {
            Vector2 dest = ConstraintWithinParentNode( localPos + offset );
            rectTransform.localPosition = dest;
            dropEvent?.Invoke( dest );
        }
    }

    #endregion
}

拖拽事件监听

依次 开始拖拽时触发; 拖拽过程中持续触发; 拖拽结束时触发
在这里插入图片描述

原理介绍

在这里插入图片描述

开始拖拽的时候

offset = sub.localtionPos - p.localtionPos

通过计算鼠标点 计算出 相对于图片原点的 偏移 并缓存

  public void OnBeginDrag( PointerEventData eventData )
    {
        Vector2 localPos;
        if ( Convert2local( eventData.position, out localPos, eventData.pressEventCamera ) )
        {
            Vector2 src = rectTransform.localPosition;
            offset = src - localPos;
            dragBeginEvent?.Invoke( src );
        }
    }

拖拽过程中 我们加上这个偏移向量 就能得到相对偏移的拖拽方式

sub.locationsPos = p.locationPos + offset

public void OnDrag( PointerEventData eventData )
    {
        Vector2 localPos;
        if ( Convert2local( eventData.position, out localPos, eventData.pressEventCamera ) )
        {
            Vector2 dest = ConstraintWithinParentNode( localPos + offset );
            rectTransform.localPosition = dest;
            dragEvent?.Invoke( dest );
        }
    }

限制活动范围 保持在父节点以内活动

示意图

在这里插入图片描述

如图可以知道 最小X 等于自身宽 的一半 同时要减去父节点 宽的一半
可以知道 最小Y 等于自身高 的一半 同时要减去父节点 高的一半

最大值 是父节点一半 - 自身大小的一半 在Unity里 你可以通过 pivot 来获取 图片锚点相对于图片自身size的百分比值 ( 0~1)

计算出最小X,最小Y,最大X,最大Y

  private void Start()
    {
        var parentAnchorX = parentRectTrans.pivot.x * parentRectTrans.rect.width;
        var parentAnchorY = parentRectTrans.pivot.y * parentRectTrans.rect.height;
        minX = rectTransform.rect.width * 0.5f - parentAnchorX;
        minY = rectTransform.rect.height * 0.5f - parentAnchorY;
        maxX = parentRectTrans.rect.width - rectTransform.rect.width * 0.5f - parentAnchorX;
        maxY = parentRectTrans.rect.height - rectTransform.rect.height * 0.5f - parentAnchorY;
    }

新的位置约束在范围内

在这里插入图片描述

   private Vector2 ConstraintWithinParentNode( Vector2 pos )
    {
        pos.x = Mathf.Clamp( pos.x, minX, maxX );
        pos.y = Mathf.Clamp( pos.y, minY, maxY );
        return pos;
    }

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

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

相关文章

2023年蜂巢科技最新面试题

2023年蜂巢科技最新面试题 bio与nio的区别 bio同步阻塞io&#xff1a;在此种⽅式下&#xff0c;⽤户进程在发起⼀个IO操作以后&#xff0c;必须等待IO操作的完成&#xff0c;只有当真正完成了IO操作以后&#xff0c;⽤户进程才能运⾏。JAVA传统的IO模型属于此种⽅式&#xff0…

易观:商业银行持续发力趣味营销活动,助力提升手机银行用户活跃度

易观&#xff1a;随着数字化时代发展&#xff0c;商业银行仍需持续在场景营销领域积极探索创新&#xff0c;坚持以用户为中心&#xff0c;开展千人千面的趣味营销活动&#xff0c;增强手机银行的互动性&#xff0c;完善活动参与的用户体验&#xff0c;提升营销活动效果&#xf…

了解高并发场景下的限流算法和解决方案

想必大家在做项目的时候&#xff0c;或多或少的都遇到过一些高并发的场景&#xff0c;这里主要是和大家一起来探讨下有关高并发下的处理方案。 常见的限流算法 1. 计数器 直接计数&#xff0c;简单暴力&#xff0c;举个例子&#xff1a; 比如限流设定为1小时内10次&#xff…

【Maven】(四)图解Maven3依赖的功能特性:依赖范围、依赖传递、依赖冲突

文章目录1.前言2.pom中的依赖配置2.1.依赖的概念2.2.依赖传递2.3.可选依赖 [optional]2.4.依赖范围 [scope]2.4.1.scope的分类2.4.2.依赖范围对依赖传递的影响2.5.依赖冲突2.5.1.直接依赖2.5.2.间接依赖2.6.依赖排除 [exclusions]3.总结1.前言 本系列文章记录了 Maven 从0开始…

搭建XXL-JOB

搭建XXL-JOB 1、 调度中心 首先下载XXL-JOB GitHub&#xff1a;GitHub - xuxueli/xxl-job: A distributed task scheduling framework.&#xff08;分布式任务调度平台XXL-JOB&#xff09; 码云&#xff1a;xxl-job: 一个分布式任务调度平台&#xff0c;其核心设计目标是开…

JDK17 下载与安装

JDK是 Java 语言的软件开发工具包&#xff0c;主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心&#xff0c;它包含了JAVA的运行环境&#xff08;JVMJava系统类库&#xff09;和JAVA工具。 1、下载JDK17 1.1、首先&#xff0c;检查下电脑中是否安装jd…

车机系统开发——Android Automotive

Android Automotive介绍 Android Automotive是⼀个基本的Android平台&#xff0c;它运⾏预安装的&#xff08;车载信息娱乐&#xff09;IVI系统&#xff0c;Android应⽤程序以及可选的第⼆⽅和第三⽅Android应⽤程序。 Android Automotive的硬件抽象层(HAL)为Android框架提供…

封装小程序request请求[接口函数]

在这篇小程序API的Promise化文章中讲到小程序官方提供的异步API都是基于回调函数来实现的&#xff0c;在大量的使用这种回调函数就会造成回调地狱的问题&#xff0c;以及代码的可读性和可维护性差&#xff0c;通过对小程序API的Promise化能解决&#xff0c;那么本篇是来讲进行对…

203. 移除链表元素 L2-027 名人堂与代金券

给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#…

内网离线安装docker-ce工具,带你来了解!

虽然通常我们都是使用网络来安装 docker 的&#xff0c;但是对于安全要求比较高的业务或者用户来说&#xff0c;部署产品需要在内网部署&#xff0c;而内网通常是无法访问外部网络的&#xff0c;所以就需要通过内网进行安装了。 1. yum 离线安装包获取方法 下载软件包 这里以…

语义分割数据标注案例分析

语义分割&#xff08;Semantic Segmentation&#xff09;是计算机视觉领域中的一种重要任务&#xff0c;它的目的是将图像中的每个像素分配到对应的语义类别中。简单来说&#xff0c;就是将一张图像分割成多个区域&#xff0c;并为每个像素指定一个标签&#xff0c;标识出它属于…

实时手势识别(C++与python都可实现)

一、前提配置&#xff1a; Windows&#xff0c;visual studio 2019&#xff0c;opencv&#xff0c;python10&#xff0c;opencv-python&#xff0c;numpy&#xff0c;tensorflow&#xff0c;mediapipe&#xff0c;math 1.安装python环境 这里我个人使用的安装python10&#…

MySQL进阶篇之MySQL管理

07、MySQL管理 7.1、系统数据库 MySQL数据库安装完成后&#xff0c;自带了四个数据库&#xff0c;具体作用如下&#xff1a; 数据库含义mysql存储MySQL服务器正常运行所需要的各种信息&#xff08;时区、主从、用户、权限等&#xff09;information_schema提供了访问数据库元…

科技赋能智慧警务,“链上天眼科技助警中国行”在京启动

2月28日&#xff0c;由全球领先的区块链大数据科技企业欧科云链和中国警察网联合举办的“链上天眼科技助警中国行”活动&#xff08;下称“活动”&#xff09;&#xff0c;在北京正式启动。为了普及区块链基础知识&#xff0c;以及虚拟货币犯罪追踪与打击的新型技术应用经验&am…

(三)随处可见的LED广告屏是怎么工作的呢?接入GUI

续上文&#xff0c;本篇我们将尝试接入一个GUI来控制点阵屏。在前两篇中&#xff0c;我们相继介绍了点阵屏的控制原理&#xff0c;以及如何让点阵屏按照我们所想的进行显示。本篇将在此基础上接入一个GUI&#xff0c;使点阵屏的控制更加优雅。限于阅读体验和展示效果&#xff0…

王道计算机网络课代表 - 考研计算机 第一章 计算机网络体系结构 究极精华总结笔记

本篇博客是考研期间学习王道课程 传送门 的笔记&#xff0c;以及一整年里对 计算机网络 知识点的理解的总结。希望对新一届的计算机考研人提供帮助&#xff01;&#xff01;&#xff01; 关于对 “计算机网络体系结构” 章节知识点总结的十分全面&#xff0c;涵括了《计算机网络…

SpringMVC之JSON工具:Jackson Gson 和fastjson通过JSON工具来解决文字乱码和时间格式问题——通过JSON工具生成JSON

什么是Json&#xff1f; JSON&#xff1a;JavaScript Object NotationJS对象 它是一种轻量级的数据交换格式JSON&#xff08;当前是交互的顶流&#xff09;&#xff0c;它自身具有独立的编程格式&#xff0c;它的特点是简洁和清晰&#xff0c;Json的存在大大改造了网络传输的…

ffmpeg音视频解码和渲染流程

背景&#xff1a; 随着游戏娱乐等直播业务的增长&#xff0c;在移动端观看直播的需求也日益迫切。但是移动端原生的播放器对各种直播流的支持却不是很好。Android 原生的 MediaPlayer 不支持 flv、hls 直播流&#xff0c;iOS 只支持标准的 HLS 流。本文介绍一种基于 ffplay 框…

挑选销售自动化工具应该关注什么功能?

销售自动化可以极大地提高你的生产力和效率&#xff0c;每周都为你节省时间。这样&#xff0c;你就可以把更多的时间用于完成交易&#xff0c;而减少用于行政任务的时间。市面上的销售自动化工具有很多&#xff0c;作为一般经验法则&#xff0c;以下是销售自动化工具中需要寻找…

智能家居Homekit系列一智能插座

WiFi智能插座对于新手接触智能家居产品更加友好&#xff0c;不需要额外购买网关设备 很多智能小配件也给我们得生活带来极大的便捷&#xff0c;智能插座就是其中之一&#xff0c;比如外出忘记关空调&#xff0c;可以拿起手机远程关闭。 简单说就是&#xff1a;插座可以连接wi…