发生拖拽行为之后,鼠标move都会执行该方法,通过不断更新拖拽节点的样式来是节点发生移动效果。
drag(event) {
const pageX = event.pageX, pageY = event.pageY;
const x = pageX - this.containerOffset.left - this.offsetX,
y = pageY - this.containerOffset.top - this.offsetY;
this.dragElement.style.cssText += ';transform:translate('+ x +'px, '+ y +'px)';
}主要是计算节点相对于容器的偏移:鼠标距离页面距离-容器偏移-鼠标距离拽节点距离就为节点距离容器的距离。
dragEnd
主要是重置状态。逻辑比较简单,就不再细说了。
到这里已经单个节点已经可以跟随鼠标进行移动了。
使placeholder可以跟随拖拽节点运动
本节是要讲占位节点(placeholder阴影部分)跟随拖拽节点一起移动。主要思路是:
通过拖拽节点距离容器的偏移(drag方法中的x, y),可以将其转化为对应网格的坐标。
转化后的坐标如果发生变化,则更新占位节点的坐标。
drag方法中增加的代码如下:
// 坐标转换
const nodeX = Math.round(x / opt.cellW);
const nodeY = Math.round(y / opt.cellH);
let currentNode = this.dragrid.currentNode;
// 发生移动
if(currentNode.x !== nodeX || currentNode.y !== nodeY) {
currentNode.x = nodeX;
currentNode.y = nodeY;
}nodes重排及上移
本节核心点有两个:
用一个二维数组来表示网格,这样节点的位置信息就可以在此二维数组中标记出来了。
nodes中只要某个节点发生变化,就要重新排版,要将每个节点尽可能地上移。
二维数组的构建
getArea(nodes) {
let area = [];
nodes.forEach(n => {
for(let row = n.y; row < n.y + n.h; row++){
let rowArr = area[row];
if(rowArr === undefined){
area[row] = new Array();
}
for(let col = n.x; col < n.x + n.w; col++){
area[row][col] = n.id;
}
}
});
return area;
}按需可以动态扩展该二维数据,如果某行没有任何节点占位,则实际存储的是一个undefined值。否则存储的是节点的id值。
布局方法
dragird.vue中watch了nodes,发生变化后会调用layout方法,代码如下:
/**
* 重新布局
* 只要有一个节点发生变化,就要重新进行排版布局
*/
layout() {
this.nodes.forEach(n => {
const y = this.moveup(n);
if(y < n.y){
n.y = y;
}
});
},
// 向上查找节点可以冒泡到的位置
moveup(node) {
let area = this.area;










