基於vue實現可拖動彈框
阿新 • • 發佈:2021-01-14
基於vue實現可拖動彈框
el-dialog彈框拖拽
- 在 utils 中新建 directives.js 檔案
import Vue from 'vue'
// 自定義元素實現彈框拖拽[重點]
Vue.directive('draw', {
inserted: function (el, binding, vNode) {
el.setAttribute('style', 'position: fixed; z-index: 9999')
},
bind: function (el, bindding, vNode) {
el. setAttribute('draggable', true)
let left, top, width, height
el._dragstart = function (event) {
event.stopPropagation()
left = event.clientX - el.offsetLeft
top = event.clientY - el.offsetTop
width = el.offsetWidth
height = el.offsetHeight
}
el._checkPosition = function () { // 防止被拖出邊界
let width = el.offsetWidth
let height = el.offsetHeight
let left = Math.min(el.offsetLeft, document.body.clientWidth - width)
left = Math.max(0, left)
let top = Math.min(el.offsetTop, document.body.clientHeight - height)
top = Math.max(0, top)
el.style.left = left + 'px'
el.style.top = top + 'px'
el.style.width = width + 'px'
el.style.height = height + 'px'
}
el._dragEnd = function (event) {
event.stopPropagation()
left = event.clientX - left
top = event.clientY - top
el.style.left = left + 'px'
el.style.top = top + 'px'
el.style.width = width + 'px'
el.style.height = height + 'px'
el._checkPosition()
}
el._documentAllowDraop = function (event) {
event.preventDefault()
}
document.body.addEventListener('dragover', el._documentAllowDraop)
el.addEventListener('dragstart', el._dragstart)
el.addEventListener('dragend', el._dragEnd)
window.addEventListener('resize', el._checkPosition)
},
unbind: function (el, bindding, vNode) {
document.body.removeEventListener('dragover', el._documentAllowDraop)
el.removeEventListener('dragstart', el._dragstart)
el.removeEventListener('dragend', el._dragEnd)
window.removeEventListener('resize', el._checkPosition)
delete el._documentAllowDraop
delete el._dragstart
delete el._dragEnd
delete el._checkPosition
}
})
// v-dialogDrag: 彈窗拖拽
Vue.directive('dialogDrag', {
bind (el, binding, vnode, oldVnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cursor = 'move'
// 獲取原有屬性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
dialogHeaderEl.onmousedown = (e) => {
// 滑鼠按下,計算當前元素距離可視區的距離
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
// 獲取到的值帶px 正則匹配替換
let styL, styT
// 注意在ie中 第一次獲取到的值為元件自帶50% 移動之後賦值為px
if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
} else {
styL = +sty.left.replace(/\px/g, '')
styT = +sty.top.replace(/\px/g, '')
}
document.onmousemove = function (e) {
// 通過事件委託,計算移動的距離
const l = e.clientX - disX
const t = e.clientY - disY
// 移動當前元素
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
// 將此時的位置傳出去
// binding.value({x:e.pageX,y:e.pageY})
}
document.onmouseup = function (e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
})
// v-dialogDragWidth: 彈窗寬度拖大 拖小
Vue.directive('dialogDragWidth', {
bind (el, binding, vnode, oldVnode) {
const dragDom = binding.value.$el.querySelector('.el-dialog')
el.onmousedown = (e) => {
// 滑鼠按下,計算當前元素距離可視區的距離
const disX = e.clientX - el.offsetLeft
document.onmousemove = function (e) {
e.preventDefault() // 移動時禁用預設事件
// 通過事件委託,計算移動的距離
const l = e.clientX - disX
dragDom.style.width = `${l}px`
}
document.onmouseup = function (e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
})
- main.js中匯入:import ‘./utils/directives.js’
- 使用
el-dialog
的地方加入v-dialogDrag
<el-dialog
:visible.sync="dialogVisible"
v-dialogDrag>
// ...
</el-dialog>
自定義元素彈框拖拽(重點)
自定義指令的內容,請見utils 中新建 directives.js 檔案
<div class="drag" v-draw>可拖動視窗</div>
參考文章: