当前位置: 首页 > news >正文

React 模态框的设计(三)拖动组件的完善

我在上次的Draggable组件的设计中给了一个简化的方法,今天我来完善一下这个组件,可用于任何可移动组件的包裹。完善后的效果如下所示:

在这里插入图片描述
这个优化中,增加了一个注目的效果,还增加了触发可拖动区域的指定功能,这样我们对可拖动组件有更大的自由掌控。

Draggable 中增加以下两个Props

  • enableHandler 是否启用可拖动句柄

  • draggableHandler 可拖动句柄字符

上面的draggableHandler就是一个类名,如果 enableHandlertrue的情况下,可拖动组件中含有 draggableHandler 指定的类名的子组件的 mouseDown 事件会触发拖动的移动效果。其实触发事件是通过Draggable代理实现的。

import React, { useEffect, useRef, useState } from 'react';
import Box from '@mui/material/Box';/*** 拖动组件* @param {是否启用拖动句柄 } enableHandler * @param {拖动句柄的类名} draggableHandler*/
export default function Draggable({children, // 子组件enableHandler = false, // 是否启用拖动句柄draggableHandler = ".modelHandler" // 拖动句柄的类名
}) {const [isDragging, setIsDragging] = useState(false); // 是否正在拖动const [canDrag, setCanDrag] = useState(!enableHandler); // 是否可以拖动const [position, setPosition] = useState({ x: 0, y: 0 }); // 位置const offsetX = useRef(0); // x轴偏移量const offsetY = useRef(0); // y轴偏移量useEffect(() => {// 鼠标移动事件const handleMouseMove = (e) => {if (isDragging) {setPosition({x: e.clientX - offsetX.current,y: e.clientY - offsetY.current});}};// 鼠标抬起事件const handleMouseUp = (e) => {if(e.button !== 0) return;setIsDragging(false);};// 在相关的事件委托到document上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 onMouseMove = (e) => {if (enableHandler) {// 判断是否在拖动句柄上if (document.elementFromPoint(e.clientX, e.clientY).className.includes(draggableHandler)) {setCanDrag(true);} else {setCanDrag(false);}}}const handleMouseDown = (e) => {e.preventDefault();e.stopPropagation();if (enableHandler) {// 判断是否在拖动句柄上if (document.elementFromPoint(e.clientX, e.clientY).className.includes(draggableHandler)) {if (e.button !== 0) return;setIsDragging(true);offsetX.current = e.clientX - position.x;offsetY.current = e.clientY - position.y;}} else {if (e.button !== 0) return;setIsDragging(true);offsetX.current = e.clientX - position.x;offsetY.current = e.clientY - position.y;}};return (<Boxsx={{position: 'relative',transform: `translate(${position.x}px, ${position.y}px)`,cursor: canDrag ? isDragging ? "grabbing" : "grab" : "default",transition: `transform:`,}}onMouseDown={handleMouseDown}onMouseMove={onMouseMove}><Boxsx={{transform: `${isDragging ? "scale(1.03)" : "scale(1)"}`,transition: `transform 200ms ease-in-out`,}}>{children}</Box></Box>);
}

上面的逻辑并不复杂,通过过下面的语句可以找到含有指定类名的组件:

document.elementFromPoint(e.clientX, e.clientY).className.includes(draggableHandler)

这样就能判断当前鼠标是否处于指定的组件上并启动移动效果。 由于我们要实现抓取注目动画和移动动画,都是通过 transform实现的,但是我们只要缩放动画,所以我用了两层Box包裹来分割transform属性。

为了测试这个Draggable, 我来做个小组件测试 draggableHandler 的作用。

/** @jsxImportSource @emotion/react */
import { css, jsx } from '@emotion/react'
import Box from '@mui/material/Box';const titleBarCss = css`background-color: #BDBDBD;padding: 8px;`;const modelContentCss = css`padding: 16px;`;const ModalTest = ({width = 400, height = 300, bgColor = "white"}) => {return (<Box css={css`position: relative;background-color: ${bgColor};border: 1px solid #ccc;border-radius: 5px;overflow: hidden;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);width: ${width}px;height: ${height}px;`}><Boxcss={titleBarCss}className=".modelHandler">这是标题</Box><Box css={modelContentCss}>这是弹窗内容</Box></Box>);
};export default ModalTest;

上面的组件中,我们在标题栏上增加了类名: modelHandler。很简单是不是。接下来我们来完整的测试:

import React from "react";
import Stack from "@mui/material/Stack";
import Draggable from "../../framework-kakaer/SModel/_Draggable";
import ModelTest from "../../framework-kakaer/SModel/_DraggableContent";export default function DraggableTest() {return (<Stack spacing={3}><Stack direction="row" spacing={2}><Draggable><div style={{ width: 200, height: 200, backgroundColor: 'red' }}>Draggable</div></Draggable><Draggable><div style={{ width: 200, height: 200, backgroundColor: 'green' }}>Draggable</div></Draggable><Draggable><div style={{ width: 200, height: 200, backgroundColor: 'blue' }}>Draggable</div></Draggable></Stack><Stack direction="row" spacing={2}><Draggable enableHandler={true}><ModelTest width={200} height={200} bgColor="yellow" /></Draggable><Draggable><ModelTest width={200} height={200} bgColor="#FF9500" /></Draggable><Draggable><ModelTest width={200} height={200} bgColor="#5AC8FA" /></Draggable></Stack></Stack>);
}

这样就有了开头的效果了。相当的完美是不是。

相关文章:

React 模态框的设计(三)拖动组件的完善

我在上次的Draggable组件的设计中给了一个简化的方法&#xff0c;今天我来完善一下这个组件&#xff0c;可用于任何可移动组件的包裹。完善后的效果如下所示&#xff1a; 这个优化中&#xff0c;增加了一个注目的效果&#xff0c;还增加了触发可拖动区域的指定功能&#xff0c;…...

wondows10用Electron打包threejs的项目记录

背景 电脑是用的mac&#xff0c;安装了parallels desktop ,想用electron 想同时打包出 苹果版本和windows版本。因为是在虚拟机里安装&#xff0c;它常被我重装&#xff0c;所以记录一下打包的整个过程。另外就是node生态太活跃&#xff0c;几个依赖没记录具体版本&#xff0…...

git的master、develop、feature分支分别是做什么用的?有什么区别和联系?

在Git版本控制系统中&#xff0c;master、develop和feature分支都是常用的分支类型&#xff0c;它们有不同的用途和特点。 master分支&#xff1a;master分支是Git默认的主分支&#xff0c;它包含了项目的稳定版本。通常&#xff0c;master分支用于发布正式版本&#xff0c;即经…...

前端基础面试题

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1.请说明Ajax、Fetch、Axios三者的区别 三者都用于网络请求&#xff0c;但维度不同&#xff1a; Ajax&#xff08;Asynchronous Javascript ang XML&#xff09;&#xff0c;是一种在不重新…...

docker自定义网络实现容器之间的通信

Background docker原理 docker是一个Client-Server结构的系统&#xff0c;Docker的守护进程运行在主机上。通过Socket从客户端访问。docker核心三大组件&#xff1a;image–镜像、container-容器、 repository-仓库。docker使用的cpu、内存以及系统内核等资源都是直接使用宿主…...

NLP_构建GPT模型并完成文本生成任务

文章目录 搭建GPT模型&#xff08;解码器&#xff09;构建文本生成任务的数据集训练过程中的自回归文本生成中的自回归&#xff08;贪婪搜索&#xff09;完整代码小结 搭建GPT模型&#xff08;解码器&#xff09; GPT 只使用了 Transformer的解码器部分&#xff0c;其关键组件…...

使用puppeteer完成监听浏览器下载文件并保存到自己本地或服务器上完成上传功能

需求场景 获取网站点击的下载pdf&#xff0c;并把pdf重命名再上传到COS云上面 技术使用 “puppeteer”: “^19.7.2”, “egg”: “^3.15.0”, // 服务期用egg搭的 文件服务使用COS腾讯云 核心思路 获取浏览器下载事件&#xff0c;并把文件保存到本地 const session awai…...

软件压力测试:测试方法与步骤详解

随着软件应用的不断发展&#xff0c;用户对系统性能的要求也逐渐提高。在不同的负载条件下&#xff0c;系统必须能够保持稳定、高效的运行。软件压力测试是一种验证系统在各种负载情况下性能表现的关键手段。本文将详细探讨软件压力测试的方法和步骤。 1. 明确测试目标 在进行压…...

Oerlikon欧瑞康LPCVD system操作使用说明

Oerlikon欧瑞康LPCVD system操作使用说明...

pyspark统计指标计算

下面介绍如何使用pyspark处理计算超大数据的统计指标&#xff0c;主要为&#xff1a;最大值、最小值、均值、方差、标准差、中位数、众数、非重复值等。 # 加载稽核数据 rd_sql f"select * from database.table" spark_data spark.sql(rd_sql)# 计算众数 由于spar…...

2.22号qt

1.使用信号和槽实现多个界面跳转 1.1准备两个界面 1.2第一个界面准备signal 1.3第二个界面准备slot 1.4将第一个界面的信号和槽进行连接 2.qss登录界面升级优化 2.1概念 Qss是Qt程序界面中用来设置控件的背景图片、大小、字体颜色、字体类型、按钮状态变化等属性&#xff…...

$attrs

一、概念 vue官网定义如下: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过v-bind="$attrs"传入内部组件——在创建…...

OS X(MACOS) C/C++ 遍历系统所有的IP路由表配置。

以下源实现为遍历MAC苹果电脑系统上配置的所有IP路由表配置&#xff0c;回调 predicate 过滤函数只在 AF_INET(IPV4)的时候跳出&#xff0c;其它时不处理&#xff0c;人们可以根据自己的需求改动。 无需依赖MAC OS框架库提供的函数&#xff0c;最小依赖才有可能更容易移植代码到…...

人工智能_普通服务器CPU_安装清华开源人工智能AI大模型ChatGlm-6B_003---人工智能工作笔记0098

前面的环境安装差不多了,这里我没有安装git,因为我认为用不到,好下面去下载算法: 首先是算法下载: https://codeload.github.com/THUDM/ChatGLM-6B/zip/refs/heads/main 算法的下载连接是这里: 可以看到下载以后得到这个ChatGLM-6B-main这个算法压缩包 然后我们再去: 然后…...

基于JAVA的实验室耗材管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…...

NXP实战笔记(七):S32K3xx基于RTD-SDK在S32DS上配置ICU输入捕获

目录 1、概述 2、输入捕获SDK配置 2.1、SAIC中断方式 2.2、IPWM或者IPM 1、概述 输入捕获&#xff0c;可以抓取高电平时间、低电平时间、占空比、周期、边沿检测与回调函数、边沿计数&#xff08;ABZ解码&#xff09;、时间戳、唤醒中断。 记录一下根据Emios模块实现上述部分…...

左右联动布局效果

效果图&#xff1a; <template><el-dialog :modelValue"modelValue" :before-close"close" fullscreen :close-on-click-modal"false"><div class"farmer_detail"><div class"info_content"><di…...

【工具类】vscode ssh 远程免密登录开发

存放代码的机器运行 sshd,使用 vscode 的机器保证可以通过 ssh 登录服务器vscode 机器通过 ssh-keygen 生成 ssh 公私钥对将客户端的 id_rsa.pub 加入到服务器的鉴权队列 cat id_rsa.pub >> authorized_keysvscode 配置即可.ctrlp, remote-ssh: open ssh configuration f…...

【Antd】Form 表单获取不到 Input 的值

文章目录 今天遇到了一个奇怪的bug&#xff0c;Form表单中的Input组件的值&#xff0c;不能被Form获取&#xff0c;导致输入了内容&#xff0c;但是表单提交的时候值为undefined 报错代码 import { Button, Form, Input } from antd; import React from react;const App: Rea…...

Encoder-decoder 与Decoder-only 模型之间的使用区别

承接上文&#xff1a;Transformer Encoder-Decoer 结构回顾 笔者以huggingface T5 transformer 对encoder-decoder 模型进行了简单的回顾。 由于笔者最近使用decoder-only模型时发现&#xff0c;其使用细节和encoder-decoder有着非常大的区别&#xff1b;而huggingface的接口为…...

从点击到意图:鸿蒙 App 的 AI 进化

子玥酱 &#xff08;掘金 / 知乎 / CSDN / 简书 同名&#xff09; 大家好&#xff0c;我是 子玥酱&#xff0c;一名长期深耕在一线的前端程序媛 &#x1f469;‍&#x1f4bb;。曾就职于多家知名互联网大厂&#xff0c;目前在某国企负责前端软件研发相关工作&#xff0c;主要聚…...

海底管道电伴热机理及系统建模与控制策略【附程序】

✨ 长期致力于电伴热、集肤效应、Hammerstein模型、参数辨识、约束广义预测控制算法、功率调节、场路耦合法研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#…...

大模型小白必看:收藏!揭秘京东面试官如何破解多轮RAG“越聊越蠢”的难题

本文深入剖析多轮RAG在对话场景中容易出现的问题——越聊越“蠢”&#xff0c;即系统无法准确理解用户意图。文章指出&#xff0c;主要原因是历史对话内容污染了当前检索query&#xff0c;导致检索偏离用户真实意图。作者提出了四点判断框架&#xff1a;区分四类对象、检索quer…...

嵌入式C语言单元测试实战:Unity框架入门与工程实践

1. 项目概述&#xff1a;为什么嵌入式开发也需要单元测试&#xff1f;在嵌入式开发领域&#xff0c;尤其是使用C语言进行单片机、RTOS或裸机程序开发时&#xff0c;我们常常陷入一种“烧录-看灯-调串口”的循环。代码逻辑稍微复杂一点&#xff0c;比如一个状态机或者一个协议解…...

体验 Taotoken 官方价折扣活动对个人开发者月度支出的实际影响

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 体验 Taotoken 官方价折扣活动对个人开发者月度支出的实际影响 作为一名独立开发者&#xff0c;我日常需要调用多种大模型 API 来完…...

别再只盯着p值和FC了!用DisGeNET给你的Hub Gene打分,提升下游验证成功率

别再只盯着p值和FC了&#xff01;用DisGeNET给你的Hub Gene打分&#xff0c;提升下游验证成功率 在基因功能研究的海洋中&#xff0c;Hub Gene如同灯塔般指引着研究方向。然而&#xff0c;许多研究者仍被困在传统筛选方法的局限中——过度依赖差异表达基因的p值和fold change阈…...

为什么你的Perplexity总搜不到知网核心期刊?97.6%用户忽略的3个元数据过滤阈值(附知网后台原始字段对照表)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Perplexity知网文献搜索失效的底层归因 Perplexity.ai 作为一款基于大模型的实时网络问答工具&#xff0c;其核心能力依赖于对公开网页内容的动态抓取与语义解析。然而当用户尝试通过 Perplexity 查询中…...

从一块烧坏的板子说起:PCB电源平面设计中最容易被忽略的‘路径’与‘形状’陷阱

从一块烧坏的板子说起&#xff1a;PCB电源平面设计中最容易被忽略的‘路径’与‘形状’陷阱 那块烧焦的PCB板至今仍躺在我的抽屉里——12V电源轨上清晰的碳化痕迹&#xff0c;像一道闪电劈开了整个设计团队的自信。当客户退回第三批故障设备时&#xff0c;我们才意识到&#xf…...

联发科天玑700/720/900核心板选型指南:5G物联网与智能硬件性能功耗全解析

1. 项目概述&#xff1a;从核心板选型看5G入门级应用的性能锚点 在嵌入式开发和智能硬件领域&#xff0c;选择一颗合适的核心板&#xff08;Core Board&#xff09;往往是项目成败的第一步。它集成了处理器、内存、基带、射频等核心部件&#xff0c;直接决定了产品的性能基线、…...

LinuxCNC新手到专家:5个步骤打造你的完美数控系统

LinuxCNC新手到专家&#xff1a;5个步骤打造你的完美数控系统 【免费下载链接】linuxcnc LinuxCNC controls CNC machines. It can drive milling machines, lathes, 3d printers, laser cutters, plasma cutters, robot arms, hexapods, and more. 项目地址: https://gitcod…...