antd Design Model彈框可拖拽(可移動)操作

需求

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)可以拖動的效果代碼修改得到的验烧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末板驳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子碍拆,更是在濱河造成了極大的恐慌若治,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件感混,死亡現(xiàn)場離奇詭異端幼,居然都是意外死亡,警方通過查閱死者的電腦和手機弧满,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門婆跑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人庭呜,你說我怎么就攤上這事滑进。” “怎么了募谎?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵扶关,是天一觀的道長。 經(jīng)常有香客問我数冬,道長节槐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任拐纱,我火速辦了婚禮疯淫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘戳玫。我一直安慰自己熙掺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布咕宿。 她就那樣靜靜地躺著币绩,像睡著了一般蜡秽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缆镣,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天芽突,我揣著相機與錄音,去河邊找鬼董瞻。 笑死寞蚌,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的钠糊。 我是一名探鬼主播挟秤,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抄伍!你這毒婦竟也來了艘刚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤截珍,失蹤者是張志新(化名)和其女友劉穎攀甚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岗喉,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡秋度,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钱床。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片静陈。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖诞丽,靈堂內(nèi)的尸體忽然破棺而出鲸拥,到底是詐尸還是另有隱情,我是刑警寧澤僧免,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布刑赶,位于F島的核電站,受9級特大地震影響懂衩,放射性物質(zhì)發(fā)生泄漏撞叨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一浊洞、第九天 我趴在偏房一處隱蔽的房頂上張望牵敷。 院中可真熱鬧,春花似錦法希、人聲如沸枷餐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毛肋。三九已至怨咪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間润匙,已是汗流浹背诗眨。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留孕讳,地道東北人匠楚。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像厂财,于是被迫代替她去往敵國和親芋簿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容