思路:

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='啥也没有O_o' />
{
dragging &&
<div
                className='drag-mask'
                onMouseMove={this.handleMouseMove}
                onMouseUp={this.hanldeMouseUp}
               ></div>
}
</Modal>
</div>
)
}
}
.drag-mask{
position: fixed;
left:;
right:;
top:;
bottom:;
z-index:;
} .drag-target{
position: absolute;
left:;
right:;
top:;
bottom:;
cursor: move;
}

 注意:

现在Modal是可以拖动了,但是你可能会发现Modal中原本可以点击的子元素不能点了[○・`Д´・ ○] ~不要生气~这时给子元素设置定位position:relative,子元素就可以点击了。

因为.......同辈元素定位方式不同时,动态定位居上。即drag-target为absolute,它的兄弟元素是static,那么drag-target的层级就在兄弟元素们的上面。

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

ps:如果需要复用可以将其改写成高阶组件。

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

让Antd Modal变成可拖动弹窗的更多相关文章

  1. Antd Modal 可拖拽移动

    一 目标: 实现antd Modal 弹窗或者其他弹窗的点击标题进行拖拽的效果 二 准备及思录: 1.使用antd  Modal 组件,要想改变位置需要改变Modal style 的left 和top ...

  2. react 可拖拽改变位置和大小的弹窗

    一 目标 最近,项目上需要一个可以弹出一个可以移动位置和改变大小的窗口,来显示一下对当前页面的一个辅助内容 二 思路 1.之前写过一个antd modal的可移动弹窗但是毕竟不如自己写的更定制化,比如 ...

  3. JS编写简单的弹窗插件(含有demo和源码)

    最近项目做完了 事情不是很多,今天正好也在调休,所以趁着这个时间研究了一下简易的JS弹窗功能,当然网上这块插件非常多,本人也没有仔细看网上的插件源码 只是凭着日常使用过的弹窗插件有这么多功能 来实现自 ...

  4. dialog参数、方法以及事件

    参数(options) DOM方式初始化dialog的,推荐使用集合属性data-options定义参数,如果使用data属性定义参数,注意转换成对应的名称. 名称 类型 默认值 描述 id stri ...

  5. BJUI 转

    B-JUI 前端框架B-JUI(Bootstrap for DWZ)是一个富客户端框架,基于DWZ-jUI富客户端框架修改. 本文是B-JUI中文使用手册,包括使用示例代码,感兴趣的同学参考下. 概览 ...

  6. Bootstrap模态弹出框

    前面的话 在 Bootstrap 框架中把模态弹出框统一称为 Modal.这种弹出框效果在大多数 Web 网站的交互中都可见.比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作 ...

  7. 关于React中状态保存的研究

    在使用react搭配react-router做应用的时候,你可能遇到这样的问题,当我从第一个页面过渡到第二个页面,然后返回之后,发现之前的页面的状态全部不见了,即回到了初始的状态. 这点在页面存在多个 ...

  8. 移动端 -webkit-user-select:text; ios10 bug 解决方案

    移动端一般body的css.会设置 作用就不解释了: body{ height:100%;min-height:100%; font-family: "微软雅黑",'Helveti ...

  9. angularJS的插件使用

    $uibModal&&$uibModalInstance $uibModal和$uibModalInstance是一款angularJS的弹窗控件,github地址 http://an ...

随机推荐

  1. CentOs7 使用iptables开启关闭端口

    介绍 iptables命令是Linux上常用的防火墙软件,是netfilter项目的一部分 iptables文件设置路径:命令:vim /etc/sysconfig/iptables-config 注 ...

  2. Core Data 数据出现Fault

    I am mapping Json Data from Server using Restkit and I am Displaying those data by fetching from db. ...

  3. 2019-8-31-PowerShell-通过-WMI-获取系统信息

    title author date CreateTime categories PowerShell 通过 WMI 获取系统信息 lindexi 2019-08-31 16:55:58 +0800 2 ...

  4. jieba分词流程及部分源码解读(一)

    首先我们来看一下jieba分词的流程图: 结巴中文分词简介 1)支持三种分词模式: 精确模式:将句子最精确的分开,适合文本分析 全模式:句子中所有可以成词的词语都扫描出来,速度快,不能解决歧义 搜索引 ...

  5. meta标签、常用的文字类标签及其区别

    常用的文字类基本标签 段落:p标题文字 :h1~h6超链接:a,必须属性href,后跟跳转地址图片:img,必须属性src,后跟图片地址字体斜体:em.i 文字加粗:b.strong文字下划线:u文字 ...

  6. Java实现Windows锁屏

    public class LockWindows { public static void main(String [] args) throws Exception { Runtime.getRun ...

  7. servicemix 实例 -- 参考open source ESBs in action这本书

    1. 项目结构 2. bean服务处理单元 1)Person类 package esb.chapter3; import java.io.StringWriter; import javax.xml. ...

  8. python3在pycharm中为什么导入random模块不能用? TypeError: 'module' object is not callable

    新手学python求大神指导,也用sys导入了random.py的路径,仍然不行. 刚刚排错貌似找到了问题的原因...那是因为我在pycharm中新建的python文件名就是random,所以当前目录 ...

  9. 定位问题 vue+element-ui+easyui(兼容性)

    项目背景:靠近浏览器窗口的各个方向(左上.下.左.右)都有不同的模态框悬浮于窗口,这里针对于底部组件定位的选择(主要针对pc端垂直方向上的定位) 1.百分比:easyui的window窗口定位方式:设 ...

  10. Vue基础练习之Todo List

    <body> <div id = "app"> <input type="text" v-model="inputVal ...