辅助线功能开发

更新时间: 2021-08-04 09:13:01

辅助线功能大概的思路是当同一个父元素中的Accelerator实例超过两个时,移动到两个实例的坐标相同时显示出辅助线,原本这个功能应该是和吸附一起使用的,不过我打算先写辅助线,因为没有写吸附,所以辅助线出现的条件会比较困难,效果如下:

# 原理分析

写辅助线就必须要知道当前所以的Accelerator实例的位置信息,之前将所有实例都存在了Accelerator._instanceList中,现在正好派上用场。

最多的时候会出现六条辅助线:

其中横线三条,竖线三条,也就是图中的x1,x2,x3和y1,y2,y3。

这六条线的坐标相当好算,假设当前正在移动的实例为current:

x1 = current.x
x2 = current.x + (current.width / 2)
x3 = current.x + current.width
y1 = current.y
y2 = current.y + (current.height / 2)
y3 = current.y + current.height

然后图中所有的绿色的点都要分别和x1,x2,x3,y1,y2,y3对比,得到x或者y坐标一致的点,例如:

设x1 = 10,图中和x1的x坐标相等的点一共有6个,假设分别是 (10,0),(10,10),(10,20),(10,25),(10,35),(10,45)即最左侧的六个绿色点,那么x1这条线x坐标为10,y应该是从0开始,45结束。另外5条线也是同理。

# 步骤

代码就懒得放了,直接说一下过程吧:

  1. 首先检测一下同一个父元素下的实例有没有超过两个,如过有两个或两个以上才会往后计算参考线
  2. 计算六条辅助线的x或y坐标,即x1,x2,x3,y1,y2,y3
  3. 将每个的实例的坐标抽象成图中绿点标出的8个点
  4. 将所有的绿点和x1,x2,x3,y1,y2,y3分别对比,找到x或y相等的点
  5. 计算参考线的起始位置,找出第五个步骤得到的点位的x或y坐标的最小值和最大值,这个值就是参考线的起始位置
  6. 往父元素中添加六条参考线,并实时更改它们的属性

# 代码

算咯,我还是放一下代码吧。。虽然菜得抠脚。。我以后一定认真学算法!!

import { getPoints } from '../utils/common'

/**
     * 在domEl移动过程中计算对齐的点
     */
 export function countAxisLine() {
    //首先把同父元素下,除了当前移动中的所有实例的参考点打印出来
    const pointList = []  //所有被对比的点
    const xLine = [
        {
            value:this.x,
            list:[]
        },
        {
            value:this.xCenter,
            list:[]
        },
        {
            value:this.x1,
            list:[]
        }
    ]
    const yLine = [
        {
            value:this.y,
            list:[]
        },
        {
            value:this.yCenter,
            list:[]
        },
        {
            value:this.y1,
            list:[]
        }
    ]
    if(!this.parentEl.querySelector('.ac_line')){
        for(let i = 0;i < 3;i++) {
            const el = document.createElement('div')
            el.classList = 'ac_line x_line x_line_'+i
            el.style.cssText = 'background:blue;width:1px;position:absolute;display:none;z-index:9999;'
            this.parentEl.appendChild(el)
            const el1 = document.createElement('div')
            el1.classList = 'ac_line y_line y_line_'+i
            el1.style.cssText = 'background:blue;height:1px;position:absolute;display:none;z-index:9999;'
            this.parentEl.appendChild(el1)
        }
    }
    if(this.constructor._instanceList.length < 2) {
        return false
    }
    for(let i = 0;i< this.constructor._instanceList.length; i++) {
        const instance = this.constructor._instanceList[i]
        if(instance.parentEl === this.parentEl && instance.id !== this.id) {
            pointList.push(...getPoints(instance))
        }
    }
    if(pointList.length > 0) {
        pointList.push(...getPoints(this))
    }else{
        return false
    }
    for(let i = 0; i < xLine.length; i++) {
        const value = xLine[i].value
        for(let j = 0;j<pointList.length; j++) {
            if(value === pointList[j].x) {
                xLine[i].list.push(pointList[j])
            }
        }
    }
    for(let i = 0; i < yLine.length; i++) {
        const value = yLine[i].value
        for(let j = 0;j<pointList.length; j++) {
            if(value === pointList[j].y) {
                yLine[i].list.push(pointList[j])
            }
        }
    }
    
    //list中的数据必须大于4条才算有效
    for(let i = 0;i < xLine.length; i++) {
        if(xLine[i].list.length >= 4) {
            const xPos = xLine[i].value
            const yList = xLine[i].list.map(item => item.y)
            const yPos1 = Math.min(...yList)
            const yPos2 = Math.max(...yList)
            const line = this.parentEl.querySelector('.x_line_'+i)
            line.style.left = xPos + 'px'
            line.style.top = yPos1 + 'px'
            line.style.height = (yPos2 - yPos1) + 'px'
            line.style.display = 'block'
        }else{
            const line = this.parentEl.querySelector('.x_line_'+i)
            line.style.display = 'none'
        }
    }

    for(let i = 0;i < yLine.length; i++) {
        if(yLine[i].list.length >= 4) {
            const yPos = yLine[i].value
            const xList = yLine[i].list.map(item => item.x)
            const xPos1 = Math.min(...xList)
            const xPos2 = Math.max(...xList)
            const line = this.parentEl.querySelector('.y_line_'+i)
            line.style.top = yPos + 'px'
            line.style.left = xPos1 + 'px'
            line.style.width = (xPos2 - xPos1) + 'px'
            line.style.display = 'block'
        }else{
            const line = this.parentEl.querySelector('.y_line_'+i)
            line.style.display = 'none'
        }
    }
}

export function hideAxisLine() {
    for(let i = 0;i < 3; i++) {
        const line = this.parentEl.querySelector('.x_line_'+i)
        line.style.display = 'none'
    }

    for(let i = 0;i < 3; i++) {
        const line = this.parentEl.querySelector('.y_line_'+i)
        line.style.display = 'none'
    }
}

export function registerAxis(_this) {
    _this.countAxisLine = countAxisLine.bind(_this)
    _this.hideAxisLine = hideAxisLine.bind(_this)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

实例化Accelerator的时候调用registerAxis, 然后在移动元素或者缩放的时候调用countAxisLine,需要隐藏参考线的时候调用hideAxisLine就可以了,ok,今天下午写吸附