React Draggable 实现图片拖拽

news/2024/7/15 19:09:19 标签: react.js, javascript, 前端

React Draggable 实现拖拽

React Draggablereact 生态中,最好用的拖拽实现库之一。如果你的应用中需要实现拖拽功能,可以尝试用 react-draggable,它可以满足多数情况下的拖拽需求,比如一个弹出设置浮窗,可以相互遮挡的容器之类。在所有 react 拖拽库里(即 react dnd, drag and drop),react-draggable 算是把功能性和易用性平衡得最好的拖拽库了。

在实现卡拉云时,我们也大量使用了 react-draggable。所以这篇文章里,我们介绍如何使用 react-draggable,一些常见的设置和我们的经验。请根据下面的代码一步步实现,最终你要实现的效果如下
在这里插入图片描述

如果你在参考的过程中有不确定代码应该怎么写,可以直接到代码库中找到对应的文件。本文可参考的代码放在 github 上: react-draggable代码,觉得不错的话不妨打个星。

react-draggable 简介

react-draggable 经过几年的发展,已经是一个相对比较稳定的库了。从 npm trends 上看,从 16 年起它的流行程度就迅速超过了其它几个类似的项目。它在 github 上算非常热门的项目了,使用它的项目众多,所以可以放心地使用。如果有 bug 反馈也会非常快

如果看它的源码的话,会发现它的原理其实很简单,它只是将一个需要被拖拽的组件包到它定义的一个组件中,当鼠标拖拽时,重新计算组件的位置,这样就实现了“拖拽”的效果。这也是绝大多数拖拽组件库的实现方式。

准备项目

我们按常规,使用 create-react-app 这个工具来创建项目。如果你本地没有安装 npx 的话,强烈推荐,使用非常方便。

在准备好 react 脚手架后,你就可以到目录里,把项目跑起来。

执行 npm start。这时候应该看到一个熟悉的画面

在这里插入图片描述

当然如果你是在已有项目里准备加上 react-draggable,那么跳过本步,直接执行下一步安装就好了。

安装 react-draggable

现在执行 npm install react-draggable,执行完后应该在你的 node_modules 中就装好了 react-draggable

新建一个盒子组件

我们先在 App.js 文件中加上几个简单的结构,比如一个框用来表示需要拖拽的组件,同时在框上加上一个拖拽把手,这样方便用户识别。

App.js 中加上一个叫 Box 的组件先占位,如下

	import './App.css';
	 
	const Box = () => {
	  return <>hello world</>
	}
	 
	function App() {
	  return (
	    <div className="App">
	        <Box></Box>
	    </div>
	  );
	}
	 
	export default App;

注意,这里的 Box 只是非常简单地在屏幕上打一行字出来。

接着,我们把 Box 稍微完善一下,把它的 css 写得规整一点。如果你对 css 本身不熟悉,没有关系,直接复制 index.css 中的代码就可以了。

.box {
  background-color: green;
  width: 300px;
  height: 300px;
  display: flex;
  flex-direction: column;
}
 
.drag-handler {
  background-color: grey;
  height: 50px;
  cursor: move;
}

到这里,我们应该已经可以看见基本成型的一个盒子组件。注意当鼠标移到把手上时,会出现拖拽的指针指示,这样可以提示用户这是一个可拖拽组件。

接入 react-draggable

现在,我们希望当用户鼠标拖拽把手时,把手本身可以被移动。首先我们把 react-draggable 导入

import Draggable from 'react-draggable'; 

到这里,App.js 中就是。

import './App.css';
import Draggable from 'react-draggable'; // The default
 
const Box = () => {
  return <div className="box">
    <div className='drag-handler'>拖这里可以</div>
    <div>box 正文,拖这里拖不动</div>
  </div>
}
 
function App() {
  return (
    <div className="App">
      <Draggable>
        <Box></Box>
      </Draggable>
 
    </div>
  );
}
 
export default App;

但是千万注意,如果这里你去试图拖拽一下把手,是拖不动的。原因是 Draggable 并不能直接包一个组件,而需要再包一层 div。我一开始在这里卡了很久时间,但解决的办法很简单,只需要多包一层 div 在外面即可。

function App() {
  return (
    <div className="App">
      <Draggable>
        <div>
          <Box />
        </div>
      </Draggable>
 
    </div>
  );
}

可以看到,如果这时候开始拖动,Box 就可以在界面上自由移动了。但是有一个问题,我们不希望用户拖动正文部分时,也将组件拖动。

在这里插入图片描述

要解决这个问题也很简单,请看下一章

如何在 react-draggable 中仅允许组件的一部分被拖动

react-draggableAPI 中,一个属性叫 handle,这个属性的作用就是用来选出对拖动有反应的组件部分。

对应到我们上面的例子,我们只希望在用户拖动把手时,整个组件移动。所以我们只需要用 handle 属性,选出来把手即可。我们在代码中加入

function App() {
  return (
    <div className="App">
      <Draggable handle='.drag-handler'>
        <div>
          <Box />
        </div>
      </Draggable>
 
    </div>
  );
}

注意这里,.drag-handler 是一个选择器,用来选出 className=drag-handler 的组件部分,也就是对应的我们的把手。

那么到此,组件就只能通过拖动把手而拖动了。

在这里插入图片描述

限制可拖动范围

有时候我们希望限制可以拖动的范围,比如你不希望用户把一个组件拖到另一个区域,因为可能挡住那个区域的其它界面。在 react-draggable 中,要限制拖动范围很简单,只需要给定 bounds 属性就可以了。

bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,

这个 bounds 属性可以指定屏幕上上下左右四个位置的边界限制,同时你也可以给一个字符串,用来选择组件的父组件,这样可以限制该组件只能在它的父组件中移动。限制在父组件中的情况较多,比如你在做一个扑克牌游戏时,显然只希望扑克牌只在牌桌上被拖动,那么你就可以限制扑克牌,让它始终在父组件牌桌中。

具体的例子这里就不展开讲了,请自行探索。

调整样式

最后我们稍微调整一下样式,让整个 APP 看起来漂亮一些。到此,你应该就已经学会使用 react-draggable 来实现拖拽操作了

在这里插入图片描述

总结
react-draggable 总体来说是一个非常优秀的拖拽库,虽然自己写也不需要太多代码,但使用一个“经历过战场”的组件库还是可以省掉不少自己实现的时间。同时它的 API 足够优秀,可以满足日常工作需要。如果你觉得自己写有太大挑战,尝试一下用卡拉云搭建后台工具,事半功倍。


http://www.niftyadmin.cn/n/96130.html

相关文章

I/O 多路复用:select/poll/epoll

url&#xff1a;9.2 I/O 多路复用&#xff1a;select/poll/epoll | 小林coding &#xff08;仅供自己学习使用&#xff09; 为什么要使用I/O多路复用技术 TCP Socket 调用流程是最简单、最基本的&#xff0c;它基本只能一对一通信&#xff0c;因为使用的是同步阻塞的方…

外盘国际期货招商:原油市场热点话题

原油市场热点话题 问&#xff1a;目前美国原油库存如何&#xff1f; 答&#xff1a;EIA原油库存数据显示&#xff0c;由于美国炼油厂季节性检修&#xff0c;开工率继续下降&#xff0c;原油库存连续九周增长至2021年5月份以来最高水平&#xff0c;同期美国汽油库存减少而精炼…

Near-Optimal Bayesian Online Assortment of Reusable Resources

摘要 受租赁服务在电子商务中的应用的激励&#xff0c;我们考虑为不同类型的到达消费者提供可重复使用资源的在线分类的收入最大化。我们针对贝叶斯环境中的最优在线策略设计了具有竞争力的在线算法&#xff0c;其中类型随时间独立于已知的异构分布绘制。在初始库存最小值cmin…

从0开始装Oracle Linux 7.9系统(另加多路径连接存储)

激动不已&#xff0c;因为学了很多本领 联想SR850 全盘打乱磁盘阵列&#xff0c;重新做系统 介质准备 借助 rufus等工具&#xff0c;将系统ISO文件&#xff0c;“烧”到U盘里 系统安装 F1 进入 System Setup&#xff0c;对磁盘阵列的RAID 性质进行定义 退出后&#xff0c;重启&…

APISIX网关系列之Dashboard配置路由(二)

APISIX网关系列之Dashboard配置路由(二) 1.概述 APISIX作为系列介绍&#xff0c;将它所有的功能按照职责划分输出到每篇文章中。 上篇文章作为系列的开篇文章对APISIX进行了分析和安装介绍&#xff0c;查看详情地址&#xff1a;https://blog.csdn.net/m0_38039437/article/de…

Android高仿陌陌应用点点滑动效果

效果图&#xff1a;分析:从效果上看图片的展示具有层次感&#xff0c;在数据结构上更像是stack,所以通过继承FrameLayout来实现&#xff08;不清楚FrameLayout布局特点的可以先百度下哈&#xff09;&#xff0c;外面是通过继承FrameLayout自定义的TinderStackLayout&#xff0c…

软考中级--嵌入式系统设计师考试培训教程开始了

1.考试时间: 1.1 上半年5月下旬考试 1.2 下半年11月上旬考试 2.考试内容 2.1 系统基础 满分75分 时间150分钟 2.2 系统设计 满分75分 时间150分钟 3.计划安排 3.1 熟悉考试大纲 3.2 按考纲学习相关内容 整理设计知识 快速学习形成知识印象 3.3 复习整理的知识 …

SpringBoot-基础篇

SpringBoot基础篇 ​ 在基础篇中&#xff0c;我给学习者的定位是先上手&#xff0c;能够使用SpringBoot搭建基于SpringBoot的web项目开发&#xff0c;所以内容设置较少&#xff0c;主要包含如下内容&#xff1a; SpringBoot快速入门SpringBoot基础配置基于SpringBoot整合SSMP…