for(let row = node.y - 1; row > 0; row--){
// 如果一整行都为空,则直接继续往上找
if(area[row] === undefined) continue;
for(let col = node.x; col < node.x + node.w; col++){
// 改行如果有内容,则直接返回下一行
if(area[row][col] !== undefined){
return row + 1;
}
}
}
return 0;
}
布局方法layout中遍历所有节点,moveup方法返回该节点纵向可以上升到的位置坐标,如果比实际坐标小,则进行上移。moveup方法默认从上一行开始找,直到发现二维数组中存放了值(改行已经有元素了),则返回此时行数加1。
到这里,拖拽节点移动时,占位节点会尽可能地上移,如果只有一个节点,那么占位节点一直在最上面移动。
相关节点的下移
拖拽节点移动时,与拖拽节点发生碰撞的节点及其下发的节点,都先下移一定距离,这样拖拽节点就可以移到相应位置,最后节点都会发生上一节所说的上移。
请看dragrid.vue中的overlap方法:
overlap(node) {
// 下移节点
this.nodes.forEach(n => {
if(node !== n && n.y + n.h > node.y) {
n.y += node.h;
}
});
}n.y + n.h > node.y 表示可以与拖拽节点发生碰撞,以及在拖拽节点下方的节点。
在dragdrop.drag中会调用该方法。
注意目前该方法会有问题,没有考虑到如果碰撞节点比较高,则 n.y += node.h 并没有将该节点下沉到拖拽节点下方,从而拖拽节点会叠加上去。后面会介绍解决方法。
缩放
上面的思路都理解之后,缩放其实也是一样的,主要还是要进行坐标转换,坐标发生变化后,就会调用overlap方法。
resize(event) {
const opt = this.dragrid.cfg;
// 之前
const x1 = this.currentNode.x * opt.cellW + this.offsetX,
y1 = this.currentNode.y * opt.cellH + this.offsetY;
// 之后
const x2 = event.pageX - this.containerOffset.left,
y2 = event.pageY - this.containerOffset.top;
// 偏移
const dx = x2 - x1, dy = y2 - y1;
// 新的节点宽和高
const w = this.currentNode.w * opt.cellW + dx,
h = this.currentNode.h * opt.cellH + dy;
// 样式设置
this.dragElement.style.cssText += ';width:' + w + 'px;height:' + h + 'px;';
// 坐标转换
const nodeW = Math.round(w / opt.cellW);
const nodeH = Math.round(h / opt.cellH);
let currentNode = this.dragrid.currentNode;
// 发生移动
if(currentNode.w !== nodeW || currentNode.h !== nodeH) {
currentNode.w = nodeW;
currentNode.h = nodeH;
this.dragrid.overlap(currentNode);
}
}根据鼠标距拖拽容器的距离的偏移,来修改节点的大小(宽和高),其中x1为鼠标点击后距离容器的距离,x2为移动一段距离之后距离容器的距离,那么差值dx就为鼠标移动的距离,dy同理。










