Antd Modal 拖拽实现

834 阅读1分钟

一、插件实现

1.dragm

链接:www.npmjs.com/package/dra…

下载量:898

安装插件:cnpm i dragm

代码实现:

1.封装组件

import React from 'react';
import DragM from 'dragm';

export default class ModalDrag extends React.Component {
    updateTransform = transformStr => {
        this.modalDom.style.transform = transformStr;
    };
    componentDidMount() {
        this.modalDom = document.getElementsByClassName(
            'ant-modal-wrap', // modal的class是ant-modal-wrap
        )[0];
    }
    render() {
        const { title } = this.props;
        return (
            <DragM updateTransform={this.updateTransform}>
                <div>{title}</div>
            </DragM>
        );
    }
}

2.Modal中引用组件

import React from 'react';
import { Modal } from 'antd';
import ModalDrag from '@/components/ModalDrag';

export default class Demo extends React.Component {
    render(){
        const title = <ModalDrag title="标题” />
        return(
            <Modal
                title={title}
            >
            </Modal>
        )
    }
}

2.antd-draggable-modal

链接:www.npmjs.com/package/ant…

下载量:126

安装插件:cnpm i antd-draggable-modal

代码实现:

import React, { PureComponent } from 'react';
import { Button } from 'antd';
import AntdDraggableModal from 'antd-draggable-modal';

class Test extends PureComponent {
  state = {
    visible: false,
  }
 
  handleVisible = visible => {
    this.setState({
      visible,
    });
  }
 
  handleOk = () => {
    this.handleVisible(false);
  }
 
  handleCancel = () => {
    this.handleVisible(false);
  }

  render() {
    return (
        <Button onClick={() => this.handleVisible(true)}>打开弹窗</Button>
 
        {this.state.visible && (
          <AntdDraggableModal
            title="Basic Modal"
            visible={this.state.visible}
            onOk={this.handleOk}
            onCancel={this.handleCancel}
          >
            <p>Some contents...</p>
            <p>Some contents...</p>
            <p>Some contents...</p>
          </AntdDraggableModal>
        )}
    );
  }
}

export default Test;
  

\

二、封装组件

代码:

import type { MouseEvent } from 'react';
import  { Component } from 'react';
import type { ModalProps } from 'antd/lib/modal';
import { Modal } from 'antd';
import 'antd/es/modal/style/index.css';

export default class AntDraggableModal extends Component<ModalProps> {
    private simpleClass: string;
    private header: any;
    private contain: any;
    private modalContent: any;

    private mouseDownX: number = 0;
    private mouseDownY: number = 0;
    private deltaX: number = 0;
    private deltaY: number = 0;
    private sumX: number = 0;
    private sumY: number = 0;
    private offsetLeft: number = 0;
    private offsetTop: number = 0;

    constructor(props: ModalProps) {
        super(props);
        this.simpleClass = Math.random().toString(36).substring(2);
    }

    handleMove = (event: any) => {
        const deltaX = event.pageX - this.mouseDownX;
        const deltaY = event.pageY - this.mouseDownY;
        this.deltaX = deltaX;
        this.deltaY = deltaY;
        let tranX = deltaX + this.sumX;
        let tranY = deltaY + this.sumY;
        // 左侧
        if (tranX < -this.offsetLeft) {
            tranX = -this.offsetLeft;
        }
        // 右侧
        const offsetRight =
            document.body.clientWidth -
            this.modalContent.parentElement.offsetWidth -
            this.offsetLeft;
        if (tranX > offsetRight) {
            tranX = offsetRight;
        }
        // 上侧
        if (tranY < -this.offsetTop) {
            tranY = -this.offsetTop;
        }
        // 下侧
        const offsetBottom =
            document.body.clientHeight -
            this.modalContent.parentElement.offsetHeight -
            this.offsetTop;
        if (tranY > offsetBottom) {
            tranY = offsetBottom;
        }
        this.modalContent.style.transform = `translate(${tranX}px, ${tranY}px)`;
    };

    initialEvent = (visible: boolean) => {
        const { title } = this.props;
        if (title && visible) {
            setTimeout(() => {
                window.removeEventListener('mouseup', this.removeUp, false);

                this.contain = document.getElementsByClassName(this.simpleClass)[0];
                this.header = this.contain.getElementsByClassName('ant-modal-header')[0];
                this.modalContent = this.contain.getElementsByClassName('ant-modal-content')[0];
                this.offsetLeft = this.modalContent.parentElement.offsetLeft;
                this.offsetTop = this.modalContent.parentElement.offsetTop;
                this.header.style.cursor = 'all-scroll';
                this.header.onmousedown = (e: MouseEvent<HTMLDivElement>) => {
                    this.mouseDownX = e.pageX;
                    this.mouseDownY = e.pageY;
                    document.body.onselectstart = () => false;
                    window.addEventListener('mousemove', this.handleMove, false);
                };
                window.addEventListener('mouseup', this.removeUp, false);
            }, 0);
        }
    };

    removeMove = () => {
        window.removeEventListener('mousemove', this.handleMove, false);
    };

    removeUp = () => {
        // document.body.onselectstart = () => true;
        this.sumX += this.deltaX;
        this.sumY += this.deltaY;
        this.deltaX = 0;
        this.deltaY = 0;
        if (this.sumX < -this.offsetLeft) {
            this.sumX = -this.offsetLeft;
        }
        const offsetRight =
            document.body.clientWidth -
            this.modalContent.parentElement.offsetWidth -
            this.offsetLeft;
        if (this.sumX > offsetRight) {
            this.sumX = offsetRight;
        }
        // 上侧
        if (this.sumY < -this.offsetTop) {
            this.sumY = -this.offsetTop;
        }
        // 下侧
        const offsetBottom =
            document.body.clientHeight -
            this.modalContent.parentElement.offsetHeight -
            this.offsetTop;
        if (this.sumY > offsetBottom) {
            this.sumY = offsetBottom;
        }
        this.removeMove();
    };

    componentDidMount() {
        const { visible = false } = this.props;
        this.initialEvent(visible);
    }
    componentWillReceiveProps(newProps: any) {
        const { visible } = this.props;
        if (newProps.visible && !visible) {
            this.initialEvent(newProps.visible);
        }
        if (visible && !newProps.visible) {
            this.removeMove();
            window.removeEventListener('mouseup', this.removeUp, false);
        }
    }
    componentWillUnmount() {
        this.removeMove();
        window.removeEventListener('mouseup', this.removeUp, false);
    }

    render() {
        const { children, wrapClassName, ...other } = this.props;
        const wrapModalClassName = wrapClassName
            ? `${wrapClassName} ${this.simpleClass}`
            : `${this.simpleClass}`;
        return (
            <Modal {...other} wrapClassName={wrapModalClassName}>
                {children}
            </Modal>
        );
    }
}