思路:

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. ORA错误查询手册

    ORA-00910: 指定した長さがデータ型に対して長すぎます 原因: データ型CHARまたはRAWに対して指定した長さは.2000を超える値または4000を超える値であるため無効です. 処置: 指定 ...

  2. Getting started with the basics of programming exercises_5

    1.编写函数,把由十六进制数字组成的字符串转换为对应的整型值 编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型值.字符串中允许包含的数字包括:0~9 ...

  3. jquery实现单击div切换背景

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. BERT大火却不懂Transformer?读这一篇就够了 原版 可视化机器学习 可视化神经网络 可视化深度学习

    https://jalammar.github.io/illustrated-transformer/ The Illustrated Transformer Discussions: Hacker ...

  5. ORACLE内部操作

    当执行查询时,ORACLE采用了内部的操作. 下表显示了几种重要的内部操作. ORACLE Clause 内部操作 ORDER BY SORT ORDER BY UNION UNION-ALL MIN ...

  6. oracle 用IN来替换OR

    下面的查询可以被更有效率的语句替换: 低效: SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR     LOC_ID = 20 OR     LOC_ID = 3 ...

  7. JS划重点——类和对象的不正经阐述

    JS划重点--类和对象的不正经阐述 /在JS 类里面函数也是一个对象,那么要创建一个对象就需要一个类,这个类可以由这个对牛逼的对象-函数来实现/ /首先是普罗大众都会的 工厂模式来创建一类/ func ...

  8. Activiti学习之spring boot 与activiti整合

    声明:本文是springboot2.0的多项目构建,springboot2.0和spingboot1.5的配置是有出入的,构建项目之前请规范您的springboot版本,选择2.0以上. 一.在IDE ...

  9. Native memory allocation (mmap) failed to map xxx bytes for committing reserved memory

    遇到问题 在服务器上运行 nexus 出现Native memory allocation (mmap) failed to map 838860800 bytes for committing re ...

  10. Python--day61--安装Django,Django项目的启动和设置运行端口和关闭运行端口

    0,安装Django 1,Django项目的启动 2,设置运行端口和关闭运行端口