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


    一 目标

     最近,项目上需要一个可以弹出一个可以移动位置和改变大小的窗口,来显示一下对当前页面的一个辅助内容

    二 思路

     1.之前写过一个antd modal的可移动弹窗但是毕竟不如自己写的更定制化,比如不需要显示遮罩层,但是移动的思想一致都是鼠标的按下和抬起事件以及坐标位置来计算改变弹窗位置.

     2.窗口的的小调节可以用css的resize属性,当然也可以自己写一个指定边框拖拽调整大小的功能,后期可能会更新

    三 代码内容

     index.js

     1 import React, { Component } from 'react'
     2 import { Icon } from 'antd'
     3 import style from './index.less'
     4 class PopContainer extends Component {
     5     constructor(props) {
     6         super(props);
     7         this.windowH = document.body.clientHeight;
     8         this.windowW = document.body.clientWidth;
     9         this.state = {
    10             styleTop: 20,
    11             styleLeft: 10,
    12             styleHeight: props.height || this.windowH * 0.85,
    13             styleWidth: props.width || this.windowW * 0.45,
    14         }
    15     }
    16   //计算是否超出屏幕
    17     InWindow = (left, top, startPosX, startPosY) => {
    18         let H = document.body.clientHeight;
    19         let W = document.body.clientWidth;
    20         if ((left < 20 && startPosX > left) || (left > W - 20 && startPosX < left) ||
    21             (top < 20 && startPosY > top) || ((top > H - 20 && startPosY < top))) {
    22             return false
    23         }
    24         return true
    25     }
    26     onMouseDown = e => {
    27         e.preventDefault();
    28         let startPosX = e.clientX;
    29         let startPosY = e.clientY;
    30         const { styleLeft, styleTop } = this.state;
    31         document.body.onmousemove = e => {
    32             let left = e.clientX - startPosX + styleLeft;
    33             let top = e.clientY - startPosY + styleTop;
    34             if (this.InWindow(e.clientX, e.clientY, startPosX, startPosY)) {
    35                 this.setState({
    36                     styleLeft: left,
    37                     styleTop: top,
    38                 })
    39             } else {
    40                 document.body.onmousemove = null;
    41                 document.body.onmouseup = null;
    42             }
    43         };
    44         document.body.onmouseup = function () {
    45             document.body.onmousemove = null;
    46             document.body.onmouseup = null;
    47         };
    48     };
    49     render() {
    50         const { styleLeft, styleTop, styleHeight, styleWidth } = this.state
    51         const { visible, onClose, children, bodyStyle, title } = this.props
    52         return <div className={style.popContainer} style={{
    53             display: visible ? "block" : "none",
    54             left: styleLeft + 'px', top: styleTop + 'px',
    55         }}>
    56             <div className={style.header}>
    57                 <div className={style.title} onMouseDown={this.onMouseDown} >{title}</div>
    58                 <span className={style.close} onClick={onClose}><Icon type="close" /></span>
    59             </div>
    60             <div className={style.content} style={{ ...bodyStyle }}>
    61                 {children}
    62             </div>
    63             <div className={style.footer}>
    64             </div>
    65         </div>
    66 
    67     }
    68 }
    69 
    70 export default PopContainer;

    index.less

    .popContainer {
        position        : fixed;
        width           : 50vw;
        height          : 80vh;
        background-color: white;
        z-index         : 200;
        box-shadow      : 0px 4px 12px 0px rgba(0, 0, 0, 0.45);
        border-radius   : 4px;
        resize          : both;
        overflow        : auto;
        min-width       : 200px;
        min-height      : 60px;
    
        .header {
            padding      : 16px 24px;
            color        : rgba(0, 0, 0, 0.65);
            border-bottom: 1px solid #e8e8e8;
            border-radius: 4px 4px 0 0;
    
            .close {
                position   : absolute;
                top        : 0;
                right      : 0;
                cursor     : pointer;
                width      : 56px;
                height     : 56px;
                font-size  : 16px;
                line-height: 56px;
                text-align : center;
                color      : rgba(0, 0, 0, 0.45);
    
                &:hover {
                    color: black;
                }
            }
    
            .title {
                cursor     : move;
                color      : rgba(0, 0, 0, 0.85);
                font-weight: 500;
                font-size  : 16px;
                line-height: 22px;
            }
        }
    
        .content {
            height    : calc(100% - 70px);
            overflow-y: scroll;
            padding   : 24px;
        }
    
    }

    引用的文件

     import PopContainer from './PopContainer/index.js'
      ...
     onShow = ()=>{
         this.setState({visible:true})
     }
     onClose=()=>{
        this.setState({visible:false})
     }
     render(){
          <Button  onClick={this.onShow}>打开弹窗</Button>
          <PopContainer  visible={this.state.visible} onClose={this.onClose} title="标题" >
         内容  
        <PopContainer /> 
    }
  • 相关阅读:
    Mac基本操作记录
    flutter vscode+第三方安卓模拟器
    git一些基本操作
    获取点击元素的绝对位置
    windows下提交前检测操作
    VGG网络学习
    MySQL数据库中文乱码
    配深度学习环境中的小tips(tensorflow+anaconda+keras+cuda)
    Docker安装指定的anaconda
    yolov1阅读
  • 原文地址:https://www.cnblogs.com/ITCoNan/p/13718799.html
Copyright © 2020-2023  润新知