基于react-draggable实现antd的可拖拽弹框

485 阅读3分钟

使用场景: 有时候在用户操作后台管理系统某个页面时,会出现一种录入弹窗,但是会遮挡我们要看的一些信息,这时候就会有需求这个弹窗可拖拽,这样子我们就可以移动看到我们需要的相关信息

准备工作

拖砖功能主要是基于 react-draggable实现的,首先安装依赖

npm install react-draggable
或者
yarn add react-draggable

常用属性

属性默认值介绍
axisxhandle拖动的方向,可选值 x ,y,both
handle指定拖动handle的class
positionhandle的位置,需要实时改变,否则handle无法拖动,类似于react的受控组件
onStrat方法拖动开始
onDrag方法拖动中
onStop方法结束拖动

属性列表

属性名称说明
bounds指定移动的边界值;可以设置的值 left:number,top:number,right:number,bottom:number
groupgroup= “name”,相同的组之间可以相互拖拽
sortsort= “true”,是否开启内部排序,如果设置为false,它所在组无法排序,在其他组可以拖动排序
delaydelay= “0”, 鼠标按下后多久可以拖拽
touchStartThreshold鼠标移动多少px才能拖动元素
disableddisabled= “true”,是否启用拖拽组件
animation拖动时的动画效果,还是很酷的,数字类型。如设置animation=1000表示1秒过渡动画效果
handlehandle=“.mover” 只有当鼠标移动到css为mover类的元素上才能拖动
filterfilter=“.unmover” 设置了unmover样式的元素不允许拖动
draggabledraggable=“.item” 那些元素是可以被拖动的
ghostClassghostClass=“ghostClass” 设置拖动元素的占位符类名,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true
chosenClassghostClass=“hostClass” 被选中目标的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true
dragClassdragClass="dragClass"拖动元素的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true
dataIdAttrdataIdAttr: ‘data-id’
forceFallback默认false,忽略HTML5的拖拽行为,因为h5里有个属性也是可以拖动,你要自定义ghostClass chosenClass dragClass样式时,建议forceFallback设置为true
fallbackClass默认false,克隆的DOM元素的类名
allbackOnBody默认false,克隆的元素添加到文档的body中
fallbackTolerance拖拽之前应该移动的px
scroll默认true,有滚动区域是否允许拖拽
scrollFn滚动回调函数
scrollSensitivity距离滚动区域多远时,滚动滚动条
scrollSpeed滚动速度

例子展示

页面中有一个antd弹窗,使用modalRender自定义渲染对话框,本质是外层包裹Draggable

......
import { useState } from 'react';
import { Modal } from 'antd';
import Draggable from 'react-draggable';
.......
  const draggleRef = useRef(null);
  const [bounds, setBounds] = useState({
    left: 0,
    top: 0,
    bottom: 0,
    right: 0,
  });
  
    const onStart = (_event, uiData) => {
    const { clientWidth, clientHeight } = window.document.documentElement;
    const targetRect = draggleRef.current?.getBoundingClientRect();

    if (!targetRect) {
      return;
    }

    setBounds({
      left: -targetRect.left + uiData.x,
      right: clientWidth - (targetRect.right - uiData.x),
      top: -targetRect.top + uiData.y,
      bottom: clientHeight - (targetRect.bottom - uiData.y),
    });
  };

<Modal
  getContainer={() => document.getElementById('layout') as HTMLElement}
  width={375}
  title={
    <div>
      这是页面中的弹窗
    </div>
  }
  onCancel={() => {
    ......
  }}
  open={trur}
  footer={null}
  modalRender={(modal) => {
    return (
      <Draggable
        bounds={bounds}
        onStart={(event, uiData) => onStart(event, uiData)}
      >
        <div ref={draggleRef}>{modal}</div>
      </Draggable>
    );
  }}
>
    这是页面中弹窗的内容
</Modal>

按上述事例,即可实现简易拖拽,实际场景可以不是弹窗,任何元素都可以