思路
主要使用directives自定义拖动指令,指令内部主要有关于拖动的3个事件,鼠标按下,鼠标移动,鼠标抬起。事件内部的回调函数有鼠标点击的坐标,根据三个事件的坐标计算弹框的最终位置坐标,然后将坐标转化为css样式赋值给弹框。
效果
代码
<template>
<div class="draggable-modal" v-draggable>
<div class="modal-content">
{{ formattedDate }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
date: new Date(),
};
},
computed: {
formattedDate() {
return this.moment(this.date).format("YYYY-MM-DD HH:mm:ss");
},
},
directives: {
// 自定义指令
draggable: {
bind(el) {
const modal = el;
let drag = false;
let startX, startY, initialX, initialY;
let finalX, finalY;
modal.addEventListener("mousedown", function (event) {
drag = true;
startX = event.clientX;
startY = event.clientY;
initialX = parseFloat(modal.style.left || "0");
initialY = parseFloat(modal.style.top || "0");
});
window.addEventListener("mousemove", function (event) {
if (drag) {
finalX = initialX + (event.clientX - startX);
finalY = initialY + (event.clientY - startY);
modal.style.left = finalX + "px";
modal.style.top = finalY + "px";
}
});
window.addEventListener("mouseup", function () {
drag = false;
});
},
},
},
};
</script>
<style>
.draggable-modal {
position: relative;
width: 300px;
height: 200px;
background-color: rgba(0, 0, 0, 0.5);
border: 1px solid #ccc;
cursor: move;
}
.modal-content {
padding: 20px;
background-color: #fff;
}
</style>
// 全局指令
Vue.directive("draggable", {
bind(el) {
const modal = el;
let drag = false;
let startX, startY, initialX, initialY;
let finalX, finalY;
modal.addEventListener("mousedown", function (event) {
drag = true;
startX = event.clientX;
startY = event.clientY;
initialX = parseFloat(modal.style.left || "0");
initialY = parseFloat(modal.style.top || "0");
});
window.addEventListener("mousemove", function (event) {
if (drag) {
finalX = initialX + (event.clientX - startX);
finalY = initialY + (event.clientY - startY);
modal.style.left = finalX + "px";
modal.style.top = finalY + "px";
}
});
window.addEventListener("mouseup", function () {
drag = false;
});
},
});