视觉编辑器的辅助线生成和自动吸收原理分析
最编程
2024-06-01 10:24:29
...
有生之年的死神千年血战篇镇楼
背景
之前公司开发了一款可视化编辑器,由于之前开发匆忙,辅助线的功能模块做的不是很完善,并且没有吸附功能。近日正好有时间,把生成逻辑重写优化了一下,并增加了吸附功能,在此分享一下实现的原理。
本文分析要点
- 辅助线生成逻辑
- 辅助线显示优化
- 辅助线吸附逻辑
效果展示
一.辅助线生成原理
- 首先我们要知道,辅助线就是为了方便对齐某个元素而生成的参考线,看上图
- 通常我们会对一个元素的 左、中、右,上、中、下 六个位置进行对齐,也就是图中的ABC(纵向)、DEF(横向)六条线
- 知道要生成哪些线,逻辑就清晰了,我们只需要在拖拽元素时,获取要对齐元素的六个点,然后创建对应的辅助线就行。
伪代码(仅用于简述原理,文章最后会附上demo)
// 1.拖动元素时,获取要对齐元素的六个点
// 假如橙框的尺寸为 100* 100, left、top也都是100
let lineX = [left, left+width/2, left+width]; // ABC坐标点 [100,150,200]
let lineY = [top, top+height/2, top+height]; // DEF坐标点 [100,150,200]
// 2.循环lineX、lineY创建辅助线
lineX.forEach(item => {
createVerticalLine(item) //创建纵向辅助线
})
lineY.forEach(item => {
createHorizontalLine(item) //创建横向辅助线
})
二、辅助线生成优化
在实际应用过程中,一个画布中会有很多元素,如果不做任何处理,生成出来的辅助线会非常多,下方绿色的是纵向的辅助线,如果加上横向的,你甚至怀疑创建的不是辅助线,而是网格 ????
针对以上情况,需要在创建时做相应的处理优化。
伪代码
// 1.在拖拽元素的过程中,实时获取拖动元素的坐标点,获取方式同之前一样,只不过拖拽元素的left、top是实时变化的
let selfX = [left, left+width/2, left+width];
let selfY = [top, top+height/2, top+height];
let distance = 10; //辅助线展示、吸附的距离
// 2.在创建辅助线的过程中,对返回所有创建的辅助线,然后取最近的一条进行创建
let arrX = [];
selfX.forEach(self => {
lineX.forEach(other => {
if( Math.abs(self - other) <= distance){
arrX.push(other)
}
})
})
createVerticalLine(Math.min(arrX)) //取离拖拽元素最近的一条创建(横向同理)
三.辅助线吸附逻辑
达到预先设置的吸附距离后,直接将拖拽元素位置设置到对应的坐标点。
设置拖拽元素位置时,要注意判断是拖拽元素的哪个点与辅助线对齐。
以横向吸附举例:
1.如拖拽元素的最左侧与辅助线最先接近,则直接设置拖拽元素的left值为辅助线的位置就行
2.如果是中心点与辅助线接近,则用辅助线的位置 - 拖拽元素宽度的一半设置left
3.如果是最右侧与辅助线接近,则用辅助线的位置 - 拖拽元素的宽度设置left
有一个注意的点就是,元素在旋转后,尺寸会发生变化,需要通过三角函数计算旋转后的元素尺寸,再进行相应的计算,大家可以看下我写的demo
四、DEMO
以下是我在重做功能前,在本地写的一个简单demo梳理逻辑用的,毫无优雅可言,大家仅参考实现逻辑就行
相关文章
- 可视化编辑器 之 元素拖拽位置、大小、旋转解析
- 可视化编辑器 之 多元素组合功能解析
推荐阅读