使用react-draggable和react-resizable实现Ant Design Modal的拖动和拖拽改变宽度

使用react-draggable和react-resizable实现Ant Design Modal的拖动和拖拽改变宽度

需求

Ant Design 提供的Modal是不支持拖动还有侧边拖拽改变宽度的,基于这一点我们需要自定义一个我们自己的Modal组件,来实现拖动和拖拽改变宽度。

其中会用到的技术有:使用react-draggable来实现modal的拖动,使用react-resizable来实现拖拽改变宽度。

实现

首先实现拖动这个比较简单,直接引入react-draggable,然后使用<Draggable>包裹一下就可以了,网上案例很多,不具体讲。 唯一比较特别的是,如果你直接包裹在<Modal>外面是无法实现拖拽的,而是要在<Modal>中的modalRender属性中进行<Draggable>的包裹。还有一点需要注意的是拖动的时候需要设置一下不能超出当前可视窗口。

实现拖拽改变宽度也不难,也是引入react-resizable,然后用<Resizable>包裹一下就可以了,但是需要设置width,并且是number类型。还有一点需要注意的是,需要设置一下modal最小的宽度,防止拖拽改变宽度太小导致modal里面的内容样式错乱。

参考代码

import Draggable, {DraggableBounds, DraggableData, DraggableEvent} from 'react-draggable'
import {Modal, ModalProps} from "antd";
import React, {useLayoutEffect, useRef, useState} from "react";
import './index.css';
import {Resizable} from "react-resizable";

interface DraggableModalProps extends ModalProps {
  modalMinWidth?: number,
  width?: number
}

const DraggableModal: React.FC<DraggableModalProps> = (props: any) => {

  const [bound, setBound] = useState<DraggableBounds>({left: 0, top: 0, bottom: 0, right: 0})
  const modalRef = useRef();
  const draggableRef = useRef();
  const {children, ...other} = props;
  const [resizableWidth, setResizableWidth] = useState<number>(props.width || 0);
  const resizeableSpaceWidth = 5;
  const defaultMinSize = 400;
  const onStart = (event: DraggableEvent, draggableData: DraggableData) => {
    const {clientWidth, clientHeight} = window?.document?.documentElement;
    const targetRect = (draggableRef?.current as any)?.getBoundingClientRect();
    setBound({
      left: -targetRect?.left + draggableData?.x,
      right: clientWidth - (targetRect?.right - draggableData?.x) - resizeableSpaceWidth,
      top: -targetRect?.top + draggableData?.y,
      bottom: clientHeight - (targetRect?.bottom - draggableData?.y)
    })
  };

  useLayoutEffect(() => {
    setResizableWidth(props.width || defaultMinSize);
  }, [props.width])

  const onResize = (e: React.SyntheticEvent<Element, Event>, {size}: any) => {
    if (size.width < (props.modalMinWidth || defaultMinSize)) {
      setResizableWidth(props.modalMinWidth || defaultMinSize);
    } else {
      setResizableWidth(size.width);
    }
  }


  return (
    <Modal {...other} ref={modalRef}
           width={resizableWidth}
           modalRender={modal => (
             <Draggable handle={'.ant-modal-header'}
                        bounds={bound}
                        onStart={(event, uiData) => onStart(event, uiData)}>
               {/* @ts-ignore*/}
               <div ref={draggableRef} className={'draggable-modal'}>
                 <Resizable width={resizableWidth} height={0}
                            onResize={onResize}>
                   {modal}
                 </Resizable>

               </div>
             </Draggable>
           )}>
      {children}
    </Modal>

  );
}

export default DraggableModal;

参考

React Draggable 实现拖拽 - 最详细中文教程 - 卡拉云

React 拖拽改变大小,react-resizable 属性详解

antd modal拖拽,自定义modal拖拽react-draggable

react-modal-draggable

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值