需求
React在使用antd項目中需要使用Model彈框誊役,彈框展示(彈出時),需要可以拖拽移動彈框蛔垢,并且不能超過可視范圍击孩。
代碼
/* eslint-disable prefer-destructuring */
import type { MouseEvent } from 'react';
import React, { Component } from 'react';
import type { ModalProps } from 'antd/lib/modal';
// import AntdModal from 'antd/lib/modal';
/* 可以將model換成上方注釋的AntdModal ,將下方一行注釋,放出上方一行代碼啦桌,在使用Model的地方替換成AntdModal 。 */
/* 解釋:使用AntdModal 時及皂,按鈕是英文甫男,使用Model,是因為按鈕按現(xiàn)在有的語言環(huán)境展示的*/
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;
// 左側(cè)
if (tranX < -this.offsetLeft) {
tranX = -this.offsetLeft;
}
// 右側(cè)
const offsetRight =
document.body.clientWidth -
this.modalContent.parentElement.offsetWidth -
this.offsetLeft;
if (tranX > offsetRight) {
tranX = offsetRight;
}
// 上側(cè)
if (tranY < -this.offsetTop) {
tranY = -this.offsetTop;
}
// 下側(cè)
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;
}
// 上側(cè)
if (this.sumY < -this.offsetTop) {
this.sumY = -this.offsetTop;
}
// 下側(cè)
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>
);
}
}
展示效果
自行復(fù)制代碼去測試吧。
引用
本效果是借鑒 Ant-design Modal實現(xiàn)可以拖動的效果代碼修改得到的验烧。