react-draggable 前端可拖动容器的使用探索

3,666 阅读5分钟

关于react-draggable的使用总结

最近需要实现一个既支持PC端又支持H5端的悬浮可拖动按钮,自己实现的在页面渲染上总是感觉会延迟渲染,导致出现bug,网上很多文章,尝试过后总是会有一些小问题存在;

后来发现了react-draggable组件库,以下是我的一个使用探索;

参考资源: npm官方文档地址:

最简单的使用就是:

<Draggable>
  <div className={styles.btnStyle}>
    拖拽按钮
  </div>
</Draggable>

关于悬浮直接通过css样式定位去写就可以,这里简单举个例子:

.btnStyle
    position: fixed
    cursor: pointer
    top: 72px
    right: 20px
    height: 48px
    width: 48px

这是最简单的demo,可以先这么尝试以下,你就会发现,可拖拽的一个元素就实现了;

然后就根据自己的需求查看官方文档进行尝试吧!

onStart,onDrag,onStop

首先我想要的是一个可点击的按钮嘛,如果是拖动的操作的话,不会触发点击事件,如果没有拖动的话,偏要出发点击事件,所以便从官方文档提供的这三个事件下手啦;

  • onStart: 开始拖动的时候调用的事件;
  • onDrag: 拖动的时候调用的事件;
  • onStop: 拖动结束的时候调用的事件;

所以我设置了一个判断是否可点击的状态值,如果开始拖动,就将这个状态置为TRUE,但是如果触发了onDrag事件,进行了拖动,就将这个值置为FALSE,然后在onStop事件中进行判断,是否可以触发click事件;

实现思路是这样的,下面是代码的实现:

import React, { useState } from 'react';
import Draggable from 'react-draggable';
import styles from './style.module.styl';

const DragBtnComponent = (props) => {
  // 是否可点击
  const [isClick, setIsClick] = useState(false);

  const handleStart = () => {
    console.log('拖动开始');
    setIsClick(true);
  };

  const handleDrag = () => {
    console.log('拖动ing');
    setIsClick(false);
  };

  const handleEnd = () => {
    console.log('拖动结束');
    if (isClick) {
      console.log('可点击');
    }
  };
  return (
    <Draggable onStart={handleStart} onDrag={handleDrag} onStop={handleEnd}>
      <div className={styles.btn}>
        <span>按钮</span>
      </div>
    </Draggable>
  );
};

export default DragBtnComponent;

这样一个简单的悬浮可拖动的按钮就实现了;

bounds

官方文档对该属性的解释(百度翻译的):

bounds: 指定移动的边界值;可以设置的值:

  • parent:限制节点的offsetParent内的移动(位置为相对或绝对的最近节点);
  • 选择器:限制目标节点内的移动;
  • 具有“左、上、右和下”属性的对象:指示了可拖动设备在每个方向上可以移动的距离;

在拖动的过程中,为了避免将按钮拖到屏幕外边,所以设置该属性,执行拖动按钮的活动范围;在这里我想要的效果是在整个屏幕内部拖动,所以采用最后一种方式,设定一个具有上下左右属性的对象;

这里记录一个我的误解:我刚开始直接这么设定的:bounds:{ left: 0, top: 0, right: 0, bottom: 0 };结果发现不能拖动了,然后又看了下API,发现这四个值指的是在该方向上的移动距离,不要像我这样粗心哦!

在观察DOM节点的时候发现,这个库是通过css转换来实现拖动的,即 transform: translate(0px, 0px);,而不是像我之前一样通过改动它的位置定位;

我们一般都会将按钮的初始位置放在页面的一个角落里,这里我是放在右上角,所以直接指定它向左和向下移动的距离,另外两个方向置为0就OK了;

还有一点就是结合translate(0px, 0px)函数,向X轴平移,填正数往右平移,填负数,往左平移;向Y轴平移,填正数往下平移,填负数,往上平移;

const left = target.offsetLeft - 20;
const bottom = document.documentElement.clientHeight - target.offsetTop - target.offsetWidth;
setBounds({ right: 0, top: 0, left: -left, bottom });

其他这次未用到的属性

  1. allowAnyClick: 如果设置为“true”,将允许在非左键单击时拖动。

  2. axis: 指定拖动的方向,可以设置的值为(

    • both: 默认值,水平垂直方向都可以拖动;
    • x: 只能在水平方向拖动;
    • y: 只能在垂直方向拖动;
    • none: 不可拖动; );
  3. cancel: 这个没怎么看懂,😂; 以下这三个属于一挂的:指定拖动元素的样式

  4. defaultClassName: 默认值:'react-draggable'

  5. defaultClassNameDragging: 默认值:'react-draggable-dragging'

  6. defaultClassNameDragged: 默认值:'react-draggable-dragged'

  7. defaultPosition: 拖动元素的默认位置,一般很少使用;

  8. disabled: 如果设置为TRUE,将不触发拖动的处理,我理解的是拖动的开关;

  9. grid: 官方给的解释是指定应该移动的x和y的值;

  10. handle: 指定初始拖动的选择器;

  11. offsetParent: 如果需要,您可以为阻力计算提供自己的offsetParent。默认情况下,我们使用DragTable的offsetParent。这对于具有奇数显示类型或浮动的元素很有用。

  12. onMouseDown: 每当用户按下鼠标时调用。不管句柄或禁用状态。

  13. nodeRef:nodeRef也可以在<DraggableCore>上找到。

  14. position: 将拖动元素变成受控的,自己指定位置;

  15. positionOffset: 初始位置的一个位置偏移量;

  16. scale: 指定要拖动此元素的画布的比例。这允许例如,当您通过放大或缩小时,您需要获得正确的拖动增量此元素父元素中的变换或矩阵。

总结

主要是关于react-draggable使用的一个探索,有时间的话还要继续研究一下这次没使用到的属性,还有看看源码,对比反思一下自己实现的,产生bug的原因和解决方案;