欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

视觉编辑器的辅助线生成和自动吸收原理分析

最编程 2024-06-01 10:24:29
...

src=http___n.sinaimg.cn_sinacn20191220ac_222_w2048h574_20191220_2a56-ikyziqw8496273.jpg&refer=http___n.sinaimg.webp

有生之年的死神千年血战篇镇楼

背景

之前公司开发了一款可视化编辑器,由于之前开发匆忙,辅助线的功能模块做的不是很完善,并且没有吸附功能。近日正好有时间,把生成逻辑重写优化了一下,并增加了吸附功能,在此分享一下实现的原理。

本文分析要点

  1. 辅助线生成逻辑
  2. 辅助线显示优化
  3. 辅助线吸附逻辑

效果展示

gif.gif

一.辅助线生成原理

iShot_2022-10-26_09.44.17.png

  1. 首先我们要知道,辅助线就是为了方便对齐某个元素而生成的参考线,看上图
  2. 通常我们会对一个元素的 左、中、右,上、中、下 六个位置进行对齐,也就是图中的ABC(纵向)、DEF(横向)六条线
  3. 知道要生成哪些线,逻辑就清晰了,我们只需要在拖拽元素时,获取要对齐元素的六个点,然后创建对应的辅助线就行。

企业微信截图_30de8598-74c8-4511-9fe4-394147568c0a.png

伪代码(仅用于简述原理,文章最后会附上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) //创建横向辅助线
})

二、辅助线生成优化

在实际应用过程中,一个画布中会有很多元素,如果不做任何处理,生成出来的辅助线会非常多,下方绿色的是纵向的辅助线,如果加上横向的,你甚至怀疑创建的不是辅助线,而是网格 ???? iShot_2022-10-26_10.21.20.png

针对以上情况,需要在创建时做相应的处理优化。

伪代码

// 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梳理逻辑用的,毫无优雅可言,大家仅参考实现逻辑就行

相关文章

  • 可视化编辑器 之 元素拖拽位置、大小、旋转解析
  • 可视化编辑器 之 多元素组合功能解析