React 模态框的设计(一)拖动组件的设计

春节终结束了,忙得我头疼。终于有时间弄自己的东西了。今天来写一个关于拖动的实例讲解。先看效果:
在这里插入图片描述

这是一个简单的组件设计,如果用原生的js设计就很简单,但在React中有些事件必须要多考虑一些。这是一个系列的文章,专门针对实际应用开发过程中的技术难点逐个讲解,相信大家能用得着。
再次说明,我的示例都是基于MUI框架的,如果你不讲究样式的话,也可以直接采用原生dom的样式设计。关于项目的创建及MUI的应用请查看我以往的文章,都是详细的教程讲解。

要点解说

设计的思路是只把把要移动的组件进行包裹就可以对其进行拖动,注意是拖动,(不是拖放,我后期会出一个拖放的技术文章,请大家另行期待)

第一步: 首先是触发机制,当在目标组件上按下左键时开始拖动,所以要有个标记记录拖动的状态。

const [isDragging, setIsDragging] = useState(false);

当按下左键时设置为 true, 放开时设置为false

// 鼠标按下左键时的事件
const handleMouseDown = (event) => {if (event.button !== 0) return;  // 按下的不是左键则直接返回。setIsDragging(true);
};// 鼠标放开左键时的事件
const handleMouseUp = (event) => {if(event.button !== 0) return;setIsDragging(false);
};

第二步: 单击左键时要记录下鼠标的位置信息,我们定义一个state来记录这个值:

const offsetX = useRef(0);
const offsetY = useRef(0);

第三步: 单击左键不放进行移动,要记录下相对于position的变化量。因为要把这个变化反应到UI上,所以要用useState:

const [position, setPosition] = useState({ x: 0, y: 0 });

继续下面的代码:

// 鼠标按下左键时的事件
const handleMouseDown = (event) => {if (event.button !== 0) return;offsetX.current = event.clientX - position.x;offsetY.current = event.clientY - position.y;setIsDragging(true);
};// 鼠标移动事件
const handleMouseMove = (event) => {if (isDragging) {setPosition({x: event.clientX - offsetX.current,y: event.clientY - offsetY.current});}
};

或许你会想直接把这些事件绑定到要拖动的组件上就行了,但这里有个问题,有时我们拖着拖着由于速度过快,鼠标就移出了组件,这就达不到我们的设计效果了。所以呢,我们要把相应的事件绑定到document上是最靠谱的。我们只要把触发事件绑定到拖动组件上就可以了。

if (isDragging) {document.addEventListener('mousemove', handleMouseMove);document.addEventListener('mouseup', handleMouseUp);
} else {document.removeEventListener('mousemove', handleMouseMove);document.removeEventListener('mouseup', handleMouseUp);
}

document上绑定的事件在组件卸载后还要移除,所以我们用到useEffect,完整的代码如下:

import React, { useEffect, useRef, useState } from 'react';export default function Draggable({children}) {const [isDragging, setIsDragging] = useState(false);const [position, setPosition] = useState({ x: 0, y: 0 });const offsetX = useRef(0);const offsetY = useRef(0);useEffect(() => {const handleMouseMove = (event) => {if (isDragging) {setPosition({x: event.clientX - offsetX.current,y: event.clientY - offsetY.current});}};const handleMouseUp = (event) => {if(event.button !== 0) return;setIsDragging(false);};if (isDragging) {document.addEventListener('mousemove', handleMouseMove);document.addEventListener('mouseup', handleMouseUp);} else {document.removeEventListener('mousemove', handleMouseMove);document.removeEventListener('mouseup', handleMouseUp);}return () => {document.removeEventListener('mousemove', handleMouseMove);document.removeEventListener('mouseup', handleMouseUp);};}, [isDragging]);const handleMouseDown = (event) => {event.preventDefault();event.stopPropagation();if (event.button !== 0) return;offsetX.current = event.clientX - position.x;offsetY.current = event.clientY - position.y;setIsDragging(true);};return (<divstyle={{position: 'relative',userSelect: 'none',cursor: isDragging ? 'grabbing' : 'grab',transform: `translate(${position.x}px, ${position.y}px)`}}onMouseDown={handleMouseDown}>{children}</div>);
}

这样一个基本的拖动组件就设计完成了。快试试效果吧。

import React from "react";
import Draggable from "../framework-kakaer/SModel/_Dragable";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Typegraphy from "@mui/material/Typography";function DraggableTest() {return (<Boxsx={{display: 'flex',flexDirection: 'column',alignItems: 'center',justifyContent: 'center',height: '100vh',}}><Stack spacing={2}><Typegraphy variant="h4">拖动组件设计测试</Typegraphy><Draggable><Box sx={{ width: 100, height: 100, bgcolor: 'red' }} /></Draggable><Draggable><Box sx={{ width: 100, height: 100, bgcolor: 'blue' }} /></Draggable></Stack></Box>)
}export default DraggableTest;

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

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

相关文章

UI设计中,2D、2.5D、3D、4D该如何辨别?教会你

hello&#xff0c;我是大千UI工场&#xff0c;从事UI设计8年之久&#xff0c;在日常工作中经常听到一些概念&#xff0c;现在将这些概念图文并茂的呈现给您&#xff0c;欢迎点赞评论&#xff0c;如有设计需求&#xff0c;可以私信我们。 在UI设计中&#xff0c;2D、2.5D、3D和4…

企业计算机服务器中了babyk勒索病毒怎么办?Babyk勒索病毒解密数据恢复

随着网络技术的应用与普及&#xff0c;越来越多的企业采用了数字化办公模式&#xff0c;数字化办公模式可以为企业提供强有力的数据支撑&#xff0c;可以为企业的发展方向与产品业务调整做好基础工作。但网络是一把双刃剑&#xff0c;在为企业提供便利的同时&#xff0c;也为企…

Visual Studio 打开.edmx文件不显示表并报错:没有可用于.edmx的编辑器

打开.edmx文件时&#xff0c;呈现的是xml视图&#xff0c;不显示Diagram视图&#xff0c;且弹出报错“没有可用于.edmx的编辑器” 解决方案&#xff1a;在.edmx文件上右键&#xff0c;选择ado.net entity data model designer&#xff0c;即可正常显示表

EasyRecovery2024数据恢复软件深度评测与使用教程

一、EasyRecovery数据恢复软件是否好用&#xff1f; EasyRecovery是一款业界知名的数据恢复软件&#xff0c;具有强大的恢复能力和广泛的数据兼容性。它能帮助用户从各种存储设备中恢复丢失或删除的数据&#xff0c;包括硬盘、U盘、SD卡等。以下是关于EasyRecovery的详细分析&…

《C++面向对象程序设计》✍学习笔记

C的学习重点 C 这块&#xff0c;重点需要学习的就是一些关键字、面向对象以及 STL 容器的知识&#xff0c;特别是 STL&#xff0c;还得研究下他们的一些源码&#xff0c;下面是一些比较重要的知识&#xff1a; 指针与引用的区别&#xff0c;C 与 C 的区别&#xff0c;struct 与…

25-k8s集群中-RBAC用户角色资源权限

一、RBAC概述 1&#xff0c;k8s集群的交互逻辑&#xff08;简单了解&#xff09; 我们通过k8s各组件架构&#xff0c;知道各个组件之间是使用https进行数据加密及交互的&#xff0c;那么同理&#xff0c;我们作为“使用”k8s的各种资源的使用者&#xff0c;也是通过https进行数…

ARMv8-AArch64 的异常处理模型详解之异常向量表vector tables

目录 一&#xff0c;AArch64 异常向量表 二&#xff0c;栈指针以及SP寄存器的选择 三&#xff0c;从异常返回 一&#xff0c;AArch64 异常向量表 异常向量表&#xff08;vector tables&#xff09;是一组存放于普通内存&#xff08;normal memory&#xff09;空间的&#xf…

【智能车入门:pcb版】(蓝牙遥控、超声波避障、红外循迹)

实现最简单的蓝牙遥控、超声波避障、红外循迹&#xff09; 总览项目获取 本篇是对 上一篇博客的改进&#xff0c;上一篇博客使用面包板&#xff0c;看起来很乱&#xff0c;春节结束之后嘉立创免费打板恢复&#xff0c;板子到了之后进行焊接测试&#xff0c;相较于使用面包板&a…

【算法与数据结构】链表、哈希表、栈和队列、二叉树

目录 一、算法与数据结构 二、链表 三、哈希表 四、栈和队列 五、二叉树 一、算法与数据结构 算法和数据结构是计算机科学中两个非常重要的概念。 数据结构是组织和存储数据的方式&#xff0c;它定义了数据元素之间的关系和操作。数据结构可以分为线性结构&#xff08;如…

【前端素材】推荐优质后台管理系统Welly平台模板(附源码)

一、需求分析 后台管理系统&#xff08;或称作管理后台、管理系统、后台管理平台&#xff09;是一种专门用于管理网站、应用程序或系统后台运营的软件系统。它通常由一系列功能模块组成&#xff0c;为管理员提供了管理、监控和控制网站或应用程序的各个方面的工具和界面。以下…

让程序员设计B端界面,好比武大郎招聘:向我看齐。不忍直视!

hello&#xff0c;我是大美B端工场&#xff0c;B端系统的要求越来越高了&#xff0c;很多公司还让程序员负责页面&#xff0c;页面搞的没法看&#xff0c;也怪不得程序员。程序员来搞页面&#xff0c;那还不是武大郎招聘——向我看齐&#xff0c;以我的标准为标准吗&#xff1f…

Spring Security学习(七)——父子AuthenticationManager(ProviderManager)

前言 《Spring Security学习&#xff08;六&#xff09;——配置多个Provider》有个很奇怪的现象&#xff0c;如果我们不添加DaoAuthenticationProvider到HttpSecurity中&#xff0c;似乎也能够达到类似的效果。那我们为什么要多此一举呢&#xff1f;从文章的效果来看确实是多…

C++的STL常用算法->常用遍历算法、常用查找算法、常用排序算法、常用拷贝和替换算法、常用算术生成算法、常用集合算法

#include<iostream> using namespace std; #include <algorithm> #include <vector> //常用遍历算法 for_each //普通函数 void print01(int val) { cout << val << " "; } //仿函数 //函数对象 class print02 { public: v…

go语言的理解,看这一篇就够了

1.来源 Go语言是谷歌2009年发布的第二款开源编程语言 2.谷歌为什么要创建Go语言 计算机硬件技术更新频繁, 性能提高很快,默目前主流的编程语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能软件系统复杂度越来越高,维护成本越来越高,目前缺乏一个简洁而高效…

备考2024年汉字小达人:历年考题练一练-18道选择题

今天为大家分享汉字小达人的备考学习资源&#xff0c;通过参加没有报名费、人人可参加的汉字小达人比赛&#xff0c;激发孩子学习语文的兴趣&#xff0c;并且提升语文学习成绩。 汉字小达人的两轮比赛&#xff08;区级自由报名活动、市级活动&#xff09;的选择题主要有六种题型…

Unity(第三部)新手绘制地形

1、创建地形 游戏对象3d对象地形 2、功能 1、 红框内按键为创建相邻地形、点击后相近地形会呈现高亮框、点击高亮区域可以快速创建地形 每块地形面积是1km*1km 2、第二个按钮是修改地形 下面的选择是修改类型 选项含义描述Raise or Lower Terrain升高或降低地形单击左键可…

备战蓝桥杯————双指针技巧巧解数组3

利用双指针技巧来解决七道与数组相关的题目。 两数之和 II - 输入有序数组&#xff1a; 给定一个按升序排列的数组&#xff0c;找到两个数使它们的和等于目标值。可以使用双指针技巧&#xff0c;在数组两端设置左右指针&#xff0c;根据两数之和与目标值的大小关系移动指针。 …

Python中的functools模块详解

大家好&#xff0c;我是海鸽。 函数被定义为一段代码&#xff0c;它接受参数&#xff0c;充当输入&#xff0c;执行涉及这些输入的一些处理&#xff0c;并根据处理返回一个值&#xff08;输出&#xff09;。当一个函数将另一个函数作为输入或返回另一个函数作为输出时&#xf…

mapbox初体验

mapbox 初体验 简介导入 CDN 链接创建地图实例注册 token设置地图基本属性地图显示 1. 简介 我们将使用Mapbox GL JavaScript库创建地图的 HTML 示例。Mapbox GL是一个用于构建现代 Web 地图的开源库&#xff0c;提供了丰富的地图功能和自定义性。 2. 导入 CDN 链接 首先&…

2023最新盲盒交友脱单系统源码

源码获取方式 搜一搜&#xff1a;万能工具箱合集 点击资源库直接进去获取源码即可 如果没看到就是待更新&#xff0c;会陆续更新上 或 源码软件库 最新盲盒交友脱单系统源码&#xff0c;纸条广场&#xff0c;单独抽取/连抽/同城抽取/高质量盒子 新增功能包括心动推荐&#xff…