@nokecy/designer-shared 0.0.0-stage → 2.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE.md +21 -0
  3. package/PROVENANCE.json +35 -0
  4. package/README.md +9 -2
  5. package/esm/animation.d.ts +2 -0
  6. package/esm/animation.js +34 -0
  7. package/esm/animation.js.map +1 -0
  8. package/esm/array.d.ts +37 -0
  9. package/esm/array.js +112 -0
  10. package/esm/array.js.map +1 -0
  11. package/esm/clone.d.ts +4 -0
  12. package/esm/clone.js +106 -0
  13. package/esm/clone.js.map +1 -0
  14. package/esm/compose.d.ts +1 -0
  15. package/esm/compose.js +8 -0
  16. package/esm/compose.js.map +1 -0
  17. package/esm/coordinate.d.ts +106 -0
  18. package/esm/coordinate.js +485 -0
  19. package/esm/coordinate.js.map +1 -0
  20. package/esm/element.d.ts +6 -0
  21. package/esm/element.js +138 -0
  22. package/esm/element.js.map +1 -0
  23. package/esm/event.d.ts +81 -0
  24. package/esm/event.js +214 -0
  25. package/esm/event.js.map +1 -0
  26. package/esm/globalThisPolyfill.d.ts +1 -0
  27. package/esm/globalThisPolyfill.js +23 -0
  28. package/esm/globalThisPolyfill.js.map +1 -0
  29. package/esm/index.d.ts +17 -0
  30. package/esm/index.js +18 -0
  31. package/esm/index.js.map +1 -0
  32. package/esm/instanceof.d.ts +1 -0
  33. package/esm/instanceof.js +12 -0
  34. package/esm/instanceof.js.map +1 -0
  35. package/esm/keycode.d.ts +147 -0
  36. package/esm/keycode.js +151 -0
  37. package/esm/keycode.js.map +1 -0
  38. package/esm/lru.d.ts +73 -0
  39. package/esm/lru.js +294 -0
  40. package/esm/lru.js.map +1 -0
  41. package/esm/observer.d.ts +9 -0
  42. package/esm/observer.js +30 -0
  43. package/esm/observer.js.map +1 -0
  44. package/esm/request-idle.d.ts +10 -0
  45. package/esm/request-idle.js +9 -0
  46. package/esm/request-idle.js.map +1 -0
  47. package/esm/scroller.d.ts +10 -0
  48. package/esm/scroller.js +83 -0
  49. package/esm/scroller.js.map +1 -0
  50. package/esm/subscribable.d.ts +14 -0
  51. package/esm/subscribable.js +49 -0
  52. package/esm/subscribable.js.map +1 -0
  53. package/esm/types.d.ts +13 -0
  54. package/esm/types.js +22 -0
  55. package/esm/types.js.map +1 -0
  56. package/esm/uid.d.ts +1 -0
  57. package/esm/uid.js +10 -0
  58. package/esm/uid.js.map +1 -0
  59. package/lib/animation.d.ts +2 -0
  60. package/lib/animation.js +39 -0
  61. package/lib/animation.js.map +1 -0
  62. package/lib/array.d.ts +37 -0
  63. package/lib/array.js +126 -0
  64. package/lib/array.js.map +1 -0
  65. package/lib/clone.d.ts +4 -0
  66. package/lib/clone.js +111 -0
  67. package/lib/clone.js.map +1 -0
  68. package/lib/compose.d.ts +1 -0
  69. package/lib/compose.js +12 -0
  70. package/lib/compose.js.map +1 -0
  71. package/lib/coordinate.d.ts +106 -0
  72. package/lib/coordinate.js +514 -0
  73. package/lib/coordinate.js.map +1 -0
  74. package/lib/element.d.ts +6 -0
  75. package/lib/element.js +146 -0
  76. package/lib/element.js.map +1 -0
  77. package/lib/event.d.ts +81 -0
  78. package/lib/event.js +219 -0
  79. package/lib/event.js.map +1 -0
  80. package/lib/globalThisPolyfill.d.ts +1 -0
  81. package/lib/globalThisPolyfill.js +26 -0
  82. package/lib/globalThisPolyfill.js.map +1 -0
  83. package/lib/index.d.ts +17 -0
  84. package/lib/index.js +34 -0
  85. package/lib/index.js.map +1 -0
  86. package/lib/instanceof.d.ts +1 -0
  87. package/lib/instanceof.js +16 -0
  88. package/lib/instanceof.js.map +1 -0
  89. package/lib/keycode.d.ts +147 -0
  90. package/lib/keycode.js +155 -0
  91. package/lib/keycode.js.map +1 -0
  92. package/lib/lru.d.ts +73 -0
  93. package/lib/lru.js +298 -0
  94. package/lib/lru.js.map +1 -0
  95. package/lib/observer.d.ts +9 -0
  96. package/lib/observer.js +34 -0
  97. package/lib/observer.js.map +1 -0
  98. package/lib/request-idle.d.ts +10 -0
  99. package/lib/request-idle.js +14 -0
  100. package/lib/request-idle.js.map +1 -0
  101. package/lib/scroller.d.ts +10 -0
  102. package/lib/scroller.js +89 -0
  103. package/lib/scroller.js.map +1 -0
  104. package/lib/subscribable.d.ts +14 -0
  105. package/lib/subscribable.js +53 -0
  106. package/lib/subscribable.js.map +1 -0
  107. package/lib/types.d.ts +13 -0
  108. package/lib/types.js +30 -0
  109. package/lib/types.js.map +1 -0
  110. package/lib/uid.d.ts +1 -0
  111. package/lib/uid.js +13 -0
  112. package/lib/uid.js.map +1 -0
  113. package/package.json +46 -4
  114. package/src/animation.ts +38 -0
  115. package/src/array.ts +301 -0
  116. package/src/clone.ts +105 -0
  117. package/src/compose.ts +7 -0
  118. package/src/coordinate.ts +640 -0
  119. package/src/element.ts +144 -0
  120. package/src/event.ts +395 -0
  121. package/src/globalThisPolyfill.ts +19 -0
  122. package/src/index.ts +17 -0
  123. package/src/instanceof.ts +10 -0
  124. package/src/keycode.ts +150 -0
  125. package/src/lru.ts +322 -0
  126. package/src/observer.ts +38 -0
  127. package/src/request-idle.ts +22 -0
  128. package/src/scroller.ts +113 -0
  129. package/src/subscribable.ts +60 -0
  130. package/src/types.ts +27 -0
  131. package/src/uid.ts +10 -0
@@ -0,0 +1,640 @@
1
+ import { isValidNumber } from './types'
2
+ export interface IPoint {
3
+ x: number
4
+ y: number
5
+ }
6
+
7
+ export interface ISize {
8
+ width: number
9
+ height: number
10
+ }
11
+
12
+ export interface ILineSegment {
13
+ start: IPoint
14
+ end: IPoint
15
+ }
16
+
17
+ export interface IRectEdgeLines {
18
+ v: ILineSegment[]
19
+ h: ILineSegment[]
20
+ }
21
+
22
+ export function isRect(rect: any): rect is IRect {
23
+ return rect?.x && rect?.y && rect?.width && rect?.height
24
+ }
25
+
26
+ export function isPoint(val: any): val is IPoint {
27
+ return isValidNumber(val?.x) && isValidNumber(val?.y)
28
+ }
29
+
30
+ export function isLineSegment(val: any): val is ILineSegment {
31
+ return isPoint(val?.start) && isPoint(val?.end)
32
+ }
33
+
34
+ export class Point implements IPoint {
35
+ x: number
36
+ y: number
37
+ constructor(x?: number, y?: number) {
38
+ this.x = x || 0
39
+ this.y = y || 0
40
+ }
41
+ }
42
+
43
+ export class Rect implements IRect {
44
+ x = 0
45
+ y = 0
46
+ width = 0
47
+ height = 0
48
+ constructor(x: number, y: number, width?: number, height?: number) {
49
+ this.x = x
50
+ this.y = y
51
+ this.width = width || 0
52
+ this.height = height || 0
53
+ }
54
+
55
+ get left() {
56
+ return this.x
57
+ }
58
+
59
+ get right() {
60
+ return this.x + this.width
61
+ }
62
+
63
+ get top() {
64
+ return this.y
65
+ }
66
+
67
+ get bottom() {
68
+ return this.y + this.height
69
+ }
70
+ }
71
+
72
+ export class LineSegment {
73
+ start: IPoint
74
+ end: IPoint
75
+ constructor(start: IPoint, end: IPoint) {
76
+ this.start = { ...start }
77
+ this.end = { ...end }
78
+ }
79
+ }
80
+
81
+ export interface IRect {
82
+ x: number
83
+ y: number
84
+ width: number
85
+ height: number
86
+ }
87
+
88
+ export enum RectQuadrant {
89
+ Inner1 = 'I1', //内部第一象限
90
+ Inner2 = 'I2', //内部第二象限
91
+ Inner3 = 'I3', //内部第三象限
92
+ Inner4 = 'I4', //内部第四象限
93
+ Outer1 = 'O1', //内部第五象限
94
+ Outer2 = 'O2', //内部第六象限
95
+ Outer3 = 'O3', //内部第七象限
96
+ Outer4 = 'O4', //内部第八象限
97
+ }
98
+
99
+ export interface IPointToRectRelative {
100
+ quadrant: RectQuadrant
101
+ distance: number
102
+ }
103
+
104
+ export function isPointInRect(point: IPoint, rect: IRect, sensitive = true) {
105
+ const boundSensor = (value: number) => {
106
+ if (!sensitive) return 0
107
+ const sensor = value * 0.1
108
+ if (sensor > 20) return 20
109
+ if (sensor < 10) return 10
110
+ return sensor
111
+ }
112
+
113
+ return (
114
+ point.x >= rect.x + boundSensor(rect.width) &&
115
+ point.x <= rect.x + rect.width - boundSensor(rect.width) &&
116
+ point.y >= rect.y + boundSensor(rect.height) &&
117
+ point.y <= rect.y + rect.height - boundSensor(rect.height)
118
+ )
119
+ }
120
+
121
+ export function isEqualRect(target?: IRect, source?: IRect) {
122
+ return (
123
+ target &&
124
+ source &&
125
+ target.x === source.x &&
126
+ target.y === source.y &&
127
+ target.width === source.width &&
128
+ target.height === source.height
129
+ )
130
+ }
131
+
132
+ export function getRectPoints(source: IRect) {
133
+ const p1 = new Point(source.x, source.y)
134
+ const p2 = new Point(source.x + source.width, source.y)
135
+ const p3 = new Point(source.x + source.width, source.y + source.height)
136
+ const p4 = new Point(source.x, source.y + source.height)
137
+ return [p1, p2, p3, p4]
138
+ }
139
+
140
+ export function isRectInRect(target: IRect, source: IRect) {
141
+ const [p1, p2, p3, p4] = getRectPoints(target)
142
+ return (
143
+ isPointInRect(p1, source, false) &&
144
+ isPointInRect(p2, source, false) &&
145
+ isPointInRect(p3, source, false) &&
146
+ isPointInRect(p4, source, false)
147
+ )
148
+ }
149
+
150
+ export function isCrossRectInRect(target: IRect, source: IRect) {
151
+ const targetCenterPoint = new Point(
152
+ target.x + target.width / 2,
153
+ target.y + target.height / 2
154
+ )
155
+ const sourceCenterPoint = new Point(
156
+ source.x + source.width / 2,
157
+ source.y + source.height / 2
158
+ )
159
+ return (
160
+ Math.abs(targetCenterPoint.x - sourceCenterPoint.x) <=
161
+ target.width / 2 + source.width / 2 &&
162
+ Math.abs(targetCenterPoint.y - sourceCenterPoint.y) <=
163
+ target.height / 2 + source.height / 2
164
+ )
165
+ }
166
+
167
+ /**
168
+ * 计算点在矩形的哪个象限
169
+ * @param point
170
+ * @param rect
171
+ */
172
+ export function calcQuadrantOfPointToRect(point: IPoint, rect: IRect) {
173
+ const isInner = isPointInRect(point, rect)
174
+ if (point.x <= rect.x + rect.width / 2) {
175
+ if (point.y <= rect.y + rect.height / 2) {
176
+ if (isInner) {
177
+ return RectQuadrant.Inner1
178
+ } else {
179
+ return RectQuadrant.Outer1
180
+ }
181
+ } else {
182
+ if (isInner) {
183
+ return RectQuadrant.Inner4
184
+ } else {
185
+ return RectQuadrant.Outer4
186
+ }
187
+ }
188
+ } else {
189
+ if (point.y <= rect.y + rect.height / 2) {
190
+ if (isInner) {
191
+ return RectQuadrant.Inner2
192
+ } else {
193
+ return RectQuadrant.Outer2
194
+ }
195
+ } else {
196
+ if (isInner) {
197
+ return RectQuadrant.Inner3
198
+ } else {
199
+ return RectQuadrant.Outer3
200
+ }
201
+ }
202
+ }
203
+ }
204
+
205
+ export function calcDistanceOfPointToRect(point: IPoint, rect: IRect) {
206
+ let minX = Math.min(
207
+ Math.abs(point.x - rect.x),
208
+ Math.abs(point.x - (rect.x + rect.width))
209
+ )
210
+ let minY = Math.min(
211
+ Math.abs(point.y - rect.y),
212
+ Math.abs(point.y - (rect.y + rect.height))
213
+ )
214
+ if (point.x >= rect.x && point.x <= rect.x + rect.width) {
215
+ minX = 0
216
+ }
217
+ if (point.y >= rect.y && point.y <= rect.y + rect.height) {
218
+ minY = 0
219
+ }
220
+
221
+ return Math.sqrt(minX ** 2 + minY ** 2)
222
+ }
223
+
224
+ export function calcDistancePointToEdge(point: IPoint, rect: IRect) {
225
+ const distanceTop = Math.abs(point.y - rect.y)
226
+ const distanceBottom = Math.abs(point.y - (rect.y + rect.height))
227
+ const distanceLeft = Math.abs(point.x - rect.x)
228
+ const distanceRight = Math.abs(point.x - (rect.x + rect.width))
229
+ return Math.min(distanceTop, distanceBottom, distanceLeft, distanceRight)
230
+ }
231
+
232
+ export function isNearAfter(point: IPoint, rect: IRect, inline = false) {
233
+ if (inline) {
234
+ return (
235
+ Math.abs(point.x - rect.x) + Math.abs(point.y - rect.y) >
236
+ Math.abs(point.x - (rect.x + rect.width)) +
237
+ Math.abs(point.y - (rect.y + rect.height))
238
+ )
239
+ }
240
+ return Math.abs(point.y - rect.y) > Math.abs(point.y - (rect.y + rect.height))
241
+ }
242
+
243
+ /**
244
+ * 计算点鱼矩形的相对位置信息
245
+ * @param point
246
+ * @param rect
247
+ */
248
+ export function calcRelativeOfPointToRect(
249
+ point: IPoint,
250
+ rect: IRect
251
+ ): IPointToRectRelative {
252
+ const distance = calcDistanceOfPointToRect(point, rect)
253
+ const quadrant = calcQuadrantOfPointToRect(point, rect)
254
+ return {
255
+ quadrant,
256
+ distance,
257
+ }
258
+ }
259
+
260
+ export function calcBoundingRect(rects: IRect[]) {
261
+ if (!rects?.length) return
262
+ if (rects?.length === 1 && !rects[0]) return
263
+ let minTop = Infinity
264
+ let maxBottom = -Infinity
265
+ let minLeft = Infinity
266
+ let maxRight = -Infinity
267
+ rects.forEach((item) => {
268
+ const rect = new Rect(item.x, item.y, item.width, item.height)
269
+ if (rect.top <= minTop) {
270
+ minTop = rect.top
271
+ }
272
+ if (rect.bottom >= maxBottom) {
273
+ maxBottom = rect.bottom
274
+ }
275
+ if (rect.left <= minLeft) {
276
+ minLeft = rect.left
277
+ }
278
+ if (rect.right >= maxRight) {
279
+ maxRight = rect.right
280
+ }
281
+ })
282
+ return new Rect(minLeft, minTop, maxRight - minLeft, maxBottom - minTop)
283
+ }
284
+
285
+ export function calcRectByStartEndPoint(
286
+ startPoint: IPoint,
287
+ endPoint: IPoint,
288
+ scrollX = 0,
289
+ scrollY = 0
290
+ ) {
291
+ let drawStartX = 0,
292
+ drawStartY = 0
293
+ if (
294
+ endPoint.x + scrollX >= startPoint.x &&
295
+ endPoint.y + scrollY >= startPoint.y
296
+ ) {
297
+ //4象限
298
+ drawStartX = startPoint.x
299
+ drawStartY = startPoint.y
300
+ return new Rect(
301
+ drawStartX - scrollX,
302
+ drawStartY - scrollY,
303
+ Math.abs(endPoint.x - startPoint.x + scrollX),
304
+ Math.abs(endPoint.y - startPoint.y + scrollY)
305
+ )
306
+ } else if (
307
+ endPoint.x + scrollX < startPoint.x &&
308
+ endPoint.y + scrollY < startPoint.y
309
+ ) {
310
+ //1象限
311
+ drawStartX = endPoint.x
312
+ drawStartY = endPoint.y
313
+ return new Rect(
314
+ drawStartX,
315
+ drawStartY,
316
+ Math.abs(endPoint.x - startPoint.x + scrollX),
317
+ Math.abs(endPoint.y - startPoint.y + scrollY)
318
+ )
319
+ } else if (
320
+ endPoint.x + scrollX < startPoint.x &&
321
+ endPoint.y + scrollY >= startPoint.y
322
+ ) {
323
+ //3象限
324
+ drawStartX = endPoint.x
325
+ drawStartY = startPoint.y
326
+ return new Rect(
327
+ drawStartX - scrollX,
328
+ drawStartY - scrollY,
329
+ Math.abs(endPoint.x - startPoint.x + scrollX),
330
+ Math.abs(endPoint.y - startPoint.y + scrollY)
331
+ )
332
+ } else {
333
+ //2象限
334
+ drawStartX = startPoint.x
335
+ drawStartY = endPoint.y
336
+ return new Rect(
337
+ drawStartX,
338
+ drawStartY,
339
+ Math.abs(endPoint.x - startPoint.x + scrollX),
340
+ Math.abs(endPoint.y - startPoint.y + scrollY)
341
+ )
342
+ }
343
+ }
344
+
345
+ export function calcEdgeLinesOfRect(rect?: IRect): IRectEdgeLines | undefined {
346
+ if (!rect) return
347
+ return {
348
+ v: [
349
+ new LineSegment(
350
+ new Point(rect.x, rect.y),
351
+ new Point(rect.x, rect.y + rect.height)
352
+ ),
353
+ new LineSegment(
354
+ new Point(rect.x + rect.width / 2, rect.y),
355
+ new Point(rect.x + rect.width / 2, rect.y + rect.height)
356
+ ),
357
+ new LineSegment(
358
+ new Point(rect.x + rect.width, rect.y),
359
+ new Point(rect.x + rect.width, rect.y + rect.height)
360
+ ),
361
+ ],
362
+ h: [
363
+ new LineSegment(
364
+ new Point(rect.x, rect.y),
365
+ new Point(rect.x + rect.width, rect.y)
366
+ ),
367
+ new LineSegment(
368
+ new Point(rect.x, rect.y + rect.height / 2),
369
+ new Point(rect.x + rect.width, rect.y + rect.height / 2)
370
+ ),
371
+ new LineSegment(
372
+ new Point(rect.x, rect.y + rect.height),
373
+ new Point(rect.x + rect.width, rect.y + rect.height)
374
+ ),
375
+ ],
376
+ }
377
+ }
378
+
379
+ export function calcRectOfAxisLineSegment(line?: ILineSegment) {
380
+ if (!isLineSegment(line)) return
381
+ const isXAxis = line.start.x === line.end.x
382
+ return new Rect(
383
+ line.start.x,
384
+ line.start.y,
385
+ isXAxis ? 0 : line.end.x - line.start.x,
386
+ isXAxis ? line.end.y - line.start.y : 0
387
+ )
388
+ }
389
+
390
+ export function calcSpaceBlockOfRect(
391
+ target: IRect,
392
+ source: IRect,
393
+ type?: string
394
+ ) {
395
+ const targetRect = new Rect(target.x, target.y, target.width, target.height)
396
+ const sourceRect = new Rect(source.x, source.y, source.width, source.height)
397
+ if (sourceRect.bottom < targetRect.top && sourceRect.left > targetRect.right)
398
+ return
399
+ if (sourceRect.top > targetRect.bottom && sourceRect.left > targetRect.right)
400
+ return
401
+ if (sourceRect.bottom < targetRect.top && sourceRect.right < targetRect.left)
402
+ return
403
+ if (sourceRect.top > targetRect.bottom && sourceRect.right < targetRect.left)
404
+ return
405
+ if (sourceRect.bottom < targetRect.top) {
406
+ const distance = targetRect.top - sourceRect.bottom
407
+ const left = Math.min(sourceRect.left, targetRect.left)
408
+ const right = Math.max(sourceRect.right, targetRect.right)
409
+ if (type && type !== 'top') return
410
+ return {
411
+ type: 'top',
412
+ distance,
413
+ rect: new Rect(left, sourceRect.bottom, right - left, distance),
414
+ }
415
+ } else if (sourceRect.top > targetRect.bottom) {
416
+ const distance = sourceRect.top - targetRect.bottom
417
+ const left = Math.min(sourceRect.left, targetRect.left)
418
+ const right = Math.max(sourceRect.right, targetRect.right)
419
+ if (type && type !== 'bottom') return
420
+ return {
421
+ type: 'bottom',
422
+ distance,
423
+ rect: new Rect(left, targetRect.bottom, right - left, distance),
424
+ }
425
+ } else if (sourceRect.right < targetRect.left) {
426
+ const distance = targetRect.left - sourceRect.right
427
+ const top = Math.min(sourceRect.top, targetRect.top)
428
+ const bottom = Math.max(sourceRect.bottom, targetRect.bottom)
429
+ if (type && type !== 'left') return
430
+ return {
431
+ type: 'left',
432
+ distance,
433
+ rect: new Rect(sourceRect.right, top, distance, bottom - top),
434
+ }
435
+ } else if (sourceRect.left > targetRect.right) {
436
+ const distance = sourceRect.left - targetRect.right
437
+ const top = Math.min(sourceRect.top, targetRect.top)
438
+ const bottom = Math.max(sourceRect.bottom, targetRect.bottom)
439
+ if (type && type !== 'right') return
440
+ return {
441
+ type: 'right',
442
+ distance,
443
+ rect: new Rect(targetRect.right, top, distance, bottom - top),
444
+ }
445
+ }
446
+ }
447
+
448
+ export function calcExtendsLineSegmentOfRect(
449
+ targetRect: Rect,
450
+ referRect: Rect
451
+ ) {
452
+ if (
453
+ referRect.right < targetRect.right &&
454
+ targetRect.left <= referRect.right
455
+ ) {
456
+ //右侧
457
+ if (referRect.bottom < targetRect.top) {
458
+ //上方
459
+ return {
460
+ start: { x: referRect.right, y: referRect.bottom },
461
+ end: { x: targetRect.right, y: referRect.bottom },
462
+ }
463
+ } else if (referRect.top > targetRect.bottom) {
464
+ //下方
465
+ return {
466
+ start: { x: referRect.right, y: referRect.top },
467
+ end: { x: targetRect.right, y: referRect.top },
468
+ }
469
+ }
470
+ } else if (
471
+ referRect.left > targetRect.left &&
472
+ targetRect.right >= referRect.left
473
+ ) {
474
+ //左侧
475
+ if (referRect.bottom < targetRect.top) {
476
+ //上方
477
+ return {
478
+ start: { x: targetRect.left, y: referRect.bottom },
479
+ end: { x: referRect.left, y: referRect.bottom },
480
+ }
481
+ } else if (referRect.top > targetRect.bottom) {
482
+ //下方
483
+ return {
484
+ start: { x: targetRect.left, y: referRect.top },
485
+ end: { x: referRect.left, y: referRect.top },
486
+ }
487
+ }
488
+ }
489
+ if (referRect.top < targetRect.top && targetRect.bottom >= referRect.top) {
490
+ //refer在上方
491
+ if (referRect.right < targetRect.left) {
492
+ //右侧
493
+ return {
494
+ start: { x: referRect.right, y: referRect.bottom },
495
+ end: { x: referRect.right, y: targetRect.bottom },
496
+ }
497
+ } else if (referRect.left > targetRect.right) {
498
+ //左侧
499
+ return {
500
+ start: { x: referRect.left, y: referRect.bottom },
501
+ end: { x: referRect.left, y: targetRect.bottom },
502
+ }
503
+ }
504
+ } else if (
505
+ referRect.bottom > targetRect.bottom &&
506
+ referRect.top <= targetRect.bottom
507
+ ) {
508
+ //refer下方
509
+ if (referRect.right < targetRect.left) {
510
+ //右侧
511
+ return {
512
+ start: { x: referRect.right, y: targetRect.top },
513
+ end: { x: referRect.right, y: referRect.top },
514
+ }
515
+ } else if (referRect.left > targetRect.right) {
516
+ //左侧
517
+ return {
518
+ start: { x: referRect.left, y: targetRect.top },
519
+ end: { x: referRect.left, y: referRect.top },
520
+ }
521
+ }
522
+ }
523
+ }
524
+
525
+ export function calcOffsetOfSnapLineSegmentToEdge(
526
+ line: ILineSegment,
527
+ current: IRect
528
+ ) {
529
+ const edges = calcEdgeLinesOfRect(current)
530
+ const isVerticalLine = line.start.x === line.end.x
531
+ if (isVerticalLine) {
532
+ return { x: calcMinDistanceValue(edges.x, line.start.x) - current.x, y: 0 }
533
+ }
534
+ function calcEdgeLinesOfRect(rect: IRect) {
535
+ return {
536
+ x: [rect.x, rect.x + rect.width / 2, rect.x + rect.width],
537
+ y: [rect.y, rect.y + rect.height / 2, rect.y + rect.height],
538
+ }
539
+ }
540
+ function calcMinDistanceValue(edges: number[], targetValue: number) {
541
+ let minDistance = Infinity,
542
+ minDistanceIndex = -1
543
+ for (let i = 0; i < edges.length; i++) {
544
+ const distance = Math.abs(edges[i] - targetValue)
545
+ if (minDistance > distance) {
546
+ minDistance = distance
547
+ minDistanceIndex = i
548
+ }
549
+ }
550
+ return edges[minDistanceIndex]
551
+ }
552
+
553
+ return { x: 0, y: calcMinDistanceValue(edges.y, line.start.y) - current.y }
554
+ }
555
+
556
+ export function calcDistanceOfSnapLineToEdges(
557
+ line: ILineSegment,
558
+ edges?: IRectEdgeLines
559
+ ) {
560
+ let distance = Infinity
561
+ if (!edges) return distance
562
+ if (line?.start?.y === line?.end?.y) {
563
+ edges.h.forEach((target) => {
564
+ const _distance = Math.abs(target.start.y - line.start.y)
565
+ if (_distance < distance) {
566
+ distance = _distance
567
+ }
568
+ })
569
+ } else if (line?.start?.x === line?.end?.x) {
570
+ edges.v.forEach((target) => {
571
+ const _distance = Math.abs(target.start.x - line.start.x)
572
+ if (_distance < distance) {
573
+ distance = _distance
574
+ }
575
+ })
576
+ } else {
577
+ throw new Error('can not calculate slash distance')
578
+ }
579
+ return distance
580
+ }
581
+
582
+ export function calcCombineSnapLineSegment(
583
+ target: ILineSegment,
584
+ source: ILineSegment
585
+ ): ILineSegment {
586
+ if (target.start.x === target.end.x) {
587
+ return new LineSegment(
588
+ new Point(
589
+ target.start.x,
590
+ target.start.y > source.start.y ? source.start.y : target.start.y
591
+ ),
592
+ new Point(
593
+ target.start.x,
594
+ target.end.y > source.end.y ? target.end.y : source.end.y
595
+ )
596
+ )
597
+ }
598
+
599
+ return new LineSegment(
600
+ new Point(
601
+ target.start.x > source.start.x ? source.start.x : target.start.x,
602
+ target.start.y
603
+ ),
604
+ new Point(
605
+ target.end.x > source.end.x ? target.end.x : source.end.x,
606
+ target.end.y
607
+ )
608
+ )
609
+ }
610
+
611
+ export function calcClosestEdges(
612
+ line: ILineSegment,
613
+ edges: IRectEdgeLines
614
+ ): [number, ILineSegment] {
615
+ let result: ILineSegment = {
616
+ start: { x: 0, y: 0 },
617
+ end: { x: 0, y: 0 },
618
+ }
619
+ let distance = Infinity
620
+ if (line?.start?.y === line?.end?.y) {
621
+ edges.h.forEach((target) => {
622
+ const _distance = Math.abs(target.start.y - line.start.y)
623
+ if (_distance < distance) {
624
+ distance = _distance
625
+ result = target
626
+ }
627
+ })
628
+ } else if (line?.start?.x === line?.end?.x) {
629
+ edges.v.forEach((target) => {
630
+ const _distance = Math.abs(target.start.x - line.start.x)
631
+ if (_distance < distance) {
632
+ distance = _distance
633
+ result = target
634
+ }
635
+ })
636
+ } else {
637
+ throw new Error('can not calculate slash distance')
638
+ }
639
+ return [distance, result]
640
+ }