效果如图
看一下缩放代码
1、通过自定义指令 + 鼠标事件实现
// 自定义指令
directives:{
/*
指令钩子函数会被传入以下参数:
el:指令所绑定的元素,可以用来直接操作 DOM 。
binding:一个对象,包含以下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode: Vue编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
*/
drag(el,binding,vnode) {
let that = vnode.context
let canDrag = binding.value.isCanDrag && that.prillingConfig.isCanDrag//是否可拖拽
let currentKey = binding.value.index//当前操作的数组下标
let leftB=''
let topB=''
el.onmousedown = function (e) {
if(!canDrag)return; //该字段判断是否显示
e.preventDefault()
// clientX、clientY 点击位置距离当前body可视区域的x,y坐标
let thex = e.clientX
let they = e.clientY
//获取该拖拽容器的宽高 此处父级便是容器 则直接去赋值的宽高
let dom = document.getElementById('dragDiv'+that.currentId)
let ph = dom.offsetHeight// 父元素高度
let pw = dom.offsetWidth // 父元素宽度
//在鼠标点击之后 监听鼠标移动事件 并随之修改其定位信息
document.onmousemove = function (e) {
if(!canDrag)return;
//鼠标现在距离视口宽度的距离 - 刚才距离视口宽度的距离 = 相对刚才的偏移
let movx = e.clientX - thex
let movy = e.clientY - they
/**
* 元素本身高度和距离顶端的高度和
* el.offsetTop 当前元素相对父级的top
* el.offsetHeight 当前元素高度
*/
let totalH = el.offsetTop + movy + el.offsetHeight
// 元素本身宽度和距离左面的宽度和
// 距离父组件左侧 鼠标偏移 元素宽度
let totalW = el.offsetLeft + movx + el.offsetWidth
// 限制移动范围
if (el.offsetHeight < totalH/* && totalH < ph*/) {
// el.style.top = (el.offsetTop + movy) + 'px'
// console.log((el.offsetTop + movy)/ph*100 )
el.style.top = (el.offsetTop + movy)/ph*100 + '%'
topB = (el.offsetTop + movy)/ph*100
}
// 限制移动范围
// 元素小于屏幕宽度,且没有超越边界
// console.log("元素右侧距离左侧距离:",totalW,'元素宽度:',el.offsetWidth,'父元素宽度',pw)
if (el.offsetWidth < totalW && totalW < pw) {
// el.style.left = (el.offsetLeft + movx) + 'px'
el.style.left = (el.offsetLeft + movx)/pw*100 + '%'
leftB = ((el.offsetLeft + movx)/pw*100 ).toFixed(2) < 0 ? 0 : ((el.offsetLeft + movx)/pw*100 ).toFixed(2)
} else if (el.offsetWidth > pw) { // 标签的宽度大于屏幕宽度
if (totalW > 30 && totalW < (pw + el.offsetWidth - 30)) {
// el.style.left = (el.offsetLeft + movx) + 'px'
el.style.left = (el.offsetLeft + movx)/pw*100 + '%'
leftB = ((el.offsetLeft + movx)/pw*100).toFixed(2) < 0 ? 0 : ((el.offsetLeft + movx)/pw*100).toFixed(2)
}
}
thex = e.clientX
they = e.clientY
//利用防抖赋值给需要绑定的字段
if(window.FunMove){clearTimeout(window.FunMove)}
window.FunMove = setTimeout(()=>{
try{
that.JsonData[currentKey].style.leftB = leftB || that.JsonData[currentKey].style.leftB
that.JsonData[currentKey].style.topB= topB || that.JsonData[currentKey].style.topB
console.log("修改")
}catch(Err){}
window.FunMove = false
},50)
}
//在鼠标抬起时 解除事件绑定
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
}
}
}
},
html代码部分
2通过HTML5中drag实现
HTML代码部分
//绑定值目标元素
@drop="drop"
//绑定至被拖拽元素
@dragstart.stop="dragstart" //开始拖拽
@drag.stop='draging' //拖拽中
@dragend.stop="dragend"//拖拽结束
:draggable="prillingConfig.isCanDrag" //判断是否可拖拽 Boolean
// 拖拽 start
dragstart (ev) { //拖拽开始事件
ev.target.parentNode.parentNode.parentNode
ev.dataTransfer.setData('Text', ev.target.id)
// 开始点击时 鼠标在元素中的定位 保存再来后续计算偏移
this.offsetX = ev.offsetX
this.offsetY = ev.offsetY
},
// 拖拽中
draging (e) {
let that = this
let x = e.clientX
let y = e.clientY
// drag事件最后一刻,无法读取鼠标的坐标,pageX和pageY都变为0
if (x === 0 && y === 0) {
return // 不处理拖动最后一刻X和Y都为0的情形
}
x -= this.offsetX
y -= this.offsetY
//获取被拖拽元素DOM 因可能拖拽的是目标子元素 设置top left 无效 所以要获取到 需要被拖拽的元素 给其赋值left 及 right
let dom = document.getElementById(that.getParent(e.target,'a_particle'))
// 父级元素 距离 视口 左侧及顶部的距离
let parent = document.getElementById('dragDiv'+that.currentId)
let domToTop = parent.getBoundingClientRect().top
let domToLeft = parent.getBoundingClientRect().left
let ph = parent.offsetHeight// 父元素高度
let pw = parent.offsetWidth // 父元素宽度
let left = 0
let top = 0
//判断取值是% || px
if(dom.style.left && dom.style.left.indexOf('%')!=-1){
left = (x - domToLeft)/pw*100+'%'
}else{
left = x -domToLeft + 'px'
}
if(dom.style.top && dom.style.top.indexOf('%')!=-1){
top = (y-domToTop)/ph*100+'%'
}else{
top = y-domToTop + 'px'
}
dom.style.left = left
dom.style.top = top
},
drop (ev) {
console.log('drop拖放事件,绑定可拖放区域', ev)
let target = document.getElementById(ev.dataTransfer.getData('Text'))
ev.target.appendChild(target)
ev.preventDefault()
},
dragend (event) {
event.dataTransfer.clearData()
},
/**
* @description: 根据ID 寻找dom 如果未发现 继续往父级搜索
* @param {Object} dom DOM对象
* @param {string} id 需要查找的ID
*/
getParent(dom,id){
if(dom.id && dom.id.indexOf(id)!=-1){
return dom.id
}else{
return this.getParent(dom.parentNode,id)
}
},
//拖拽 end