项目场景:
提示:自用方法,有改进的地方请指正
可以拖拽,改变大小,不超出父div
解决方案:
<template>
<div class="window" :style="`top:${top};left:${left};right:${right};`">
<div class="titlebar">
<slot name="header">
</slot>
</div>
<div style="height: fit-content;width: 100%; background: rgba(71,71,71,.8);">
<slot name="header2">
</slot>
</div>
<div class="content" ref="boxContent">
<slot name="body">
</slot>
<div style="width: 100%;height: 30px;"></div>
</div>
<div class="foot">
<slot name="foot">
</slot>
</div>
</div>
</template>
<script setup>
import {onMounted, ref, toRefs, defineProps} from "vue";
import { useElementSize } from '@vueuse/core'
const props = defineProps({
//子组件接收父组件传递过来的值
top: String,
left: String,
right: String,
})
const { top } = toRefs(props)
const { left } = toRefs(props)
const { right } = toRefs(props)
const boxContent = ref()
const { width, height } = useElementSize(boxContent)
const contentShowType = ref('visible')
onMounted(() => {
const windows = document.querySelectorAll('.window');
[].forEach.call(windows,function(win){
// …find the title bar inside it and do something onmousedown
var title = win.querySelector('.titlebar');
title.addEventListener('mousedown',function(evt){
let rangWidth = win.parentNode.clientWidth; //父元素宽度,即 移动范围
let rangHeight = win.parentNode.clientHeight; //父元素高度
// boxContent.value.style.maxHeight = (rangHeight - 120) + 'px'
// boxContent.value.style.maxWidth = rangWidth + 'px'
const real = window.getComputedStyle(win),
winX = parseFloat(real.left), // 距父元素距离
winY = parseFloat(real.top);
// Record where the mouse started
const mX = evt.clientX,
mY = evt.clientY;
// console.log(evt)
// When moving anywhere on the page, drag the window
// …until the mouse button comes up
document.body.addEventListener('mousemove',drag,false);
document.body.addEventListener('mouseup',function(){
document.body.removeEventListener('mousemove',drag,false);
},false);
let disX = evt.clientX - winX // 鼠标距边
let disY = evt.clientY - winY
const dWdith = win.clientWidth // 组件尺寸
const dHeight = win.clientHeight
const dMoveLeft = rangWidth - dWdith // 最大移动距离
const dMoveTop = rangHeight - dHeight
function drag(e){
//通过事件委托,计算移动的距离
let left = e.clientX - disX;
let top = e.clientY - disY;
//移动当前元素
//如果元素的移动位置大于窗口位置,则不再移动
if(left > dMoveLeft){
win.style.left = `${dMoveLeft}px`;
}else{
win.style.left = `${left}px`;
}
if(left <0){
win.style.left = `0px`;
}
if(top > dMoveTop){
win.style.top = `${dMoveTop}px`;
}else{
win.style.top = `${top}px`;
}
if(top < 0){
win.style.top = `0px`;
}
}
},false);
});
})
</script>
<style scoped>
.window {
position:absolute;
width:fit-content;
height:fit-content;
background:#fff00000;
user-select:none;
-webkit-user-select:none;
-moz-user-select:none;
z-index: 1;
}
.window .titlebar {
width: 100%;
height: 36px;
line-height: 36px;
color: white;
background: rgba(71,71,71,.8);
border-bottom: 4px solid rgba(0,0,0,.4);
text-align:center;
cursor:move;
display: flex;
}
.window .content {
resize: both;
width: 500px;
height: fit-content;
min-width: 300px;
max-height: 60vh;
max-width: 80vw;
overflow: auto;
outline: none;
white-space: pre;
overflow-wrap: normal;
position: relative;
background: rgba(71,71,71,.8);
border: 1px solid rgba(91, 123, 235, 0.3);
}
.window .foot {
text-align: right;
padding-right: 20px;
margin-top: -36px;
height: 36px;
width: 100%;
}
</style>