React之拖动组件的设计(一)

news2024/12/24 2:11:38

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

这是一个简单的组件设计,如果用原生的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 (
        <div
            style={{
                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 (
        <Box
            sx={{
                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.coloradmin.cn/o/1461904.html

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

相关文章

【Vuforia+Unity】AR04-地面、桌面平面识别功能

不论你是否曾有过相关经验&#xff0c;只要跟随本文的步骤&#xff0c;你就可以成功地创建你自己的AR应用。 官方教程Ground Plane in Unity | Vuforia Library 这个功能很棒&#xff0c;但是要求也很不友好&#xff0c;只能支持部分移动设备&#xff0c;具体清单如下&#xf…

2024牛客寒假算法基础集训营5 -- EF soyorin的数组操作

题目大意&#xff1a; 思路解析&#xff1a; 我们可以发现偶数情况下&#xff0c;我们可以无限做 k n的操作&#xff0c;这样一定会让数组变为非降序数组。 但是奇数情况下&#xff0c;最后一个数没有办法发生变化&#xff0c;所以我们只能统计怎样在保证i--n为非降序情况下最…

ELK Stack 日志平台搭建

前言 最近在折腾 ELK 日志平台&#xff0c;它是 Elastic 公司推出的一整套日志收集、分析和展示的解决方案。 专门实操了一波&#xff0c;这玩意看起来简单&#xff0c;但是里面的流程步骤还是很多的&#xff0c;而且遇到了很多坑。在此记录和总结下。 本文亮点&#xff1a;…

洛谷 P1028 [NOIP2001 普及组] 数的计算

说明&#xff08;6&#xff09; 求出后五个加本身得到总方案 参考代码and代码解读

redis复习笔记06(小滴课堂)

分布式锁核心知识介绍和注意事项 基于Redis实现分布式锁的几种坑 综合伪代码&#xff1a; 运行&#xff1a;

压缩感知常用的测量矩阵

测量矩阵的基本概念 在压缩感知&#xff08;Compressed Sensing&#xff0c;CS&#xff09;理论中&#xff0c;测量矩阵&#xff08;也称为采样矩阵&#xff09;是实现信号压缩采样的关键工具。它是一个通常为非方阵的矩阵&#xff0c;用于将信号从高维空间映射到低维空间&…

电商+支付双系统项目------实现电商系统中分类模块的开发!

本篇文章主要介绍一下这个项目中电商系统的分类模块开发。电商系统有很多模块&#xff0c;除了分类模块&#xff0c;还有用户模块&#xff0c;购物车模块&#xff0c;订单模块等等。上一篇文章已经讲了用户模块&#xff0c;这篇文章我们讲讲项目中的分类模块。 有的人可能会很…

解决docker中运行的jar包连不上前端程序

目录 检查端口映射 查看容器的 IP 地址 检查容器网络设置 防火墙和网络策略 前端程序配置 跨域资源共享 (CORS) 日志查看 连接问题通常涉及到网络配置和端口映射。确保你在 Docker 中运行的 JAR 包可以被前端程序访问&#xff0c;可以采取以下步骤来解决问题&#xff1a…

职业技能鉴定服务中心前端静态页面(官网+证书查询)

有个朋友想做职业技能培训&#xff0c;会发证书&#xff0c;证书可以在自己网站可查。想做一个这样的网站&#xff0c;而且要特别土&#xff0c;一眼看上去像xxx官方网站&#xff0c;像jsp .net技术开发的网站。用htmlcssjquery还原了这样子一个前端页面&#xff0c;这里分享给…

操作系统导论-课后作业-ch19

1. 本书在第6章中有过介绍&#xff0c;gettimeofday函数最多精确到us&#xff0c;并且大致精确&#xff08;并不完全精确&#xff09;&#xff0c;需要多迭代几次减少误差&#xff0c;循环次数太多也会导致结束时间小于开始时间&#xff08;即回滚&#xff09;的现象&#xff…

LInux-信号1

文章目录 前言一、信号是什么&#xff1f;二、学习步骤使用kill -l命令查看信号列表可以看到有那么多信号&#xff0c;那么进程是如何识别这么多信号的呢&#xff1f; 使用kill命令终止进程信号的捕捉kill函数raise函数abort函数 Core dump如何查看自己的核心转储功能是否被打开…

【云原生】持续集成持续部署

本文主要总结CI/CD的流程&#xff0c;不会详细介绍每个知识点。 啥是集成&#xff1f;啥是部署&#xff1f; 集成&#xff0c;就是把应用程序、相关环境、配置全局打包放在一个容器中的操作。部署就不解释了。 CI/CD 如果是自己手动部署的话&#xff0c;流程应该是这样的&am…

Open CASCADE学习|计算全局属性

对于一个系统全局属性有&#xff1a; 质量(mass) 质心(mass center) 惯性张量(matrix of inertia) 关于一个轴的矩(moment about an axis) 关于一个轴的惯性半径(radius of gyration about an axis) 惯性的主属性&#xff0c;比如主轴(principal axis)&#xff0c;主矩(pr…

算法-搜索二维矩阵 II

1、题目来源 240. 搜索二维矩阵 II - 力扣&#xff08;LeetCode&#xff09; 2、题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#x…

Linux:Jenkins:GitLab+Maven+Jenkins的部署——离线包rpm版

Linux&#xff1a;Jenkins&#xff1a;GitLabMavenJenkins的部署&#xff08;1&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136157018?spm1001.2014.3001.5501这个是原版文章&#xff0c;均是使用的在线情况&#xff0c;但是不排除会有离线部署&am…

LaTex和Word中推荐使用的矢量图片格式

1、LaTex 推荐使用eps矢量格式。&#xff08;该格式直接放在word中不会显示&#xff0c;但是通过插入word后双击打开查看 2、Word 推荐使用svg矢量格式。该格式可以直接插入word中。 3、plt保存代码 import matplotlib.pyplot as plt# 绘制图形 x [1, 2, 3, 4, 5] y1 [1…

重新安装VSCode后,按住Ctrl(or Command) 点击鼠标左键不跳转问题

重新安装VSCode后&#xff0c;按住Ctrl&#xff08;or Command&#xff09; 点击鼠标左键不跳转问题 原因&#xff1a;重新安装一般是因为相应编程语言的插件被删除了或还没有下载。 本次是由于Python相关的插件被删除了&#xff0c;因此导致Python无法跳转。 解决办法 在vs…

挑战杯 基于人工智能的图像分类算法研究与实现 - 深度学习卷积神经网络图像分类

文章目录 0 简介1 常用的分类网络介绍1.1 CNN1.2 VGG1.3 GoogleNet 2 图像分类部分代码实现2.1 环境依赖2.2 需要导入的包2.3 参数设置(路径&#xff0c;图像尺寸&#xff0c;数据集分割比例)2.4 从preprocessedFolder读取图片并返回numpy格式(便于在神经网络中训练)2.5 数据预…

idm直链怎么用 IDM直链下载风险 Internet Download Manager下载 idm官网登录 idm直链提取

作为一款备受好评的下载加速器&#xff0c;idm几乎可以胜任所有的下载场景。无论是直链资源、磁力链接还是种子文件&#xff0c;idm均能把它们高速下载到本地保存。并且&#xff0c;理论上idm可以将下载速度提高3至5倍。有关idm直链怎么用&#xff0c;IDM直链下载风险的相关问题…

FFmpeg的HEVC解码器源代码学习笔记-1

一直想写一个HEVC的码流解析工具&#xff0c;看了雷神264码流解析工具&#xff0c;本来想尝试模仿写一个相似的265码流分析工具&#xff0c;但是发现265的解码过程和结构体和264的不太一样&#xff0c;很多结构体并没有完全暴露出来&#xff0c;没有想到很好的方法获得量化参数…