请大家动动小手,给我一个免费的 Star 吧~
大家如果发现了 Bug,欢迎来提 Issue 哟~
不知不觉来到第 10 章了,感觉接近尾声了。。。
对齐线
先看效果:
这里交互有两个部分:
1、节点之间的对齐线
2、对齐磁贴
多选的情况下,效果是一样的:
主要逻辑会放在控制“选择”的代码文件里:
src\Render\handlers\SelectionHandlers.ts
这里需要一些辅助都定义:
interface SortItem {
id?: number // 有 id 就是其他节点,否则就是 选择目标
value: number // 左、垂直中、右的 x 坐标值; 上、水平中、下的 y 坐标值;
}
type SortItemPair = [SortItem, SortItem]
尝试画个图说明一下上面的含义:
这里以纵向(基于 x 坐标值)为例:
这里的 x1~x9,就是 SortItem,横向(基于 y 坐标值)同理,特别地,如果是正在拖动的目标节点,会把该节点的 _id 记录在 SortItem 以示区分。
会存在一个处理,把一个方向上的所有 x 坐标进行从小到大的排序,然后一双一双的遍历,需要符合以下条件“必须分别属于相邻的两个节点”的 SortItem 对,也就是 SortItemPair。
在查找所有 SortItemPair 的同时,只会更新并记录节点距离最短的那些 SortItemPair(可能会存在多个)。
核心逻辑代码:
// 磁吸逻辑
attract = (newPos: Konva.Vector2d) => {
// 对齐线清除
this.alignLinesClear()
// stage 状态
const stageState = this.render.getStageState()
const width = this.render.transformer.width()
const height = this.render.transformer.height()
let newPosX = newPos.x
let newPosY = newPos.y
let isAttract = false
let pairX: SortItemPair | null = null
let pairY: SortItemPair | null = null
// 对齐线 磁吸逻辑
if (this.render.config.attractNode) {
// 横向所有需要判断对齐的 x 坐标
const sortX: Array<SortItem> = []
// 纵向向所有需要判断对齐的 y 坐标
const sortY: Array<SortItem> = []
// 选择目标所有的对齐 x
sortX.push(
{
value: this.render.toStageValue(newPos.x - stageState.x) // 左
},
{
value: this.render.toStageValue(newPos.x - stageState.x + width / 2) // 垂直中
},
{
value: this.render.toStageValue(newPos.x - stageState.x + width) // 右
}
)
// 选择目标所有的对齐 y
sortY.push(
{
value: this.render.toStageValue(newPos.y - stageState.y) // 上
},
{
value: this.render.toStageValue(newPos.y - stageState.y + height / 2) // 水平中