一个简单的可拖拽的弹窗样式
- HTML:通过给可拖拽区域绑定
@mousedown="startDrag"vue的事件来实现元素的拖动功能。 - CSS:通过
background: linear-gradient(180deg, color 0%, color 100%)实现背景渐变色,宽度通过width: fit-content实现自适应宽,同时设置min-width和max-width确保比例不会太离谱。 - JS:通过使用
startDrag、onDrag、stopDrag 等事件来控制拖动行为。
源码
<div v-if="showCard" ref="card" class="card_info">
<div class="card_header" @mousedown="startDrag"></div>
<div class="close_info" @click="showCard = false">×</div>
<span>≡ 标题</span>
<p>字段一: {{ metarilInfo.mapCode }}</p>
<p>字段二: {{ metarilInfo.areaCode }}</p>
<p>字段三: {{ metarilInfo.mapDataCode }}</p>
<p>字段四: {{ metarilInfo.coox }}, {{ metarilInfo.cooy }}</p>
<p>字段五: {{ metarilInfo.shelfCode }}</p>
<p>字段六: {{ metarilInfo.mapDataEmptyDate || '/' }}</p>
</div>
<script lang="ts" setup>
import { ref } from 'vue';
const showCard = ref(false);
const card = ref<any>(null);
const isDragging = ref(false);
let startX = 0;
let startY = 0;
const startDrag = (event) => {
if (!card.value) return
isDragging.value = true;
startX = event.clientX - card.value.offsetLeft;
startY = event.clientY - card.value.offsetTop;
document.addEventListener('mousemove', onDrag);
document.addEventListener('mouseup', stopDrag);
document.addEventListener('mouseleave', stopDrag);
};
const onDrag = (event) => {
if (!isDragging.value) return
event.preventDefault();
card.value.style.left = `${event.clientX - startX}px`;
card.value.style.top = `${event.clientY - startY}px`;
};
const stopDrag = () => {
isDragging.value = false;
document.removeEventListener('mousemove', onDrag);
document.removeEventListener('mouseup', stopDrag);
document.removeEventListener('mouseleave', stopDrag);
};
</script>
<style lang="scss" scoped>
.card_info {
position: absolute;
top: 20%;
left: 50%;
transform: translateX(-50%);
min-width: 12vw;
max-width: fit-content;
pointer-events: all;
background: linear-gradient(180deg, #236784f1 0%, #236784d2 20%, #2367848a 100%);
padding: 0.1vw 0.5vw 0.5vw 0.5vw;
border: 1px solid #44dbee;
border-radius: 0.25vw;
&::before {
content: "";
position: absolute;
top: 0.7vw;
left: 0;
height: 1vw;
width: 0.2vw;
background-color: #44dbee;
}
.card_header {
position: absolute;
top: 0.3vw;
left: 0.3vw;
height: 1.5vw;
width: 90%;
cursor: grab; //可拖拽样式
z-index: 1;
&:active {
cursor: grabbing; //鼠标点击后变为拖拽中样式
}
}
.close_info {
font-size: 2vh;
width: 1vw;
height: 1vw;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0.1vw;
right: 0.1vw;
&:hover {
cursor: pointer;
background-color: red;
}
}
span {
font-size: 1vw;
font-weight: 600;
height: 1.9vw;
line-height: 1.9vw;
padding: 0 1vw 0 0;
z-index: 2;
}
p {
font-size: 0.7vw;
height: 1.4vw;
line-height: 1.4vw;
background-color: #00000050;
margin-top: 0.1vw;
padding: 0 0.3vw;
white-space: nowrap;
}
}
</style>
效果图
