zoukankan      html  css  js  c++  java
  • 让Antd 的Modal 可以拖动

    需求:

    为了提升交互体验,满足用户“不关弹窗还能看弹窗下的页面”的需求,需要弹窗可以随意拖动位置。

    原本ant design的弹窗没有拖拽功能,但是为了保留原本功能样式,我们要拓展一下这个Modal组件。

    思路:

    1、首先需要两个DIV,一个是和视口一样大的drag-mask,绑定mouseMove事件和mouseUp事件,用来作为拖拽参照;另一个是和Modal一样大的drag-target,绑定mouseDown事件。

    2、已知Modal的样式.ant-modal{position:relative;top:100px;left:0px;},可见通过更改top、left我们将可以改变Modal位置。

    3、mouseDown事件时,显示drag-mask,并记录坐标(preX,preY);

    4、mouseMove事件时,Modal的新位置=Modal的原位置+移动距离:

      left2 = left1 + (pageX-preX);

      top2 = top1 + (pageY-preY);

    图示:由灰色位置移动到蓝色位置,箭头表示拖拽轨迹

    5、mouseMove到窗口边缘时不能继续拖动,误差10px,也就是说拖拽时鼠标移动到靠近窗口边缘10px时就自动mouseUp(防止拖出视口);

    代码:

    import React, { Component } from 'react';
    import ReactDom from 'react-dom';
    import { Modal, Empty } from 'antd';
    import './dragable.less';
    
    export default class DragableModal extends Component { 
        constructor(props) { 
            super(props);
            this.state = {
                visible:false,
                dragging: false,
                preX: 0,
                preY: 0,
                styleTop: 100,
                styleLeft:0,
            }
            this.windowH = document.body.clientHeight;
            this.windowW = document.body.clientWidth;
        }
    
        show = () => { 
            this.setState({
                visible: true,
                dragging: false,
                preX: 0,
                preY: 0,
                styleTop: 100,
                styleLeft:0,
            })
        }
    
        hide = () => { 
            this.setState({
                visible:false
            })
        }
    
        isOverWindow = (moveX, moveY) => { 
            const er = 10;
            if (moveX < er) return true;
            if (moveX > (this.windowW - er)) return true;
            if (moveY < er) return true;
            if (moveY > (this.windowH - er)) return true;
            return false;
        }
    
        handleMoseDown=(evt)=>{
            this.setSate({
                dragging:true,
                preX:evt.pageX,
                preY:evt.pageY,
            })    
        }
    
        handleMouseMove = (evt) => {
            if (this.isOverWindow) { 
                this.hanldeMouseUp();
                return;
            }
            const {preX,preY,styleLeft,styleTop} = this.state;
            const left = styleLeft + (evt.pageX-preX);
            const top = styleTop + (evt.pageY-preY);
            this.setState({
                preX:evt.pageX,
                preY:evt.pageY,
                styleLeft:left,
                styleTop:top,
            })   
        }
    
        hanldeMouseUp = () => { 
            this.setState({dragging:false})
        }
    
        render() { 
            const { visible, dragging, styleLeft, styleTop } = this.state;
            const style = { left: styleLeft, top: styleTop }
            
            return (
                <div>
                    <Modal
                        title='拖拽测试'
                        visible={visible}
                        onCancel={this.hide}
                        style={style}
                        maskClosable={false}
                    >
                        <div className='drag-target' onMouseDown={this.handleMouseDown}></div>
                        <Empty description='没啥内容' />
                        {
                            dragging &&
                            <div 
                    className='drag-mask'
                    onMouseMove={this.handleMouseMove}
                    onMouseUp={this.hanldeMouseUp}
                   ></div> } </Modal> </div> ) } }
    .drag-mask{
        position: fixed;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        z-index: 1001;
    }
    
    .drag-target{
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        cursor: move;
    }

     PS:

    Modal是可以拖动了,但是我发现Modal中原本可以点击的a标签不能点了[○・`Д´・ ○] ~

    淡定淡定……原来~drag-target是绝对定位absolute,它的兄弟元素a还是普通文档流,那么drag-target的层级就在兄弟元素们的上面。

    我们知道同辈元素定位方式相同,且无z-index设置时,html靠后者层级居上。所以只要给drag-target后面的兄弟元素设置为relative,那么它们就不会被drag-target遮着了。

    给a设置position:relative,a又可以点击了

    pps:因为暂时没有环境,所以上面的代码demo手敲完也没运行,如有问题欢迎指正讨论。

  • 相关阅读:
    HDU2473 Junk-Mail Filter 【可删除的并查集】
    NOI2001 食物链【扩展域并查集】*
    POJ1733 Parity game 【扩展域并查集】*
    Codeforces 9D How many trees? 【计数类DP】
    Codeforces 28C Bath Queue 【计数类DP】*
    Codeforces 280C Game on tree【概率DP】
    Codeforces 914H Ember and Storm's Tree Game 【DP】*
    Codeforces 1027E Inverse Coloring 【DP】
    BZOJ3673 可持久化并查集 by zky 【主席树】
    BZOJ4561 JLoi2016 圆的异或并 【扫描线】【set】*
  • 原文地址:https://www.cnblogs.com/JerryD/p/12161628.html
Copyright © 2011-2022 走看看