jellies-draw 0.1.11 → 0.2.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jellies-draw",
3
- "version": "0.1.11",
3
+ "version": "0.2.0",
4
4
  "description": "A drawer for jellies",
5
5
  "private": false,
6
6
  "main": "./src/index.js",
@@ -35,8 +35,13 @@ export default {
35
35
  Histories.record();
36
36
  this.stage.on('pointerdown', this.pointerDownHandler);
37
37
  this.stage.on('pointermove', this.pointerMoveHandler);
38
- this.stage.on('pointerup', this.pointerUpHandler);
38
+ this.stage.on('pointerup', this.handleCanvasPointerUp);
39
39
  this.stage.on('click tap', this.clickHandler);
40
+ this.stage.on('pointerdown', () => {
41
+ if (Properties.isUsingDrawingTool) {
42
+ window.addEventListener('pointerup', this.handleGlobalPointerUp, { once: true });
43
+ }
44
+ });
40
45
  },
41
46
  generateEventHandlers() {
42
47
  this.resizeHandler = this._handleResize.bind(this);
@@ -44,7 +49,17 @@ export default {
44
49
  this.keyupHandler = this._handleKeyup.bind(this);
45
50
  this.pointerDownHandler = this.handlePointerDown.bind(this);
46
51
  this.pointerMoveHandler = this.handlePointerMove.bind(this);
47
- this.pointerUpHandler = this.handlePointerUp.bind(this);
52
+ this.handleCanvasPointerUp = (event) => {
53
+ if (event.target.getStage()) {
54
+ this.handlePointerUp(event);
55
+ }
56
+ };
57
+ this.handleGlobalPointerUp = (event) => {
58
+ const container = this.stage.container();
59
+ if (!container.contains(event.target)) {
60
+ this.handlePointerUp(event);
61
+ }
62
+ };
48
63
  this.clickHandler = this.handleClick.bind(this);
49
64
  },
50
65
  clear() {
@@ -54,7 +69,7 @@ export default {
54
69
  destroy() {
55
70
  this.stage.off('pointerdown', this.pointerDownHandler);
56
71
  this.stage.off('pointermove', this.pointerMoveHandler);
57
- this.stage.off('pointerup', this.pointerUpHandler);
72
+ this.stage.off('pointerup', this.handleCanvasPointerUp);
58
73
  this.stage.off('click tap', this.clickHandler);
59
74
  document.removeEventListener('keydown', this.keydownHandler);
60
75
  document.removeEventListener('keyup', this.keyupHandler);
@@ -180,3 +195,4 @@ export default {
180
195
  Transformer.selectNode(targetNode, metaPressed);
181
196
  }
182
197
  }
198
+
@@ -1,51 +1,157 @@
1
1
  import Konva from 'konva'
2
2
  import Properties from '../properties'
3
3
  import Canvas from '../canvas'
4
+
4
5
  export default {
5
- temporalCurveTrajectory: null,
6
6
  temporalShape: null,
7
7
  startX: 0,
8
8
  startY: 0,
9
+ lastX: 0,
10
+ lastY: 0,
11
+ erasedNodes: new Set(),
12
+
9
13
  show({ offsetX, offsetY }) {
10
- Canvas.isDrawing = true;
14
+ Canvas.isDrawing = true
11
15
  this.startX = offsetX
12
16
  this.startY = offsetY
13
- this.temporalCurveTrajectory = null
14
- const strokeWidth = Properties.strokeWidth
15
- const newCurve = new Konva.Line({
16
- points: [offsetX, offsetY, offsetX, offsetY],
17
- stroke: 'transparent',
18
- strokeWidth,
19
- name: 'node',
20
- bezier: true,
21
- lineCap: 'round',
22
- strokeScaleEnabled: false
23
- });
17
+ this.lastX = offsetX
18
+ this.lastY = offsetY
19
+ this.erasedNodes.clear()
20
+
21
+ const newCurve = this._generateEraserLine(offsetX, offsetY)
24
22
  this.temporalShape = newCurve
25
- Canvas.layer.add(this.temporalShape);
23
+ Canvas.layer.add(this.temporalShape)
26
24
  },
25
+
27
26
  change({ offsetX, offsetY }) {
28
- if (Canvas.isDrawing) {
29
- if (!this.temporalCurveTrajectory) {
30
- this.temporalCurveTrajectory = [this.startX, this.startY]
27
+ if (!Canvas.isDrawing) return
28
+
29
+ this._updateEraserPath(offsetX, offsetY)
30
+ this._checkAndMarkIntersections(offsetX, offsetY)
31
+
32
+ this.lastX = offsetX
33
+ this.lastY = offsetY
34
+ Canvas.layer.batchDraw()
35
+ },
36
+
37
+ finish() {
38
+ this._destroyErasedNodes()
39
+ this._cleanupTemporalShape()
40
+ Canvas.layer.batchDraw()
41
+ },
42
+
43
+ _generateEraserLine(x, y) {
44
+ return new Konva.Line({
45
+ points: [x, y],
46
+ stroke: '#000000',
47
+ strokeWidth: Properties.strokeWidth * 2,
48
+ opacity: 0,
49
+ lineCap: 'round',
50
+ lineJoin: 'round',
51
+ tension: 0.5,
52
+ strokeScaleEnabled: false
53
+ })
54
+ },
55
+
56
+ _updateEraserPath(x, y) {
57
+ const points = this.temporalShape.points()
58
+ points.push(x, y)
59
+ this.temporalShape.points(points)
60
+ },
61
+
62
+ _checkAndMarkIntersections(x, y) {
63
+ Canvas.stage.find('.node').forEach(node => {
64
+ if (node === this.temporalShape) return
65
+
66
+ if (this._checkIntersection(node, { x, y })) {
67
+ if (!this.erasedNodes.has(node)) {
68
+ this._markNodeForErasure(node)
69
+ }
31
70
  }
32
- this.temporalCurveTrajectory.push(offsetX, offsetY)
33
- this.temporalShape.points(this.temporalCurveTrajectory);
34
- Canvas.stage.find('.node')
35
- .filter(node => this._hasIntersectionOnEraserCurve(node))
36
- .forEach(node => node.opacity(0.1));
71
+ })
72
+ },
73
+
74
+ _markNodeForErasure(node) {
75
+ node.opacity(0.2)
76
+ this.erasedNodes.add(node)
77
+ },
78
+
79
+ _destroyErasedNodes() {
80
+ this.erasedNodes.forEach(node => node.destroy())
81
+ this.erasedNodes.clear()
82
+ },
83
+
84
+ _cleanupTemporalShape() {
85
+ if (this.temporalShape) {
86
+ this.temporalShape.destroy()
87
+ this.temporalShape = null
37
88
  }
38
89
  },
39
- finish() {
40
- Canvas.stage.find('.node')
41
- .filter(node => this._hasIntersectionOnEraserCurve(node))
42
- .forEach(node => node.remove())
43
- this.temporalShape = null
90
+
91
+ _checkIntersection(node, point) {
92
+ if (node.attrs.nodeType === 'pen') {
93
+ return this._checkPenIntersection(node, point)
94
+ }
95
+ return this._checkDefaultIntersection(node)
96
+ },
97
+
98
+ _checkPenIntersection(node, point) {
99
+ const localPoint = this._transformPointToLocal(node, point)
100
+ const { points: pts, widths } = node.attrs
101
+
102
+ for (let i = 0; i < pts.length - 1; i++) {
103
+ const distance = this._getDistanceToLineSegment(
104
+ localPoint.x,
105
+ localPoint.y,
106
+ pts[i][0],
107
+ pts[i][1],
108
+ pts[i + 1][0],
109
+ pts[i + 1][1]
110
+ )
111
+
112
+ if (distance < (widths[i] + Properties.strokeWidth) / 2) {
113
+ return true
114
+ }
115
+ }
116
+ return false
44
117
  },
45
- _hasIntersectionOnEraserCurve(node) {
118
+
119
+ _checkDefaultIntersection(node) {
46
120
  return Konva.Util.haveIntersection(
47
121
  this.temporalShape.getClientRect(),
48
122
  node.getClientRect()
49
- );
123
+ )
124
+ },
125
+
126
+ _transformPointToLocal(node, point) {
127
+ const transform = node.getTransform()
128
+ return transform.copy().invert().point(point)
129
+ },
130
+
131
+ _getDistanceToLineSegment(px, py, x1, y1, x2, y2) {
132
+ const A = px - x1
133
+ const B = py - y1
134
+ const C = x2 - x1
135
+ const D = y2 - y1
136
+
137
+ const dot = A * C + B * D
138
+ const lenSq = C * C + D * D
139
+ const param = lenSq !== 0 ? dot / lenSq : -1
140
+
141
+ if (param < 0) return this._getDistance(px, py, x1, y1)
142
+ if (param > 1) return this._getDistance(px, py, x2, y2)
143
+
144
+ return this._getDistance(
145
+ px,
146
+ py,
147
+ x1 + param * C,
148
+ y1 + param * D
149
+ )
150
+ },
151
+
152
+ _getDistance(x1, y1, x2, y2) {
153
+ const dx = x1 - x2
154
+ const dy = y1 - y2
155
+ return Math.sqrt(dx * dx + dy * dy)
50
156
  }
51
157
  }
@@ -2,62 +2,373 @@ import Konva from 'konva'
2
2
  import Properties from '../properties'
3
3
  import Canvas from '../canvas'
4
4
  import Histories from '../histories'
5
+
5
6
  export default {
6
- temporalCurveTrajectory: null,
7
7
  temporalShape: null,
8
8
  startX: 0,
9
9
  startY: 0,
10
+ lastX: 0,
11
+ lastY: 0,
12
+ lastTime: 0,
13
+ points: [],
14
+ widths: [],
15
+ boundMinX: 0,
16
+ boundMinY: 0,
17
+ boundMaxX: 0,
18
+ boundMaxY: 0,
19
+
10
20
  show({ offsetX, offsetY }) {
11
- Canvas.isDrawing = true;
21
+ Canvas.isDrawing = true
12
22
  this.startX = offsetX
13
23
  this.startY = offsetY
14
- this.temporalCurveTrajectory = null
15
- const stroke = Properties.strokeColor
16
- const strokeWidth = Properties.strokeWidth
24
+ this.lastX = offsetX
25
+ this.lastY = offsetY
26
+ this.lastTime = Date.now()
27
+
28
+ this.boundMinX = offsetX
29
+ this.boundMinY = offsetY
30
+ this.boundMaxX = offsetX
31
+ this.boundMaxY = offsetY
32
+
33
+ this.points = [[0, 0]]
34
+ this.widths = [Properties.strokeWidth]
35
+
17
36
  const newCurve = this.generate({
18
- points: [offsetX, offsetY, offsetX, offsetY],
19
- stroke,
20
- strokeWidth
37
+ x: offsetX,
38
+ y: offsetY,
39
+ points: this.points,
40
+ widths: this.widths,
41
+ stroke: Properties.strokeColor
21
42
  })
43
+
22
44
  this.temporalShape = newCurve
23
45
  Canvas.layer.add(this.temporalShape)
24
46
  },
47
+
25
48
  change({ offsetX, offsetY }) {
26
- if (Canvas.isDrawing) {
27
- if (!this.temporalCurveTrajectory) {
28
- this.temporalCurveTrajectory = [this.startX, this.startY]
29
- }
30
- this.temporalCurveTrajectory.push(offsetX, offsetY)
31
- this.temporalShape.points(this.temporalCurveTrajectory);
32
- }
49
+ if (!Canvas.isDrawing) return
50
+
51
+ const currentTime = Date.now()
52
+ const strokeWidth = this._calculateStrokeWidth(offsetX, offsetY, currentTime)
53
+
54
+ this._updateBoundaries(offsetX, offsetY)
55
+
56
+ const relativeX = offsetX - this.startX
57
+ const relativeY = offsetY - this.startY
58
+
59
+ this.points.push([relativeX, relativeY])
60
+ this.widths.push(strokeWidth)
61
+
62
+ Canvas.layer.batchDraw()
63
+
64
+ this.lastX = offsetX
65
+ this.lastY = offsetY
66
+ this.lastTime = currentTime
33
67
  },
68
+
34
69
  finish() {
70
+ if (!this.temporalShape) return
71
+
72
+ const maxStrokeWidth = Math.max(...this.widths)
73
+ const padding = maxStrokeWidth
74
+
75
+ this._adjustShapeBoundaries(padding)
76
+ Canvas.layer.batchDraw()
35
77
  this.temporalShape = null
36
78
  },
37
- generate({ x, y, scaleX, scaleY, skewX, rotation, points, stroke, strokeWidth }) {
38
- const newLine = new Konva.Line({
39
- x,
40
- y,
41
- scaleX,
42
- scaleY,
43
- skewX,
44
- rotation,
45
- points,
79
+
80
+ generate({ points, widths, stroke, x, y, width, height }) {
81
+ const tool = this
82
+
83
+ const shape = new Konva.Shape({
84
+ x: x || 0,
85
+ y: y || 0,
86
+ width: width || 0,
87
+ height: height || 0,
46
88
  stroke,
47
- strokeWidth,
89
+ points,
90
+ widths,
48
91
  name: 'node',
49
92
  nodeType: 'pen',
50
- lineCap: 'round',
51
- bezier: false,
52
- strokeScaleEnabled: false
93
+ strokeScaleEnabled: false,
94
+
95
+ sceneFunc: (context, shape) => {
96
+ const smoothPoints = tool._calculateSmoothPoints(shape.attrs.points)
97
+ tool._drawSmoothLine(context, smoothPoints, shape.attrs.widths, shape.attrs.stroke)
98
+ },
99
+
100
+ hitFunc: (context, shape) => {
101
+ const smoothPoints = tool._calculateSmoothPoints(shape.attrs.points)
102
+ tool._drawHitPath(context, smoothPoints, shape.attrs.widths)
103
+ context.fillStrokeShape(shape)
104
+ }
53
105
  })
54
- this.bindEvents(newLine)
55
- return newLine
56
- },
57
- bindEvents(newLine) {
58
- newLine.off('transformend')
59
- newLine.off('dragend')
60
- newLine.on('transformend', Histories.record)
61
- newLine.on('dragend', Histories.record)
106
+
107
+ this.bindEvents(shape)
108
+ return shape
109
+ },
110
+
111
+ bindEvents(shape) {
112
+ shape.off('transformend')
113
+ shape.off('dragend')
114
+ shape.on('transformend', Histories.record)
115
+ shape.on('dragend', Histories.record)
116
+ },
117
+
118
+ _calculateStrokeWidth(offsetX, offsetY, currentTime) {
119
+ const timeDiff = currentTime - this.lastTime
120
+ const distance = Math.sqrt(
121
+ Math.pow(offsetX - this.lastX, 2) +
122
+ Math.pow(offsetY - this.lastY, 2)
123
+ )
124
+ const velocity = distance / (timeDiff + 1)
125
+
126
+ const baseWidth = Properties.strokeWidth
127
+ const minWidth = baseWidth * 0.7
128
+ const maxWidth = baseWidth * 1.2
129
+
130
+ if (velocity > 0.7) return minWidth
131
+ if (velocity < 0.2) return maxWidth
132
+ return maxWidth - (velocity - 0.2) * (maxWidth - minWidth) / 0.5
133
+ },
134
+
135
+ _updateBoundaries(x, y) {
136
+ this.boundMinX = Math.min(this.boundMinX, x)
137
+ this.boundMinY = Math.min(this.boundMinY, y)
138
+ this.boundMaxX = Math.max(this.boundMaxX, x)
139
+ this.boundMaxY = Math.max(this.boundMaxY, y)
140
+ },
141
+
142
+ _adjustShapeBoundaries(padding) {
143
+ this.temporalShape.x(this.boundMinX - padding)
144
+ this.temporalShape.y(this.boundMinY - padding)
145
+ this.temporalShape.width(this.boundMaxX - this.boundMinX + padding * 2)
146
+ this.temporalShape.height(this.boundMaxY - this.boundMinY + padding * 2)
147
+
148
+ const adjustedPoints = this.points.map(point => [
149
+ point[0] - (this.boundMinX - this.startX - padding),
150
+ point[1] - (this.boundMinY - this.startY - padding)
151
+ ])
152
+ this.temporalShape.attrs.points = adjustedPoints
153
+ },
154
+
155
+ _drawSmoothLine(context, points, widths, stroke) {
156
+ context.beginPath()
157
+ context.strokeStyle = stroke
158
+ context.lineCap = 'round'
159
+ context.lineJoin = 'round'
160
+ context.moveTo(points[0][0], points[0][1])
161
+
162
+ for (let i = 1; i < points.length; i++) {
163
+ const width = this._interpolateWidth(i, points.length, widths)
164
+ context.lineWidth = width
165
+ context.lineTo(points[i][0], points[i][1])
166
+ context.stroke()
167
+ context.beginPath()
168
+ context.moveTo(points[i][0], points[i][1])
169
+ }
170
+ },
171
+
172
+ _drawHitPath(context, points, widths) {
173
+ context.beginPath()
174
+ context.lineCap = 'round'
175
+ context.lineJoin = 'round'
176
+ context.moveTo(points[0][0], points[0][1])
177
+
178
+ this._drawForwardPath(context, points, widths)
179
+ this._drawReversePath(context, points, widths)
180
+ },
181
+
182
+ _drawForwardPath(context, points, widths) {
183
+ for (let i = 1; i < points.length; i++) {
184
+ const width = this._interpolateWidth(i, points.length, widths) + 10
185
+ context.lineWidth = width
186
+ context.lineTo(points[i][0], points[i][1])
187
+ }
188
+ },
189
+
190
+ _drawReversePath(context, points, widths) {
191
+ for (let i = points.length - 1; i >= 0; i--) {
192
+ const width = this._interpolateWidth(i, points.length, widths) + 10
193
+ context.lineWidth = width
194
+ context.lineTo(points[i][0], points[i][1])
195
+ }
196
+ },
197
+
198
+ _interpolateWidth(index, total, widths) {
199
+ const progress = index / total
200
+ const widthIndex = Math.floor(progress * (widths.length - 1))
201
+ const nextWidthIndex = Math.min(widthIndex + 1, widths.length - 1)
202
+ const widthProgress = progress * (widths.length - 1) - widthIndex
203
+ return widths[widthIndex] * (1 - widthProgress) +
204
+ widths[nextWidthIndex] * widthProgress
205
+ },
206
+
207
+ _calculateSmoothPoints(points) {
208
+ // 首先检查是否是近似直线
209
+ const isNearlyLine = this._checkIfNearlyLine(points)
210
+
211
+ // 如果是近似直线,使用 Douglas-Peucker 算法简化
212
+ if (isNearlyLine) {
213
+ return this._simplifyDouglasPeucker(points, 2)
214
+ }
215
+
216
+ const smoothPoints = []
217
+ for (let i = 0; i < points.length - 1; i++) {
218
+ const p0 = i > 0 ? points[i - 1] : points[i]
219
+ const p1 = points[i]
220
+ const p2 = points[i + 1]
221
+ const p3 = i < points.length - 2 ? points[i + 2] : p2
222
+
223
+ // 检查是否是锐角
224
+ if (i > 0 && i < points.length - 2) {
225
+ const angle = this._getAngle(p1, p2, p0)
226
+
227
+ if (angle < Math.PI * 0.6 && this._getSegmentLength(p1, p2) > 20) {
228
+ smoothPoints.push(p1)
229
+ smoothPoints.push(p2)
230
+ continue
231
+ }
232
+ }
233
+
234
+ this._addCatmullRomPoints(smoothPoints, p0, p1, p2, p3)
235
+ }
236
+ smoothPoints.push(points[points.length - 1])
237
+ return smoothPoints
238
+ },
239
+
240
+ _checkIfNearlyLine(points) {
241
+ if (points.length < 3) return true
242
+
243
+ // 计算所有点到起点和终点连线的最大偏差
244
+ const start = points[0]
245
+ const end = points[points.length - 1]
246
+ let maxDeviation = 0
247
+
248
+ for (let i = 1; i < points.length - 1; i++) {
249
+ const deviation = this._getPointToLineDistance(
250
+ points[i],
251
+ start,
252
+ end
253
+ )
254
+ maxDeviation = Math.max(maxDeviation, deviation)
255
+ }
256
+
257
+ // 检查所有相邻点之间的角度
258
+ for (let i = 1; i < points.length - 1; i++) {
259
+ const angle = this._getAngle(points[i-1], points[i], points[i+1])
260
+ // 176度 ≈ 3.07 弧度
261
+ if (angle < 3.07) {
262
+ return false
263
+ }
264
+ }
265
+
266
+ // 如果最大偏差小于阈值且所有角度都接近180度,认为是近似直线
267
+ return maxDeviation < 5
268
+ },
269
+
270
+ _getPointToLineDistance(point, lineStart, lineEnd) {
271
+ const dx = lineEnd[0] - lineStart[0]
272
+ const dy = lineEnd[1] - lineStart[1]
273
+ const lineLengthSq = dx * dx + dy * dy
274
+
275
+ if (lineLengthSq === 0) return 0
276
+
277
+ const t = ((point[0] - lineStart[0]) * dx +
278
+ (point[1] - lineStart[1]) * dy) / lineLengthSq
279
+
280
+ if (t < 0) return this._getSegmentLength(point, lineStart)
281
+ if (t > 1) return this._getSegmentLength(point, lineEnd)
282
+
283
+ const projX = lineStart[0] + t * dx
284
+ const projY = lineStart[1] + t * dy
285
+
286
+ return Math.sqrt(
287
+ Math.pow(point[0] - projX, 2) +
288
+ Math.pow(point[1] - projY, 2)
289
+ )
290
+ },
291
+
292
+ _getAngle(p1, p2, p0) {
293
+ const v1 = [p1[0] - p0[0], p1[1] - p0[1]]
294
+ const v2 = [p2[0] - p1[0], p2[1] - p1[1]]
295
+
296
+ // 计算向量夹角
297
+ const dot = v1[0] * v2[0] + v1[1] * v2[1]
298
+ const len1 = Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1])
299
+ const len2 = Math.sqrt(v2[0] * v2[0] + v2[1] * v2[1])
300
+
301
+ return Math.acos(dot / (len1 * len2))
302
+ },
303
+
304
+ _getSegmentLength(p1, p2) {
305
+ const dx = p2[0] - p1[0]
306
+ const dy = p2[1] - p1[1]
307
+ return Math.sqrt(dx * dx + dy * dy)
308
+ },
309
+
310
+ _addCatmullRomPoints(smoothPoints, p0, p1, p2, p3) {
311
+ for (let t = 0; t < 1; t += 0.1) {
312
+ const t2 = t * t
313
+ const t3 = t2 * t
314
+
315
+ const x = 0.5 * (
316
+ (2 * p1[0]) +
317
+ (-p0[0] + p2[0]) * t +
318
+ (2 * p0[0] - 5 * p1[0] + 4 * p2[0] - p3[0]) * t2 +
319
+ (-p0[0] + 3 * p1[0] - 3 * p2[0] + p3[0]) * t3
320
+ )
321
+ const y = 0.5 * (
322
+ (2 * p1[1]) +
323
+ (-p0[1] + p2[1]) * t +
324
+ (2 * p0[1] - 5 * p1[1] + 4 * p2[1] - p3[1]) * t2 +
325
+ (-p0[1] + 3 * p1[1] - 3 * p2[1] + p3[1]) * t3
326
+ )
327
+
328
+ smoothPoints.push([x, y])
329
+ }
330
+ },
331
+
332
+ _simplifyDouglasPeucker(points, epsilon) {
333
+ if (points.length <= 2) return points
334
+
335
+ // 找到最远点
336
+ let maxDistance = 0
337
+ let maxIndex = 0
338
+
339
+ const firstPoint = points[0]
340
+ const lastPoint = points[points.length - 1]
341
+
342
+ // 找到距离首尾连线最远的点
343
+ for (let i = 1; i < points.length - 1; i++) {
344
+ const distance = this._getPointToLineDistance(
345
+ points[i],
346
+ firstPoint,
347
+ lastPoint
348
+ )
349
+
350
+ if (distance > maxDistance) {
351
+ maxDistance = distance
352
+ maxIndex = i
353
+ }
354
+ }
355
+
356
+ // 如果最大距离大于阈值,递归处理两个子段
357
+ if (maxDistance > epsilon) {
358
+ const firstHalf = this._simplifyDouglasPeucker(
359
+ points.slice(0, maxIndex + 1),
360
+ epsilon
361
+ )
362
+ const secondHalf = this._simplifyDouglasPeucker(
363
+ points.slice(maxIndex),
364
+ epsilon
365
+ )
366
+
367
+ // 合并两个子段,去掉重复的中间点
368
+ return firstHalf.slice(0, -1).concat(secondHalf)
369
+ }
370
+
371
+ // 如果最大距离小于阈值,只保留首尾两点
372
+ return [firstPoint, lastPoint]
62
373
  }
63
374
  }
@@ -39,9 +39,8 @@ export default {
39
39
  return this.selector !== null
40
40
  },
41
41
  _isInSelector(node) {
42
- return Konva.Util.haveIntersection(
43
- this.selector.getClientRect(),
44
- node.getClientRect()
45
- );
42
+ const nodeRect = node.getClientRect()
43
+ const selectorRect = this.selector.getClientRect()
44
+ return Konva.Util.haveIntersection(selectorRect, nodeRect)
46
45
  }
47
46
  }