el-dialog 自定义指令el-drag-dialog 的使用
可放大,还原,拖拽。
直接上代码
dialog.js
export default {
bind(el, binding, vnode, oldVnode) {
if (!binding.value) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
window.getComputedStyle(dom元素, null);
const getStyle = (function() {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
return (dom, attr) => getComputedStyle(dom, false)[attr]
}
})()
dialogHeaderEl.onmousedown = (e) => {
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const dragDomWidth = dragDom.offsetWidth
const dragDomHeight = dragDom.offsetHeight
const screenWidth = document.body.clientWidth
const screenHeight = document.body.clientHeight
const minDragDomLeft = dragDom.offsetLeft
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
const minDragDomTop = dragDom.offsetTop
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
let styL = getStyle(dragDom, 'left')
let styT = getStyle(dragDom, 'top')
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
} else {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
document.onmousemove = function(e) {
let left = e.clientX - disX
let top = e.clientY - disY
if (-(left) > minDragDomLeft) {
left = -minDragDomLeft
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-(top) > minDragDomTop) {
top = -minDragDomTop
} else if (top > maxDragDomTop) {
top = maxDragDomTop
}
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
} else {
const minWidth = 400
const minHeight = 300
let isFullScreen = false
let nowWidth = 0
let nowHight = 0
let nowMarginTop = 0
const dialogHeaderEl = el.querySelector('.el-dialog__header')
let hasSetBodyHight = false
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.onselectstart = new Function('return false')
dialogHeaderEl.style.cursor = 'move'
window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
const maxMin = document.createElement('button')
maxMin.className += ' el-dialog__headerbtn el-dialog__minmax'
maxMin.style.right = '40px'
maxMin.style.color = '#909399'
maxMin.title = '最大化'
maxMin.innerHTML = '<i class="el-icon-full-screen" onMouseOver="this.style.color=\'#409EFF\'" onMouseOut="this.style.color=\'inherit\'"></i>'
dialogHeaderEl.insertBefore(maxMin, dialogHeaderEl.childNodes[1])
const moveDown = (e) => {
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
let styL, styT
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
if((t + styT) < 0 && Math.abs(t + styT) > window.screen.availHeight * 0.15){
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${-(window.screen.availHeight * 0.15 -20)}px`
}else {
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
}
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
dialogHeaderEl.onmousedown = moveDown
let bodyHeight = 'auto'
function setMaxMin() {
if (isFullScreen == false) {
const i = maxMin.querySelector('.el-icon-full-screen')
i.classList.remove('el-icon-full-screen')
i.classList.add('el-icon-crop')
maxMin.title = '还原'
bodyHeight = dragDom.querySelector('.el-dialog__body').offsetHeight + 'px'
nowHight = dragDom.clientHeight
nowWidth = dragDom.clientWidth
nowMarginTop = dragDom.style.marginTop
dragDom.style.left = 0
dragDom.style.top = 0
dragDom.style.height = '100VH'
dragDom.style.width = '100VW'
dragDom.style.marginTop = 0
isFullScreen = true
dialogHeaderEl.style.cursor = 'initial'
dialogHeaderEl.onmousedown = null
if (!hasSetBodyHight) {
dragDom.querySelector('.el-dialog__body').style.height = 'calc(100% - ' + dialogHeaderEl.offsetHeight + 'px)'
hasSetBodyHight = true
}
vnode.child.$emit('dragDialog', binding.value === 'eltabs' ? 'calc(100vh - 210px)' : (binding.value === 'eltabsB' ? 'calc(100vh - 240px)' : 'calc(100vh - 160px)'), isFullScreen)
} else {
const i = maxMin.querySelector('.el-icon-crop')
i.classList.remove('el-icon-crop')
i.classList.add('el-icon-full-screen')
maxMin.innerHTML = '<i class="el-icon-full-screen"></i>'
maxMin.title = '最大化'
dragDom.style.height = 'auto'
dragDom.style.width = nowWidth + 'px'
dragDom.style.marginTop = nowMarginTop
isFullScreen = false
dialogHeaderEl.style.cursor = 'move'
dialogHeaderEl.onmousedown = moveDown
dragDom.querySelector('.el-dialog__body').style.height = binding.value === 'eltabs' ? 'calc(100vh - 230px)' : (binding.value === 'eltabsB' ? 'calc(100vh - 200px)' : 'calc(100vh - 190px)')
hasSetBodyHight = false
vnode.child.$emit('dragDialog', binding.value === 'eltabs' ? 'calc(100vh - 380px)' : (binding.value === 'eltabsB' ? 'calc(100vh - 380px)' : 'calc(100vh - 280px)'), isFullScreen)
}
}
maxMin.onclick = setMaxMin
dialogHeaderEl.ondblclick = setMaxMin
const resizeEl = document.createElement('div')
dragDom.appendChild(resizeEl)
resizeEl.style.cursor = 'se-resize'
resizeEl.style.position = 'absolute'
resizeEl.style.height = '10px'
resizeEl.style.width = '10px'
resizeEl.style.right = '0px'
resizeEl.style.bottom = '0px'
resizeEl.onmousedown = (e) => {
const clientX = e.clientX
const disX = e.clientX - resizeEl.offsetLeft
const disY = e.clientY - resizeEl.offsetTop
document.onmousemove = function(e) {
e.preventDefault() // 移动时禁用默认事件
const x = e.clientX - disX + (e.clientX - clientX)// 这里 由于elementUI的dialog控制居中的,所以水平拉伸效果是双倍
const y = e.clientY - disY
dragDom.style.width = x > minWidth ? `${x}px` : minWidth + 'px'
dragDom.style.height = y > minHeight ? `${y}px` : minHeight + 'px'
if (!hasSetBodyHight) {
dragDom.querySelector('.el-dialog__body').style.height = 'calc(100% - ' + dialogHeaderEl.offsetHeight + 'px)'
hasSetBodyHight = true
}
vnode.child.$emit('dragDialog', binding.value === 'eltabs' ? dragDom.style.height.substring(0, dragDom.style.height.indexOf('px')) - 210 + 'px' : dragDom.style.height.substring(0, dragDom.style.height.indexOf('px')) - 180 + 'px')
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}
}
里面有一些特定的属性进行判断,只是我项目中用到了,默认是没有的,可以去掉
index.js
import dialog from './dialog'
const install = function(Vue) {
Vue.directive('el-drag-dialog', dialog)
}
if (window.Vue) {
window['el-drag-dialog'] = dialog
Vue.use(install); // eslint-disable-line
}
dialog.install = install
export default dialog
在main.js中注册
import elDragDialog from '@/components/el-drag-dialog' // base on element-ui
Vue.directive('elDragDialog', elDragDialog)
使用方式
<el-dialog v-el-drag-dialog ></el-dialog>```