react+antd model框的全屏及拖拽(个人配置)

在做项目的时候,碰到这样的一个问题,那就是model框需要做成如下样式:

那是不是直接去改样式就行了呢

改了一些样式,但是也遇到很多问题,全屏是css样式去调整,那么我把拖拽,全屏代码放到下边:

      1.封装model框

import {useState, useRef, useEffect, useCallback} from "react";
import { Modal, ModalProps } from "antd";
import Draggable from "react-draggable";
import styles from "./desModel.less";
import {CloseOutlined} from "@ant-design/icons";
import {useWatch} from "antd/es/form/Form";
import provider from "react-redux/src/components/Provider";

//ModalProps 继承官方modal属性,使用时属性提示
interface WebModal extends ModalProps {
  openDrag?: boolean; //是否开启弹窗的拖拽
  dragHandle?: boolean; //开启头部拖拽或者弹窗拖拽
}
const WebReactModal= ({
                        openDrag = false,
                        dragHandle = false,
                        ...props
                      }: WebModal) => {
  const [position,setPosition]=useState({ x: 0, y: 0 })
  const [bounds, setBounds] = useState({
    left: 0,
    top: 0,
    bottom: 0,
    right: 0,
  }); //存储模态框的边界值
  const [ji  , setJi]=useState("");
  const draggleRef = useRef<any>();
  //模态框开始移动计算莫太框的位置和边界
  const onStart = (event, uiData) => {
    const { clientWidth, clientHeight } = window?.document?.documentElement;
    //获取到模态框的位置,从而计算可以动的边界值
    const targetRect = draggleRef?.current?.getBoundingClientRect();
    setBounds({
      left: -targetRect?.left + uiData.x,
      right: clientWidth - (targetRect?.right - uiData.x),
      top: -targetRect?.top + uiData.y,
      bottom: clientHeight - (targetRect?.bottom - uiData.y),
    });
  };
  //因为设置了初始位置,所以添加模态框移动时更新位置
  const onDrag = (e, data) => {
    const { x, y } = data;
    setPosition({ x, y });
  };

  //监听模态框的关闭,恢复到初始的位置
  useEffect(() => {
    if (!props.open) {
      setPosition({ x: 0, y: 0 });
    }
    //这里监听我的状态,不管拖拽到哪,我点击全屏时,回归原位
    if(props?.flagModels === true){
      setPosition({ x: 0, y: 0 });
    }
  }, [props?.open , props?.flagModels]);
  return (
    <Modal
      maskClosable={false}
      closeIcon={<CloseOutlined style={{ color : '#fff' }} />}
      className={styles.webModal}
      modalRender={(modal) => (
        <Draggable
          handle={dragHandle?"":'.ant-modal-header'}
          disabled={openDrag}
          onDrag={onDrag}
          bounds={bounds}
          position={position}
          onStart={(event, uiData) => onStart(event, uiData)}
        >
          <div ref={draggleRef}>{modal}</div>
        </Draggable>
      )}
      {...props}
    >
      {props?.children}
    </Modal>
  );
};

export default WebReactModal;

 2. 对应封装的model框样式

//index.less 样式文件
.webModal {
  :global {
    .ant-modal-content {
      .ant-modal-header {
        padding: 10px;
        height: 55px;
        background: #269421;
        border-bottom: 1px solid #269421;
        border-radius: 0 0 0 0;
      }
    }
    //标题样式,可根据自己需要修改样式
    .ant-modal-title {
      color: #fff;
      width: 97%;
      font-size: 20px;
      cursor: move;
      user-select: none;
      font-weight: bold;
    }
  }
}

3.父组件

<WebModal width={flagModel ? '100%' : 1200}  style={{
  margin: flagModel ? '0' : '0 auto',
  maxWidth: flagModel ? '100%' : '100vw-32px',
  position : 'relative',
  top : flagModel ? '0' : '100px',
  height : flagModel ? '100%' : '200px',
}}
    onOk={onFinishModel}
    title={
      <div style={{ display : 'flex', justifyContent: 'space-between' , cursor : flagModel ? 'auto' : 'move' }}>
        <span>{modelTitle}</span>
        <span className={'kpps'} style={{ cursor : 'pointer' , fontSize : 16 , marginTop : 2 }} onClick={() => {
          setFlagModel(!flagModel)
          console.log(flagModel)
        }}>
          <FullscreenOutlined style={{ color : "#fff" , display : flagModel ? 'none' : 'block' }} />
          <FullscreenExitOutlined style={{ color : "#fff", display : flagModel ? 'block' : 'none' }} />
        </span>
      </div>
    }
    open={isModalOpen}
    onCancel={handleCancel}
    flagModels={flagModel}
>
  <div className={flagModel ? 'mlp' : ''} style={{ padding : 20 }}>
    这是内容
  </div>
</WebModal>

4.父组件的样式,因为我试了试,一些样式写在子组件的less里没有生效 

.kpps{
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kpps:hover {
  inset-inline-end: 12px;
  z-index: 1010;
  padding: 0;
  color: rgba(0, 0, 0, 0.45);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  background-color: rgba(0,0,0,0.1);
  border-radius: 4px;
  width: 32px;
  height: 32px;
  border: 0;
  outline: 0;
  transition: color 0.2s,background-color 0.2s;
}


.ant-modal .ant-modal-header {
  color: rgba(0, 0, 0, 0.88);
  background: #ffffff;
  margin-bottom: 8px;
  padding: 0;
  border-bottom: none;
}


.ant-modal .ant-modal-footer {
  text-align: end;
  background: transparent;
  margin-top: 12px;
  margin-right: 20px;
  padding: 0;
  border-top: none;
  border-radius: 0;
}

.mlp{
  height: calc(100vh - 55px - 72px)
}

父组件的样式比较粗糙,还是需要再深究下

那么这个框就好了,可以根据自己的需要去制作需要的样式,希望能提供帮助,欢迎评论

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值