最近项目中有这样一个需求:要求网格中每个块拖拽的时候吸附网格,并且放大缩小相对位置不变,传给后台的坐标信息也一致;
拖拽大家都会,特别简单,但是吸附网格+放大缩小相对信息不变可能会加大一点难度,我自己技术有限,写了一个下午终于算是写出来了,写篇博客记录一下!
附上代码以及稍微一点解释:
//自定义拖拽指令
Vue.directive("drag", {
update: function(e, value, vNode) {
var ex, ey;
var id = value.value.id;
e.onmousedown = function(e) {
var ev = e || event;
//小块-》父级元素的距离
ex = this.offsetLeft;
ey = this.offsetTop;
//鼠标在父元素外相对屏幕的距离 //不固定
var h = ev.clientX - ex;
var t = ev.clientY - ey;
//获取父元素宽高
var ph = elWrap.clientHeight;
var pw = elWrap.clientWidth;
//获取子元素宽高
var ch = this.clientHeight;
var cw = this.clientWidth;
//网格宽度
var ge = value.value.movelen;
document.onmousemove = function(e) {
var evv = e || event;
//value.value.frameBig=true 放大状态 反之。。
if (value.value.frameBig == 1) {
this.style.left =
ex + Math.round((evv.clientX - h - ex) / 0.4 / ge) * ge + "px";
this.style.top =
ey + Math.round((evv.clientY - t - ey) / 0.4 / ge) * ge + "px";
// 限制可拖拽区域
if (evv.clientX - (ev.clientX - ex * 0.4) <= 0) {
this.style.left = "0px";
} else if (evv.clientX - (ev.clientX - ex * 0.4) >= (pw - cw) * 0.4) {
this.style.left = pw - cw + "px";
}
if (evv.clientY - (ev.clientY - ey * 0.4) <= 0) {
this.style.top = "0px";
} else if (evv.clientY - (ev.clientY - ey * 0.4) >= (ph - ch) * 0.4) {
this.style.top = ph - ch + "px";
}
} else if (value.value.frameBig == 2) {
this.style.left =
ex + Math.round((evv.clientX - h - ex) / ge) * ge + "px";
this.style.top =
ey + Math.round((evv.clientY - t - ey) / ge) * ge + "px";
// 限制可拖拽区域
if (evv.clientX - h <= 0) {
this.style.left = "0px";
} else if (evv.clientX - h >= pw - cw) {
this.style.left = pw - cw + "px";
}
if (evv.clientY - t <= 0) {
this.style.top = "0px";
} else if (evv.clientY - t >= ph - ch) {
this.style.top = ph - ch + "px";
}
}
}.bind(this);
document.onmouseup = function(e) {
let lastX = this.style.left.replace("px", "");
let lastY = this.style.top.replace("px", "");
var ev = e || event;
var upx = ev.clientX - this.offsetLeft;
var upy = ev.clientY - this.offsetTop;
var moveL = Math.sqrt((h - upx) * (h - upx) + (t - upy) * (t - upy)); //求斜边移动距离
document.onmouseup = document.onmousemove = null;
// console.log(moveL);
if (moveL > 5) {
console.log(lastX, lastY); //拖动之后的坐标
let params = {
cabinetX: parseFloat(lastX),
cabinetY: parseFloat(lastY),
cabinetId: id
};
let prom = equipment.updateCabinetXY(params);
prom.then(
ret => {},
err => {}
);
value.value.ifClick(false);
}
setTimeout(() => {
value.value.ifClick(true);
}, 300);
}.bind(this);
};
}
});
1、因为这个网格背景中需要不断添加不同大小的方块并摆放位置,所以我用vue的自定义指令写,指令传了4个参数,分别为当前移动的方块id、每次移动的距离(也就是一个网格的宽度)、当前是拖拽还是单机(因为每个方块同时绑定了单机、双击、拖拽事件,所以为单机和拖拽做区分)、当前的放大缩小情况(与上面icon对应)
2、在data中给了数据
3、吸附网格很简单,思路:方格的定位值=移动了的距离/网格的宽度得到的整数部分*格子的宽度
4、刚开始没有相同怎么去做放大缩小能相对保持不变,不想设置两个尺寸再让里面的方块根据相对位置移动,后来想到了css3的scale,可以在保持占用位置和真实大小不变的情况下等比放大缩小
5、但是鼠标用scale在鼠标拖拽的时候也得乘以或者除以相对应的比例,否则物体不会紧跟着鼠标走
6、目前只是实现功能,代码略显冗杂,后期会优化更新