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://www.mzph.cn/news/696432.shtml

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

相关文章

YOLOv9来咧!

文章目录 论文:主要内容一、提出使用PGI&#xff08;Programmable Gradient Information&#xff0c;可编程梯度信息&#xff09;来解决信息瓶颈问题和深度监督机制不适合轻量级神经网络的问题。二、设计了GELAN&#xff08;Generalized ELAN &#xff0c;广义ELAN&#xff09;…

LLM 模型融合实践指南:低成本构建高性能语言模型

编者按&#xff1a;随着大语言模型技术的快速发展&#xff0c;模型融合成为一种低成本但高性能的模型构建新途径。本文作者 Maxime Labonne 利用 mergekit 库探索了四种模型融合方法&#xff1a;SLERP、TIES、DARE和passthrough。通过配置示例和案例分析&#xff0c;作者详细阐…

Ansible playbook 剧本部署WEB NFS rsync sersync(及时监控)架构

ansible playbook剧本介绍&#xff1a; playbook 是ansible用于配置&#xff0c;部署和管理被节点的剧本 由一个或多个模块组成&#xff0c;完成统一的目的&#xff0c;实现自动化操作 剧本编写需遵循yaml语法 yaml的三要素&#xff1a; 缩进&#xff1a;两个字符&#xff0c;默…

【Vue3】toRefs和toRef在reactive中的一些应用

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

C++模板->模板的概念、函数模板基本语法、函数模板注意事项、普通函数与函数模板区别、普通函数与函数模板调用规则、模板的局限性

#include<iostream> using namespace std; //交换两个整型函数 void swapInt(int& a, int& b) { int temp a; a b; b temp; } //交换两个浮点型函数 void swapDouble(double& a, double& b) { double temp a; a b; b te…

MATLAB中gtext函数用法

目录 语法 说明 示例 使用鼠标将文本添加到图窗 指定字体大小和颜色 在创建后修改文本 gtext函数的功能是使用鼠标将文本添加到图窗。 语法 gtext(str) gtext(str,Name,Value) t gtext(___) 说明 gtext(str) 在使用鼠标选择的位置插入文本 str。当将鼠标指针悬停在图…

3个wordpress中文企业主题模板

农业畜牧养殖wordpress主题 简洁大气的农业畜牧养殖wordpress主题&#xff0c;农业农村现代化&#xff0c;离不开新农人、新技术。 https://www.jianzhanpress.com/?p3051 老年公寓wordpress主题 浅绿色简洁实用的老年公寓wordpress主题&#xff0c;适合做养老业务的老年公…

高标准农田仪器设备

在当今社会中&#xff0c;农业已经逐渐走向了一条科技化、智能化的道路。高标准农田建设成为了现代化农业发展的一个重要方向。为了更好地提高农产品的产量和品质&#xff0c;科技人员们不断地在农田设备上进行创造性的改进与升级&#xff0c;以达到更加高效、节能、环保、智能…

【C语言】注释

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

【国际化】用JQuery-i18next的国际化demo,引入json

参考&#xff1a; 使用 i18next 的 jQuery 国际化 &#xff08;i18n&#xff09; 渐进式指南 (locize.com) i18next-http-backend/example/jquery/index.html at master i18next/i18next-http-backend (github.com) 文档 可能需要解决一下跨域问题&#xff0c;因为浏览器读取本…

Unity学习之Unity中的MVC思想

文章目录 1 前言2 MVC的基本概念3 不使用MVC思想制作UI逻辑3.1 拼面板3.2 面板脚本3.3 角色面板逻辑3.4 角色升级 4 使用MVC思想制作UI逻辑4.1 Model数据脚本4.2 View界面脚本4.2.1 MainView主界面4.2.2 RoleView 角色面板界面 4.3 Controller业务逻辑脚本4.3.1 MainController…

phaseDNN文章解读

文章DOI: https://doi.org/10.48550/arXiv.1905.01389 作者是 Southern Methodist University 的Wei Cai 教授 A Parallel Phase Shift Deep Neural Network for Adaptive Wideband Learning 一种并行移相深度神经网络来自适应学习宽带频率信号 20190514 核心思想&#xff1a;…

跟着pink老师前端入门教程(JavaScript)-day05

六、语句 &#xff08;一&#xff09;表达式和语句 1、表达式 表达式是可以被求值的代码&#xff0c;JavaScript 引擎会将其计算出一个结果。 2、语句 语句是一段可以执行的代码。 比如&#xff1a; prompt() 可以弹出一个输入框&#xff0c;还有 if语句 for 循环语句等…

Socks5代理IP详解:优势与应用场景

Socks5代理IP作为网络代理技术的前沿选择&#xff0c;其在多方面的优势使其在2024年成为了热门选择。 一、Socks5代理IP的核心特性 1、Socks5代理IP与其他代理类型的比较 HTTP代理设计用于web浏览&#xff0c;仅支持HTTP和HTTPS协议。 Socks4代理支持更多类型的网络协议&…

欧拉回路和欧拉路径

在一张图中&#xff0c;从一个点出发每条边经过且只经过一次得到的路径&#xff0c;如果最后回到起点&#xff0c;那么就是欧拉回路&#xff0c;如果最后没有回到起点&#xff0c;那么得到的就是欧拉路径。 在无向图中&#xff0c;欧拉路径满足的要求是&#xff0c;除了起点和…

DM数据库学习之路(十六)DEM部署DM8DPC集群

DEM部署DPC集群 DPC准备工作 在所有安装DPC服务器上部署dmagent&#xff0c;dmagent的运行环境需要依赖JAVA环境&#xff0c;JAVA版本必须为JAVA1.8。 创建用户 所有安装DPC服务器&#xff0c;手工建dmdba用户 # groupadd dinstall # useradd -g dinstall -d /home/dmdba…

并发编程之深入理解Java线程

并发编程之深入理解Java线程 线程基础知识 线程和进程 进程 程序由指令和数据组成、但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须要将指令加载至CPU、数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理IO的…

Jmeter内置变量 vars 和props的使用详解

JMeter是一个功能强大的负载测试工具&#xff0c;它提供了许多有用的内置变量来支持测试过程。其中最常用的变量是 vars 和 props。 vars 变量 vars 变量是线程本地变量&#xff0c;它们只能在同一线程组内的所有线程中使用&#xff08;线程组内不同线程之间变量不共享&#…

模型转换案例学习:等效替换不支持算子

文章介绍 Qualcomm Neural Processing SDK &#xff08;以下简称SNPE&#xff09;支持Caffe、ONNX、PyTorch和TensorFlow等不同ML框架的算子。对于某些特定的不支持的算子&#xff0c;我们介绍一种算子等效替换的方法来完成模型转换。本案例来源于https://github.com/quic/qidk…

并发编程(2)基础篇-管程

4 共享模型之管程 本章内容 共享问题synchronized线程安全分析Monitorwait/notify线程状态转换活跃性Lock 4.1 共享带来的问题 4.1.1 小故事 老王&#xff08;操作系统&#xff09;有一个功能强大的算盘&#xff08;CPU&#xff09;&#xff0c;现在想把它租出去&#xff…