功能描述:div任意拖拽,有边界控制,带吸附。
实现方式:通过计算鼠标相对元素位置,得到元素位置。
1, js代码
/**
* v-drag dom拖拽方法
*/
Vue.directive(‘drag’, {
bind(el, binding, vnode) {
const gap = 10 // 边距小于gap时,则吸附
const bodyDom = document.body // body
const dialogHeaderEl = el.querySelector('.my-dialog__header') // 能拖拽的部分
const dragDom = el // 需要移动的dom
if(!dialogHeaderEl) return // 容错
dialogHeaderEl.style.cursor = 'move' // 此光标指示某对象可被移动
dialogHeaderEl.onmousedown = (e) => {
// 算出鼠标相对元素的位置
const disX = e.clientX - dragDom.offsetLeft
const disY = e.clientY - dragDom.offsetTop
document.onmousemove = (e) => {
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX
let top = e.clientY - disY
// 左
if (left <= gap) {
left = 0
}
if (left >= bodyDom.offsetWidth - dragDom.offsetWidth - gap) {
left = bodyDom.offsetWidth - dragDom.offsetWidth
}
// 上
if (top <= gap) {
top = 0
}
if (top >= bodyDom.offsetHeight - dragDom.offsetHeight - gap) {
top = bodyDom.offsetHeight - dragDom.offsetHeight
}
el.style.left = left + 'px'
el.style.top = top + 'px'
el.style.zIndex = 9999
}
document.onmouseup = (e) => {
document.onmousemove = null
document.onmouseup = null
}
}
}
})
2, html, css 代码,用div仿一个弹窗
<div class="my-dialog" v-drag>
<header class="my-dialog__header">
我是标题
</header>
<div>
一些内容
</div>
</div>
<style>
.my-dialog {
width: 300px;
height: 300px;
background: #FFFFFF;
position: fixed;
z-index: 1;
padding: 20px;
box-shadow: 0px 0px 12px 0px rgba(0,0,0,0.09);
.my-dialog__header {
border-bottom: 1px solid #999999;
}
}
</style>
效果图: