DawnLauncher/src/renderer/components/Popup.vue

175 lines
5.2 KiB
Vue

<template>
<div class="popup top-0 left-0 w-full h-full fixed z-10">
<div :id="id" class="popup-content fixed z-20 drop-shadow-[0_0_6px_rgba(0,0,0,0.2)] app-region-no-drag">
<slot name="body"></slot>
</div>
</div>
</template>
<script>
import CommonJS from "@/common/index";
export default {
name: "Popup",
props: {
id: {
type: String,
},
width: {
type: Number,
},
height: {
type: Number,
},
},
data() {
return {
// 只运行一次窗口初始化位置
resize: true,
// 当前是否选中弹窗
current: false,
// 当前弹窗最大移动位置
maxTop: null,
maxLeft: null,
// 弹窗起始位置T
startTop: null,
startLeft: null,
// 鼠标点击的起始位置
startY: null,
startX: null,
// 宽高
w: null,
h: null,
};
},
created() {
this.w = this.width;
this.h = this.height;
},
mounted() {
let _this = this;
// 弹窗初始化位置
if (this.resize) {
this.resize = false;
this.setSize();
}
window.addEventListener("resize", this.setSize, true);
// 监听标题拖拽
let popupHeaderElementList = document.getElementsByClassName("popup-header");
for (let popupHeaderElement of popupHeaderElementList) {
popupHeaderElement.addEventListener("mousedown", function (e) {
// 点击了弹窗
_this.current = true;
// 获取弹窗元素
let popup = document.getElementById(_this.id);
// 获取popup-content位置
let { popupContentTop, popupContentLeft } = _this.getPopupContentTopLeft(popup);
// 获取弹窗所在位置
_this.startTop = popup.offsetTop;
_this.startLeft = popup.offsetLeft;
// 获取鼠标点击位置
_this.startY = e.clientY;
_this.startX = e.clientX;
// 获取屏幕的信息
let doc = document.documentElement;
// 计算当前弹窗最大移动位置
_this.maxLeft = doc.clientWidth - _this.w - popupContentLeft;
_this.maxTop = doc.clientHeight - _this.h - popupContentTop;
// 监听鼠标移动
document.onmousemove = function (e) {
if (_this.current) {
// 计算出移动的位置
let currentLeft = e.clientX - _this.startX + _this.startLeft;
let currentTop = e.clientY - _this.startY + _this.startTop;
// 如果超出的话,就用最大移动位置
currentLeft = currentLeft < 0 - popupContentLeft ? 0 - popupContentLeft : currentLeft > _this.maxLeft ? _this.maxLeft : currentLeft;
currentTop = currentTop < 0 - popupContentTop ? 0 - popupContentTop : currentTop > _this.maxTop ? _this.maxTop : currentTop;
// 设置top left
let popup = document.getElementById(_this.id);
popup.style.left = currentLeft + "px";
popup.style.top = currentTop + "px";
}
};
// 监听鼠标释放
document.onmouseup = function (e) {
_this.current = false;
document.onmousemove = document.onmouseup = null;
};
});
}
},
unmounted() {
window.removeEventListener("resize", this.setSize, true);
},
watch: {
width(newVal, oldVal) {
this.w = newVal;
},
height(newVal, oldVal) {
this.h = newVal;
},
},
methods: {
/**
* 设置弹窗初始化位置
*/
setSize() {
let popup = document.getElementById(this.id);
if (popup != null) {
// 获取popup-content位置
let { popupContentTop, popupContentLeft } = this.getPopupContentTopLeft(popup);
let body = document.querySelector("body");
popup.style.width = this.w + "px";
popup.style.height = this.h == null ? "auto" : this.h + "px";
popup.style.top = body.clientHeight / 2 - popup.clientHeight / 2 - popupContentTop + "px";
popup.style.left = body.clientWidth / 2 - popup.clientWidth / 2 - popupContentLeft + "px";
}
},
/**
* 判断是否是popupContent
*/
isPopupContent(el) {
if (el != null) {
let classList = el.classList;
if (!CommonJS.arrayIsEmpty(classList)) {
for (let clazz of classList) {
if (clazz == "popup-content") {
return true;
}
}
}
}
return false;
},
/**
* 获取popup-content位置
* @param popup
*/
getPopupContentTopLeft(popup) {
let parent = popup.parentElement;
let popupContent;
if (this.isPopupContent(parent)) {
popupContent = parent;
}
while (parent != null) {
parent = parent.parentElement;
if (this.isPopupContent(parent)) {
popupContent = parent;
}
}
let popupContentTop = 0;
let popupContentLeft = 0;
if (popupContent != null) {
if (popupContent.getBoundingClientRect() != null) {
popupContentTop = popupContent.getBoundingClientRect().top;
popupContentLeft = popupContent.getBoundingClientRect().left;
}
}
return { popupContentTop, popupContentLeft };
},
},
};
</script>
<style scoped></style>