手写react可拖拽弹窗组件
import React, { useEffect, useRef, useState } from 'react'import {PlusOutlined,FullscreenOutlined,FullscreenExitOutlined,} from "@ant-design/icons";import style from './index.less'const PopModal= (pro
·
直接上干货!
import React, { useEffect, useRef, useState } from 'react'
import {
PlusOutlined,
FullscreenOutlined,
FullscreenExitOutlined,
} from "@ant-design/icons";
import style from './index.less'
const PopModal= (props)=> {
let {
//弹窗是否显示
visible,
// //弹窗标题
// title,
//当前tab
tabIndex,
//弹窗多标签
tabs=[],
//tab切换事件 function 可不传
onTabChange,
//是否关闭
onClose,
//内容
children,
//是否显示全屏控件 默认false
isShowFullScreen=false,
isFullscreen,//是否全屏
//是否全屏 function 可不传
onFullScreen,
//距离顶部高度,没传该值,则动态计算
paddingTop,
//弹窗宽度 vw 必传
modalWid,
//弹窗高度 vh 必传
modalHgt,
// //全屏高度
// maxHgt,
// //全屏宽度
// maxWid,
styleSheet,
} = props;
// let [isFullscreen,setIsFullscreen]=useState(false);
let [styleTop,setStyleTop] = useState(50);
let [styleLeft,setStyleLeft] = useState(100);
let [maxHgt,setMaxHgt] = useState("");
let [maxWid,setMaxWid] = useState("");
const modalRef = useRef(null);
//计算是否超出屏幕
const InWindow = (left, top, startPosX, startPosY) => {
let H = document.body.clientHeight;
let W = document.body.clientWidth;
if ((left < 100 && startPosX > left) || (left > W - 100 && startPosX < left) ||
(top < 20 && startPosY > top) || ((top > H - 20 && startPosY < top))) {
return false
}
return true
}
const onMouseDown = e => {
if(isFullscreen){
return;
}
e.preventDefault();
let startPosX = e.clientX;
let startPosY = e.clientY;
document.body.onmousemove = e => {
let left = e.clientX - startPosX + styleLeft;
let top = e.clientY - startPosY + styleTop;
if (InWindow(e.clientX, e.clientY, startPosX, startPosY)) {
setStyleTop(top);
setStyleLeft(left);
} else {
document.body.onmousemove = null;
document.body.onmouseup = null;
}
};
document.body.onmouseup = function () {
document.body.onmousemove = null;
document.body.onmouseup = null;
};
};
const resetModal = ()=>{
//浏览器宽高
let bodyWid = document.body.clientWidth;
let bodyHgt = document.body.clientHeight;
//弹窗宽高
let domWid = modalRef.current.clientWidth;
let domHgt = modalRef.current.clientHeight;
// console.log('OpenModal',{bodyWid,bodyHgt,ght:modalRef.current.clientHeight});
var pLeft = Math.floor((bodyWid-domWid)/2);
if(!paddingTop){
var pTop = Math.floor((bodyHgt-domHgt)/2);
setStyleTop(pTop);
}else{
setStyleTop(paddingTop);
}
setStyleLeft(pLeft);
}
useEffect(()=>{
//
if(visible){
resetModal();
setMaxHgt(document.body.clientHeight+'px');
setMaxWid(document.body.clientWidth+'px');
}
},[visible,modalHgt])
window.onresize =()=>{
setMaxHgt(document.body.clientHeight+'px');
setMaxWid(document.body.clientWidth+'px');
}
const closeModal = ()=>{
//初始化弹窗位置
resetModal();
//关闭弹窗
onClose();
}
useEffect(()=>{
if(!isFullscreen){
resetModal();
}
},[isFullscreen])
const toggoleFullscreen=()=>{
var isFull = !isFullscreen;
if(isFull){
setStyleTop(0);
setStyleLeft(0);
}
//全屏事件回调
if(typeof(onFullScreen)=='function'){
onFullScreen(isFull);
}
}
///
const ClickTabChange =(id)=>{
//tab点击事件回调
if(typeof(onTabChange)=='function'){
onTabChange(id)
}
}
return <div className={style.model_wrap} style={{display: visible ? "block" : "none"}}>
<div className={style.popContainer} style={{
left: styleLeft+'px' , top: styleTop+'px' ,
width: isFullscreen?maxWid:modalWid,height: isFullscreen?maxHgt:modalHgt
}} ref={modalRef}>
<div className={style.header} onMouseDown={onMouseDown} style={{...styleSheet}}>
<div className={style.tabs}>
{/* {title!="" && title.length>0 && <div className={`${style.tab_item} ${style.actived_item}`}>{title}</div>} */}
{tabs.map(item=>{
return (
<div onClick={()=>ClickTabChange(item.id)} className={`${style.tab_item} ${tabIndex==item.id?style.actived_item:''}`}>{item.name}</div>
)
})}
</div>
<div className={style.right}>
{isShowFullScreen && (
!isFullscreen ?
<span className={style.is_full} onClick={toggoleFullscreen} title='全屏'><FullscreenOutlined /></span>
:<span className={style.is_full} onClick={toggoleFullscreen} title='退出全屏'><FullscreenExitOutlined /></span>
)}
<span className={style.close} title="关闭" onClick={onClose}><PlusOutlined /></span>
</div>
</div>
<div className={style.content} >
{children}
</div>
{/* <div className={style.footer}>
</div> */}
</div>
</div>
// }
}
export default PopModal;
.model_wrap {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(32, 40, 45, 0.65);
z-index: 1001;
.popContainer {
position : fixed;
width: 39vw;
// height: 45vw;
// background-color: white;
// z-index : 1001;
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;
background-color: rgba(1, 41, 77, 1);
.header {
background: #002241;
// padding : 10px 24px;
// height: 48px;
color :#FFF;
// border-bottom: 1px solid #e8e8e8;
border-radius: 4px 4px 0 0;
.tabs {
// width: 100%;
cursor : move;
height: 48px;
padding-left: 24px;
background: #002241;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
.tab_item {
display: inline-block;
color: rgba(255, 255, 255, 0.65);
font-size: 16px;
line-height: 45px;
font-weight: 500;
width: 88px;
cursor: pointer;
text-align: center;
&:hover,
&.actived_item {
color: #fff;
border-bottom: 2px solid #FFD188;
}
}
}
.right{
position: absolute;
top :0;
right: 0;
display: flex;
.is_full{
width : 36px;
height : 48px;
font-size : 16px;
line-height: 48px;
text-align : center;
cursor: pointer;
color : #FFF;
opacity: 0.4;
&:hover {
opacity: 1;
}
}
.close {
// position : absolute;
// top : 0;
// right : 0;
cursor : pointer;
width : 36px;
height : 48px;
font-size : 16px;
line-height: 48px;
text-align : center;
color: #fff;
opacity: 0.4;
svg {
transform: rotate(45deg);
}
&:hover {
opacity: 1;
}
}
}
.title {
cursor : move;
// color : rgba(0, 0, 0, 0.85);
font-weight: 500;
font-size : 16px;
line-height: 22px;
}
}
.content {
height : calc(100% - 48px);
overflow: hidden;
background-color: rgba(1, 41, 77, 1);
}
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)