react-dnd实现任意拖动与互换位置

本文实例为大家分享了react-dnd实现任意拖动与互换位置的具体代码,供大家参考,具体内容如下

react-dnd用法

hooks组件

1.使用DndProvider定义一个可以拖拽的范围

import { HTML5Backend } from 'react-dnd-html5-backend';
import { DndProvider } from 'react-dnd';

class App extends Component{
  render () {
    return (
      <div>
        <DndProvider backend={HTML5Backend}>
          <Container />
        </DndProvider>
      </div>
    )
  }
}

2.定义drag和drop

drag:就是可以被拖拽的东西

drop: 就是拖拽后可以放的地方

import { useDrag } from 'react-dnd';

/**item:必填。描述了要拖动的数据 ( 包含type: 对应drop>accept )
begin(monitor): 可选的。拖动操作开始时触发。
end(item, monitor): 可选的。当拖动停止时,end被调用。
canDrag(monitor): 可选的。使用它来指定当前是否允许拖动。
isDragging(monitor): 可选的。默认情况下,只有启动拖动操作的拖动源才被视为拖动。
collect: 可选的。收集功能。它应该返回道具的简单对象以返回注入到组件中。它接收两个参数,monitor和props。
spec:必填。一个普通的JavaScript对象,上面有一些允许的方法。它描述了拖动源如何对拖放事件做出反应。**/

const Drag = ({ name }) => {
  const [{isDragging}, drag] = useDrag({
    type: 'test',
    end(item, monitor) {   
        monitor.getDropResult()   //获取拖拽对象所处容器的数据
        monitor.didDrop()    // 当前容器能否放置拖拽对象
    }    
  })

  return (
    <div id="drag">{name}</div>
  )
}
import { useDrop } from 'react-dnd';

/**
参考api 
accept:必填。 (对应 drag item.type )
options: 可选的。一个普通的对象。
drop(item, monitor): 可选的。当兼容项目放在目标上时调用。
hover(item, monitor): 可选的。将项目悬停在组件上时调用。
canDrop(item, monitor): 可选的。使用它来指定放置目标是否能够接受该物品。如果要始终允许它,则只需忽略此方法。
collect: 可选的。收集功能。它应该返回道具的简单对象以返回注入到组件中。它接收两个参数,monitor和props
*/

const Container = (props) => {
  const [{isOver, canDrop}, drop] = useDrop({
    accept: 'test',
    drop: (item, monitor) => ({ 
        dropname: '测试', 
        top: monitor.getDifferenceFromInitialOffset().y,
        left: monitor.getDifferenceFromInitialOffset().x 
     }),  
    // 可以在这里配置数据,与drag中monitor.getDropResult()获取的信息关联
    collect: (monitor) => ({
      isOver: monitor.isOver(),   // 返回拖拽对象是否悬浮在该容器上
      canDrop: monitor.canDrop(),  // 当前容器是否支持拖拽对象放置
    })
  })

  return (
    <div ref={drop}>
        ...
    </div>
  )
}

实现任意拖拽

1.在容器中通过drop —> monitor.getDifferenceFromInitialOffset()获取拖拽对象当前位置与初始位置的偏移量

2.在drag的end中,通过monitor.getDropResult()获取到与初始位置的偏移量,给当前拖拽元素的偏移量重新赋值,即可做到任意拖拽

3.如果同时有很多个可拖拽的对象,需要给他们定义一个index值, 因为这个可拖拽组件是复用的,所以我们获取到的拖拽对象是个数组,我们可以用index作为下标,给当前拖拽组件单独赋值

const Drag = ({ name, top, left, index }) => {
  const [{isDragging}, drag] = useDrag({
    type: 'test',
    end(item, monitor) {
      console.log(item);
      if(monitor.didDrop()){
        const droptarget = monitor.getDropResult();
        const top = document.querySelectorAll('#drag')[index].offsetTop;
        const left = document.querySelectorAll('#drag')[index].offsetLeft;
        document.querySelectorAll('#drag')[index].style.top = (top + droptarget.top) + 'px';
        document.querySelectorAll('#drag')[index].style.left = (left + droptarget.left) + 'px';
      }else{
        console.log(monitor.getDropResult());
      }
    }
  })

  return (
    <div id="drag" index={index} ref={drag} style={{position: 'absolute', top: `${top}`, left: `${left}`, width: '70px', height: '40px', border: '1px solid black'}}>{name}</div>
  )
}
const Container = (props) => {
  const [{isOver, canDrop}, drop] = useDrop({
    accept: 'test',
    drop: (item, monitor) => ({ dropname: '测试', top: monitor.getDifferenceFromInitialOffset().y, left: monitor.getDifferenceFromInitialOffset().x }),
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    })
  })

  return (
    <div
      id="drop1"
      ref={drop}
      style={{width: '700px', height: '600px', backgroundColor: 'yellow'}}
    >

    </div>
  )
}

拖拽互换位置

拖拽互换位置需要组件既是drag拖拽对象,也是drop拖拽容器。所以使用useRef()定义ref,然后 drag(drop(ref)),让它即作为拖拽对象也作为拖拽容器,然后定义拖拽结束事件

import React, { useRef, useMemo } from 'react';
import { useDrag, useDrop } from 'react-dnd';
import { item } from './itemType';

const style = {
  display: 'inline',
  border: '1px dashed gray',
  padding: '0.5rem 1rem',
  marginRight: '30px',
  marginTop: '.5rem',
  backgroundColor: 'blue',
  cursor: 'move',
  borderRadius: '50%',
  position: 'relative',
};

const Drag = (props) => {
  const ref = useRef()

  const [{}, drop] = useDrop({
    accept: item.type,
    drop: (item, monitor) => {
        return {
          index: props.index
        }
    }
  })

  const count = useMemo(() => {
    document.getElementById('delete').oncontextmenu = (e) => {
      e.preventDefault();
    }
  },[1])

  const [{}, drag] = useDrag({
    type: item.type,
    end: (item, monitor) => {
      console.log(monitor.didDrop());
      if(monitor.didDrop()){
        const dropResult = monitor.getDropResult();
        props.changePosition([props.index, dropResult.index])
      }else{
        return;
      }
    }
  })

  drag(drop(ref))

  return (
    <div id="delete" ref={ref} id="drag" index={props.index} style={{...style}} >
      <span>{props.name}</span>
      <span style={{position: 'absolute', border: '1px solid gray', top: "18.5px", left: '145px', width: '29px',background: 'gray'}}></span>
    </div>
  )
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • react实现拖拽模态框

    前言 实际开发中,模态框展现数据会经常出现.但不幸的是有时功能开发完了,UI同学突然提出需求希望模态框能拖拽.本文使用的模态框由 ant design 3.0 的 Modal 组件封装而成,如何在不修改原来代码的基础上实现拖拽呢.最终效果图如下: 实践 1.创建高阶组件DragHoc 新建文件ModalDrag/index.js,将下面代码copy进去 DragObj是具体拖拽的原生js代码,后面再看 DragHoc是创建高阶组件的函数,其中参数InnerComponent是需要被改造的模态框组

  • react优雅处理多条件鼠标拖拽位移

    本文实例为大家分享了react优雅处理多条件鼠标拖拽位移的具体代码,供大家参考,具体内容如下 场景 三种拖拽条件 可纵轴 横轴 和全部方向 如果加3个监听重复代码太多因为状态更改组件会重新渲染 所以写的时候要多注意避免有大量代码的函数多次创建销毁 state const [position, setPosition] = useState(axisPosition); jsx <Container       style={{         top: position.top + "px

  • react-beautiful-dnd 实现组件拖拽

    一个React.js 的 漂亮,可移植性 列表拖拽库.想了解更多react-beautiful-dnd特点适用人群请看官方文档.中文翻译文档 npm:https://www.npmjs.com/package/react-beautiful-dnd 1.安装 ​ 在已有react项目中 执行以下命令 so easy. # yarn yarn add react-beautiful-dnd # npm npm install react-beautiful-dnd --save 2.APi 详情查

  • react实现自定义拖拽hook

    前沿 最近发现公司的产品好几个模块用到了拖拽功能,之前拖拽组件是通过Html5 drag Api 实现的但体验并不是很好,顺便将原来的拖拽组建稍做修改,写一个自定义hook,方便大家使用拖拽功能. 正文 拖拽功能原理: 1.拖拽元素通过addEventListener监听器添加鼠标按下,鼠标移动,以及鼠标抬起事件.2.再通过getBoundingClientRect() 得到拖拽元素四周相对于可拖拽区域边界的距离.3.鼠标移动时计算x轴和y轴的移动偏移量.4.通过element.style.tr

  • 使用react-beautiful-dnd实现列表间拖拽踩坑

    为什么选用react-beautiful-dnd 相比于react-dnd,react-beautiful-dnd更适用于列表之间拖拽的场景,支持移动端,且较为容易上手. 基本使用方法 基本概念 DragDropContext:构建一个可以拖拽的范围 onDragStart:拖拽开始回调 onDragUpdate:拖拽中的回调 onDragEnd:拖拽结束时的回调 Droppable - 可以放置拖拽块的区域 Draggalbe - 可被拖拽的元素 使用方法 把你想能够拖放的代码放到DragDr

  • React拖拽调整大小的组件

    本文实例为大家分享了React拖拽调整大小的组件,供大家参考,具体内容如下 一.实现流程 1.使用React.cloneElement加强包裹组件,在包裹的组件设置绝对定位,并在组件内加上四个可调整大小的拖动条,在点击拖动条并进行拖动时会改变DragBox的大小,如下: 2.使用: <DragBox dragAble={true} minWidth={350} minHeight={184} edgeDistance={[10, 10, 10, 10]} dragCallback={this.d

  • react-native 圆弧拖动进度条实现的示例代码

    本文介绍了react-native 圆弧拖动进度条实现的示例代码,分享给大家,具体如下: 先上效果图 因为需求需要实现这个效果图 非原生实现, 难点1:绘制 使用svg 难点2:点击事件的处理 难点3:封装 由于绘制需要是使用svg 此处自行百度 按照svg以及api 教学 视图代码块 render() { return ( <View pointerEvents={'box-only'} //事件处理 {...this._panResponder.panHandlers}> //实际圆环 {

  • react-dnd实现任意拖动与互换位置

    本文实例为大家分享了react-dnd实现任意拖动与互换位置的具体代码,供大家参考,具体内容如下 react-dnd用法 hooks组件 1.使用DndProvider定义一个可以拖拽的范围 import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider } from 'react-dnd'; class App extends Component{   render () {     return (  

  • Android 实现可任意拖动的悬浮窗功能(类似悬浮球)

    最近开发项目中,有个在屏幕上任意拖动的悬浮窗功能,其实就是利用 WindowManager的api来完成这个需求,具体的实现的功能如下: 1.自定义view import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.util.Log; import android.util.TypedValu

  • React DnD如何处理拖拽详解

    目录 正文 代码结构 DndProvider DragDropManager useDrag HTML5Backend TouchBackend 总结 正文 React DnD 是一个专注于数据变更的 React 拖拽库,通俗的将,你拖拽改变的不是页面视图,而是数据.React DnD 不提供炫酷的拖动体验,而是通过帮助我们管理拖拽中的数据变化,再由我们根据这些数据进行渲染.我们可能需要写额外的视图层来完成想要的效果,但是这种拖拽管理方式非常的通用,可以在任何场景下使用.初次使用可能感觉并不是那

  • Vue实现DOM元素拖放互换位置示例

    目录 一.拖放和释放 二.可拖拽属性 三.DataTransfer 3.1 属性 3.2 方法 四.DataTransferItem 4.1 属性 4.2 方法 五.DataTransferItemList 六.Event事件 七.实例 7.1 html代码 7.2 JS代码 一.拖放和释放 HTML 拖放接口使得 web 应用能够在网页中拖放文件.这里将介绍了 web 应用如何接受从底层平台的文件管理器拖动DOM的操作. 拖放的主要步骤是为 drop 事件定义一个释放区(释放文件的目标元素)

  • 使用jQuery实现两个div中按钮互换位置的实例代码

    效果如下 代码如下: <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript" src="js/jquery-2.1.0.js"></script> <script type="text/javascript"> $(function() { /

  • javascript实现拖动元素交换位置

    本文实例讲述了javascript实现拖动元素交换位置的代码.分享给大家供大家参考.具体如下: 实现目标:可拖动元素拖动到另外一个元素位置的时候,互相交换位置. 启发来源:最初形式是网上看到的一个拼图小游戏. 运行效果截图如下: 具体代码如下: 代码: body,ul,li{margin:0;padding:0;} ul{list-style: none;} body{font:13px/1.5 Tahoma;} #box{position:relative;width:435px;height

  • 易语言设置拖动滚动条的位置是否允许拖动跟踪的方法

    允许拖动跟踪属性 所属对象:纵向滚动条   操作系统支持:Windows,数据类型:逻辑型: 本属性设定当用户拖动滚动条的位置盒的过程中是否产生位置改变事件. 语法:  对象.允许拖动跟踪 =  逻辑型 应用对象:纵向滚动条 例程 说明: 纵向滚动条的允许拖动跟踪为假时,当拖动滚动条的鼠标放开以后才触发"位置被改变"事件. 纵向滚动条的允许拖动跟踪为真时,当滚动条的位置发生改变就触发"位置被改变"事件,与鼠标放不放开无关. 运行结果: 总结 以上就是这篇文章的全部内

  • vue实现div拖拽互换位置

    本文实例为大家分享了vue实现div拖拽互换位置的具体代码,供大家参考,具体内容如下 template模板 <transition-group tag="div" class="container"> <div class="item" v-for="(item,index) in items" :key="item.key" :style="{background:item.c

  • Android 自定义LineLayout实现满屏任意拖动功能的示例代码

    1.前言 在开发中,会有需求实现控件在屏幕随意拖动,这就需要自定义View,然后在OnTouchEvent事件中,处理MotionEvent.ACTION_MOVE事件,然后通过坐标点传值给onlayout方法,来实现控件的任意拖动,具体代码如下: import android.content.Context; import android.util.AttributeSet; import android.view.Display; import android.view.MotionEven

  • jQuery实现鼠标拖动div改变位置、大小的实践

    实现类似windows窗体的效果,在中间拖动改变div位置,在边缘拖动改变div大小,鼠标在相应的位置改变成相应的形状 效果如图: (截图没显示鼠标) 代码如下: $(".test1").mousemove(function(e){ $(".test1").unbind("mousedown"); $(".test1").css("cursor","default"); //$(&quo

随机推荐