JS 拖拽对齐参考线+自动吸附+对齐到网格

具体代码参见:https://github.com/yyccmmkk/js-reference-line

 

【需求】

对一个元素进行拖拽时,生成这个组件和其它组件对齐的参考线,实现各组件间四条边及水平中心线及垂直中心线对齐。在拖动完成后实现自动吸附对齐。

【解决思路】

1 MAP记录所有需要对齐组件的视窗坐标点(左上,右上,左下,右下)

2 P为当前拖拽对象实时的坐标点(左上,左下,右上,右下,中心点)

3 拿当前对象的坐标点P去匹配座标记录MAP

4 发现某一边对齐时,在canvas中画线,清除画布的操作应该在拖动时进行处理,

问题的关键在于如何快速的去计算当前组件的6条线(四边+中心线)和其它所有组件6条线在一条线上,看似麻烦其实可以简化逻辑为,只要判断三个点,左上角、右下角、中心点,在记录中有没有存在

  1. 如何判断两个组件垂直对齐?答:坐标x一样
  2. 如何判断两个组件水平对齐?答:坐标Y一样
  3. 如何记录坐标点便于查询
  4. 根据坐标画线

【答:3】

创建一个数组 tempArry 存放所有的坐标对象(包含座标信息),像下边这样

let tempArray=[
        {let:1,right:100,top:10,bottom:400},
        {let:2,right:200,top:20,bottom:600},
        {let:1,right:300,top:30,bottom:400}
        ];

创建两个对象mapX 、mapY。对tempArray 进行遍历,mapX mapY 分别以x ,y 为key。 值为数组(ps:因为有可能多个组件 坐标是相同的),数组保存了坐标对象在tempArray中的索引。

mapX 记录所有组件的坐标x,每个组件三个x坐标(ps:左、中、右),结果如下

let mapX={
        1:[0,2],
        2:[1],
        50.5:[0],
        101:[1],
        150.5:[2],
        100:[0],
        200:[1],
        300:[2]
    };

mapY 记录所有组件的坐标y,每个组件有三个坐标y(ps:上、中、下),结果如下

let mapY={
        10:[0],
        205:[0],
        310:[1],
        215:[2],
        20:[1],
        30:[2],
        400:[0,2],
        600:[1],

    }

 

假设有一组件视窗坐标为(left:1,right:600,top:20,bottom:300);

通过判断左上角坐标点(p1) 就可以检测组件左边与上边的对齐,通过右下角坐标点(p2),就可以检测组件 右边与下边的对齐,对过中心坐标(p3)就可以找到水平与垂直线的对齐。

p1 x:1,y:20

p2 x:600,y:300

p3 x:300.5,y:160

mapX 中存在以x 为值的key 就证明有垂直对齐的线,

mapY 中存在以 y为值 的key 就证明有水平对齐的线

通过map 中的值索引可以快速拿到对应的对齐组件信息,把当前组件的坐标点信息扔进去,取最大最小值就可以拿到对齐线的坐标信息,详见源码,大概思路是这样,其中还涉及一些细节,比如排自身的坐标信息等。

【自动吸附】

移动中的自动吸附功能不但性能开销高而且相对来说比较复杂,暂时开发为在拖动完成后进行自动吸附操作。

对于自动吸附可以抒理一下子功能点,

1 在吸附范围内找到符合的坐标点,也就是说 目标点坐标 (有3个目标点坐标)减掉当前座标点 绝对值不大于吸附范围

2 在前边的功能中只要找到三个点就可以,所以吸附功能也要找到当前元素的这三个点坐标 及吸附范围 坐标

3 需要区分的是当前元素的哪条边对齐了,因为操作作当前元素样式时,如果底边或右侧的边对齐了需要减掉元素自身的宽或高

4 需要知道当前移动的方向,当用户在远离在吸附范围内的元素时不要吸附

具体的实现细节详见代码

【对齐到网格】

对齐到网格更简单,在之前的基础上把网格坐标放入需要吸附到的坐点数组里即可,生成网格x,y坐标放入,具体详见源码

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值