react+antd实现Modal弹窗拖拽功能

1、版本

"antd": "^5.1.6",

2、新建draggerModal.tsx文件,将下方代码复制进去

/* eslint-disable prefer-destructuring */
import type { MouseEvent } from "react";
import React, { Component } from "react";
import type { ModalProps } from "antd/lib/modal";
import { Modal } from "antd";
import "antd/es/modal/style/index"

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;
    // 左侧
    if (tranX < -this.offsetLeft) {
      tranX = -this.offsetLeft;
    }
    // 右侧
    const offsetRight =
      document.body.clientWidth -
      this.modalContent.parentElement.offsetWidth -
      this.offsetLeft;
    if (tranX > offsetRight) {
      tranX = offsetRight;
    }
    // 上侧
    if (tranY < -this.offsetTop) {
      tranY = -this.offsetTop;
    }
    // 下侧
    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 = (open: boolean) => {
    const { title } = this.props;
    if (open && title) {
      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.style.color = "green";
        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;
    }
    // 上侧
    if (this.sumY < -this.offsetTop) {
      this.sumY = -this.offsetTop;
    }
    // 下侧
    const offsetBottom =
      document.body.clientHeight -
      this.modalContent.parentElement.offsetHeight -
      this.offsetTop;
    if (this.sumY > offsetBottom) {
      this.sumY = offsetBottom;
    }
    this.removeMove();
  };

  componentDidMount() {
    const { open = false } = this.props;
    this.initialEvent(open);
  }
  componentWillReceiveProps(newProps: any) {
    const { open } = this.props;
    if (newProps.open && !open) {
      this.initialEvent(newProps.open);
    }
    if (open && !newProps.open) {
      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>
    );
  }
}

3、引入并使用

import AntDraggableModal from "/@/plugins/commonPlugins/draggerModal";

                .......
    
    <AntDraggableModal
          open={visiable}
          onOk={() => {
            setVisiable(false);
          }}
          onCancel={() => {
            setVisiable(false);
          }}
          width={1380}
          title={data.cellName}
          destroyOnClose={true}
          footer={null}
          closable={true}
          centered={true}
          key={data?.cellId}
          closeIcon={<CloseOutlined style={{ color: "#fff" }} />}
          bodyStyle={{ backgroundColor: "rgb(17, 17, 41)" }}
          className={modalStyle.modal}
        >
          {visiable && <aModal data={prop} visiable={visiable} />}
    </AntDraggableModal>

over~ 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例代码: 首先安装所需依赖: ```bash npm install react antd axios --save ``` 然后创建一个 `Login` 组件和一个 `Register` 组件,分别用于登录和注册的页面展示。其中,我们使用了 `Form` 和 `Input` 组件来实现表单输入,以及 `Button` 组件来实现按钮的功能。 ```jsx // Login.jsx import React, { useState } from 'react'; import { Form, Input, Button, message } from 'antd'; import axios from 'axios'; const Login = () => { const [loading, setLoading] = useState(false); const onFinish = async (values) => { setLoading(true); try { const response = await axios.post('/api/login', values); message.success(response.data.message); setLoading(false); } catch (error) { message.error(error.response.data.message); setLoading(false); } }; return ( <Form name="login" onFinish={onFinish}> <Form.Item name="email" rules={[{ required: true, message: 'Please input your email!' }]} > <Input placeholder="Email" /> </Form.Item> <Form.Item name="password" rules={[{ required: true, message: 'Please input your password!' }]} > <Input.Password placeholder="Password" /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit" loading={loading}> Login </Button> </Form.Item> </Form> ); }; export default Login; ``` ```jsx // Register.jsx import React, { useState } from 'react'; import { Form, Input, Button, message } from 'antd'; import axios from 'axios'; const Register = () => { const [loading, setLoading] = useState(false); const onFinish = async (values) => { setLoading(true); try { const response = await axios.post('/api/register', values); message.success(response.data.message); setLoading(false); } catch (error) { message.error(error.response.data.message); setLoading(false); } }; return ( <Form name="register" onFinish={onFinish}> <Form.Item name="name" rules={[{ required: true, message: 'Please input your name!' }]} > <Input placeholder="Name" /> </Form.Item> <Form.Item name="email" rules={[{ required: true, message: 'Please input your email!' }]} > <Input placeholder="Email" /> </Form.Item> <Form.Item name="password" rules={[{ required: true, message: 'Please input your password!' }]} > <Input.Password placeholder="Password" /> </Form.Item> <Form.Item name="confirmPassword" rules={[ { required: true, message: 'Please confirm your password!' }, ({ getFieldValue }) => ({ validator(_, value) { if (!value || getFieldValue('password') === value) { return Promise.resolve(); } return Promise.reject(new Error('The two passwords do not match!')); }, }), ]} > <Input.Password placeholder="Confirm Password" /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit" loading={loading}> Register </Button> </Form.Item> </Form> ); }; export default Register; ``` 在这里我们使用了 `axios` 来发送登录和注册的请求,需要注意的是,这里的请求地址是 `/api/login` 和 `/api/register`,而不是实际的后端接口地址,根据实际情况进行修改。 最后在需要展示登录和注册功能的页面中引入 `Login` 和 `Register` 组件即可。 ```jsx import React from 'react'; import Login from './Login'; import Register from './Register'; const LoginPage = () => { return ( <div> <h1>Login</h1> <Login /> <hr /> <h1>Register</h1> <Register /> </div> ); }; export default LoginPage; ``` 以上就是一个简单的使用 `react` 和 `antd` 实现登录和注册功能的示例代码,希望对你有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值