要输入一些表单时候,但是模态框又会把我们需要的背景重要部分挡住,于是我们就想拖动窗口。观察了一些组件,基本没有我想要的效果。以前写过一段时间的
angular
,发现angular
的官方组件库material design
很好用,他们的拖拽也非常的好。下面我实现的也是借鉴了一点他们的想法,再加上结合了网友们的代码写的。主要是通过transform
这个属性
实现效果
通过拖动模态框的头部来拖动模态框
实现
指令
// drag.js
const drag = {
install (Vue) {
Vue.directive('dragHandle', {
inserted: (el) => {
el.addEventListener('mousedown', touch, false)
document.addEventListener('mouseup', mouseup, false)
}
})
Vue.directive('drag', {
bind: (el) => {
el.classList.add('c-drag')
}
})
}
}
var dom = null
var E_SIZER = {}
export function getStyle (el, attr) {
if (typeof window.getComputedStyle !== 'undefined') {
return window.getComputedStyle(el, null)[attr]
} else if (typeof el.currentStyle !== 'undefined') {
return el.currentStyle[attr]
}
return ''
}
export function getParentDom (el) {
if (el.parentElement.classList.value.indexOf('c-drag') > -1) {
dom = el.parentElement
return el.parentElement
} else {
return getParentDom(el.parentElement)
}
}
export function touch (e) {
let parentDom = getParentDom(e.target)
e.stopPropagation()
e.preventDefault()
let matrix3dReg = /^matrix3d\((?:[-\d.]+,\s*){12}([-\d.]+),\s*([-\d.]+)(?:,\s*[-\d.]+){2}\)/
let matrixReg = /^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/
let matrix3dSourceValue = getStyle(parentDom, 'transform')
let matrix3dArrValue = matrix3dSourceValue.match(matrix3dReg) || matrix3dSourceValue.match(matrixReg)
E_SIZER['clientX'] = e.clientX
E_SIZER['clientY'] = e.clientY
E_SIZER['targetX'] = matrix3dArrValue ? matrix3dArrValue[1] : 0
E_SIZER['targetY'] = matrix3dArrValue ? matrix3dArrValue[2] : 0
E_SIZER['distX'] = E_SIZER['clientX'] - E_SIZER['targetX']
E_SIZER['distY'] = E_SIZER['clientY'] - E_SIZER['targetY']
document.addEventListener('mousemove', move, false)
}
export function mouseup (e) {
e.stopPropagation()
e.preventDefault()
document.removeEventListener('mousemove', move)
}
export function move (e) {
e.stopPropagation();
e.preventDefault();
let moveY = e.clientY - E_SIZER['distY']
let moveX = e.clientX - E_SIZER['distX']
dom.style.transform = `translate3d(${moveX}px,${moveY}px,1px)`
}
export default drag
// main.js
import drag from './directive/drag.js'
Vue.use(drag)
使用方法
<div class="drag-modal" v-drag>
<div class="modal-title" v-dragHandle>
<h2>{{ title }}</h2>
<a-icon type="close" @click="close" class="close" />
</div>
<div class="modal-content">
<slot name="content"></slot>
</div>
</div>
说明:指令中关于拖拽的代码来源https://zhuanlan.zhihu.com/p/82906845,写的很详细,想更清楚的了解运行机制啥的可以去看他的文章。这个模态框是自定义的,因为一些UI组件的模态框封装性较好,这个指令用上去会有一些问题,如果要处理这些问题,就会导致指令的通用性较差。有需要自定义模态框(使用了vue)的代码可以看我写的另外一篇文章vue 自定义模态框