@operato/image-marker 8.0.0-alpha.23 → 8.0.0-alpha.25

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.
@@ -38,57 +38,57 @@ export class OxImageMarkerMode extends LitElement {
38
38
  }
39
39
  `
40
40
 
41
- @property({ type: String }) currentMode: ImageMarkerMode = 'select'
41
+ @property({ type: String }) currentMode: ImageMarkerMode = 'edit'
42
42
  @property({ type: String }) currentShapeType?: ShapeType
43
43
 
44
44
  render() {
45
45
  return html`
46
46
  <div class="palette">
47
47
  <md-icon
48
- title="Move or Select"
49
- ?selected=${this.currentMode !== 'draw'}
50
- @click=${() => this.setMode(this.currentMode !== 'select' ? 'select' : 'move')}
51
- >${this.currentMode !== 'move' ? 'select' : 'drag_pan'}</md-icon
48
+ title="Edit or View"
49
+ ?selected=${this.currentMode !== 'shape'}
50
+ @click=${() => this.setMode(this.currentMode !== 'edit' ? 'edit' : 'view')}
51
+ >${this.currentMode !== 'view' ? 'brush' : 'drag_pan'}</md-icon
52
52
  >
53
53
 
54
54
  <md-icon
55
55
  title="Text"
56
- ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'text'}
56
+ ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'text'}
57
57
  @click=${() => this.setShape('text')}
58
58
  >match_case</md-icon
59
59
  >
60
60
 
61
61
  <md-icon
62
62
  title="Rectangle"
63
- ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'rectangle'}
63
+ ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'rectangle'}
64
64
  @click=${() => this.setShape('rectangle')}
65
65
  >rectangle</md-icon
66
66
  >
67
67
 
68
68
  <md-icon
69
69
  title="Circle"
70
- ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'circle'}
70
+ ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'circle'}
71
71
  @click=${() => this.setShape('circle')}
72
72
  >circle</md-icon
73
73
  >
74
74
 
75
75
  <md-icon
76
76
  title="Triangle"
77
- ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'triangle'}
77
+ ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'triangle'}
78
78
  @click=${() => this.setShape('triangle')}
79
79
  >change_history</md-icon
80
80
  >
81
81
 
82
82
  <md-icon
83
83
  title="Line"
84
- ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'line'}
84
+ ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'line'}
85
85
  @click=${() => this.setShape('line')}
86
86
  >shape_line</md-icon
87
87
  >
88
88
 
89
89
  <md-icon
90
90
  title="Arrow"
91
- ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'arrow'}
91
+ ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'arrow'}
92
92
  @click=${() => this.setShape('arrow')}
93
93
  >line_end_arrow</md-icon
94
94
  >
@@ -105,7 +105,7 @@ export class OxImageMarkerMode extends LitElement {
105
105
  `
106
106
  }
107
107
 
108
- private setMode(mode: ImageMarkerMode) {
108
+ public setMode(mode: ImageMarkerMode) {
109
109
  this.currentMode = mode
110
110
 
111
111
  this.dispatchEvent(
@@ -117,12 +117,12 @@ export class OxImageMarkerMode extends LitElement {
117
117
  )
118
118
  }
119
119
 
120
- private setShape(shapeType: ShapeType) {
121
- this.currentMode = 'draw'
120
+ protected setShape(shapeType: ShapeType) {
121
+ this.currentMode = 'shape'
122
122
  this.currentShapeType = shapeType
123
123
  this.dispatchEvent(
124
124
  new CustomEvent('mode-changed', {
125
- detail: { mode: 'draw', shapeType: this.currentShapeType },
125
+ detail: { mode: 'shape', shapeType: this.currentShapeType },
126
126
  bubbles: true,
127
127
  composed: true
128
128
  })
@@ -1,12 +1,13 @@
1
1
  import './ox-image-marker-mode'
2
2
 
3
3
  import { html, css, svg, nothing } from 'lit'
4
- import { state, customElement } from 'lit/decorators.js'
4
+ import { query, state, customElement } from 'lit/decorators.js'
5
5
  import { ifDefined } from 'lit/directives/if-defined.js'
6
6
  import { keyed } from 'lit/directives/keyed.js'
7
7
 
8
8
  import { ImageMarkerMode, Shape, ShapeType } from './types'
9
9
  import { BaseImageMarker } from './base-image-marker'
10
+ import { OxImageMarkerMode } from './ox-image-marker-mode'
10
11
 
11
12
  @customElement('ox-image-marker')
12
13
  export class OxImageMarker extends BaseImageMarker {
@@ -27,11 +28,11 @@ export class OxImageMarker extends BaseImageMarker {
27
28
  }
28
29
 
29
30
  svg {
30
- cursor: crosshair;
31
+ cursor: default;
31
32
  }
32
33
 
33
- svg.dragging {
34
- cursor: move;
34
+ svg[drawing] {
35
+ cursor: crosshair;
35
36
  }
36
37
 
37
38
  .resize-handle {
@@ -41,14 +42,18 @@ export class OxImageMarker extends BaseImageMarker {
41
42
  ]
42
43
 
43
44
  @state() private currentShapeType?: ShapeType
44
- @state() private currentMode: ImageMarkerMode = 'select'
45
+ @state() private currentMode: ImageMarkerMode = 'edit'
45
46
  @state() private selectedShape: Shape | null = null
46
47
 
48
+ @query('ox-image-marker-mode') imageMarkerMode!: OxImageMarkerMode
49
+
47
50
  private drawing = false
48
51
  private startX = 0
49
52
  private startY = 0
50
53
  private offsetX = 0
51
54
  private offsetY = 0
55
+ private shapeMoveThreshold = 10
56
+ private shapeMoveInitiated = false
52
57
 
53
58
  connectedCallback() {
54
59
  super.connectedCallback()
@@ -72,6 +77,7 @@ export class OxImageMarker extends BaseImageMarker {
72
77
  @wheel=${this.onSvgWheel}
73
78
  @dblclick=${this.onSvgDoubleClick}
74
79
  viewBox=${this.viewBox}
80
+ ?drawing=${this.currentMode == 'shape'}
75
81
  >
76
82
  <image href=${this.imageUrl} @load=${this.onImageLoad}></image>
77
83
  ${this.shapes.map(shape => keyed(shape.id, this.renderShape(shape)))}
@@ -103,15 +109,12 @@ export class OxImageMarker extends BaseImageMarker {
103
109
  protected onSvgMouseDown(event: MouseEvent) {
104
110
  event.preventDefault()
105
111
 
106
- this.selectedShape = null
107
- this.shapes = this.shapes.map(s => {
108
- return { ...s, selected: false }
109
- })
112
+ this.setSelectedShape(null)
110
113
 
111
- if (this.currentMode === 'move') {
112
- this.startPanning(event)
113
- } else if (this.currentMode === 'draw') {
114
+ if (this.currentMode === 'shape') {
114
115
  this.startDrawing(event)
116
+ } else {
117
+ this.startPanning(event)
115
118
  }
116
119
  }
117
120
 
@@ -123,15 +126,12 @@ export class OxImageMarker extends BaseImageMarker {
123
126
  }
124
127
 
125
128
  if (event.touches.length === 1) {
126
- this.selectedShape = null
127
- this.shapes = this.shapes.map(s => {
128
- return { ...s, selected: false }
129
- })
129
+ this.setSelectedShape(null)
130
130
 
131
- if (this.currentMode === 'move') {
132
- this.startPanning(event)
133
- } else if (this.currentMode === 'draw') {
131
+ if (this.currentMode === 'shape') {
134
132
  this.startDrawing(event)
133
+ } else {
134
+ this.startPanning(event)
135
135
  }
136
136
  } else if (event.touches.length === 2) {
137
137
  this.startPinchZooming(event)
@@ -160,20 +160,24 @@ export class OxImageMarker extends BaseImageMarker {
160
160
  }
161
161
 
162
162
  if ('touches' in event) {
163
- this.svg.addEventListener('touchmove', this.onDrawingMouseMove)
164
- this.svg.addEventListener('touchend', this.onDrawingMouseUp)
163
+ this.svg.addEventListener('touchmove', this.onMouseMoveForDrawing)
164
+ this.svg.addEventListener('touchend', this.onMouseUpForDrawing)
165
165
  } else {
166
- this.svg.addEventListener('mousemove', this.onDrawingMouseMove)
167
- this.svg.addEventListener('mouseup', this.onDrawingMouseUp)
166
+ this.svg.addEventListener('mousemove', this.onMouseMoveForDrawing)
167
+ this.svg.addEventListener('mouseup', this.onMouseUpForDrawing)
168
168
  }
169
169
  }
170
170
 
171
171
  private setMode(mode: ImageMarkerMode, shapeType: ShapeType) {
172
+ if (mode == 'view') {
173
+ this.setSelectedShape(null)
174
+ }
175
+
172
176
  this.currentMode = mode
173
177
  this.currentShapeType = shapeType
174
178
  }
175
179
 
176
- private onDrawingMouseMove = (event: MouseEvent | TouchEvent) => {
180
+ private onMouseMoveForDrawing = (event: MouseEvent | TouchEvent) => {
177
181
  if (!this.drawing) {
178
182
  return
179
183
  }
@@ -243,8 +247,8 @@ export class OxImageMarker extends BaseImageMarker {
243
247
  return
244
248
  }
245
249
 
246
- this.selectedShape = newShape
247
250
  this.shapes = [...this.shapes, newShape]
251
+ this.setSelectedShape(newShape)
248
252
  }
249
253
 
250
254
  if (this.selectedShape) {
@@ -278,7 +282,7 @@ export class OxImageMarker extends BaseImageMarker {
278
282
  }
279
283
  }
280
284
 
281
- private onDrawingMouseUp = (event: MouseEvent | TouchEvent) => {
285
+ private onMouseUpForDrawing = (event: MouseEvent | TouchEvent) => {
282
286
  event.preventDefault()
283
287
 
284
288
  this.drawing = false
@@ -286,20 +290,30 @@ export class OxImageMarker extends BaseImageMarker {
286
290
  const svg = this.svg as SVGSVGElement
287
291
 
288
292
  if ('touches' in event) {
289
- svg.removeEventListener('touchmove', this.onDrawingMouseMove)
290
- svg.removeEventListener('touchend', this.onDrawingMouseUp)
293
+ svg.removeEventListener('touchmove', this.onMouseMoveForDrawing)
294
+ svg.removeEventListener('touchend', this.onMouseUpForDrawing)
291
295
  } else {
292
- svg.removeEventListener('mousemove', this.onDrawingMouseMove)
293
- svg.removeEventListener('mouseup', this.onDrawingMouseUp)
296
+ svg.removeEventListener('mousemove', this.onMouseMoveForDrawing)
297
+ svg.removeEventListener('mouseup', this.onMouseUpForDrawing)
294
298
  }
295
299
 
296
- if (this.selectedShape) {
297
- this.selectedShape.selected = true
298
- }
300
+ this.imageMarkerMode.setMode('edit')
299
301
 
300
302
  this.requestUpdate()
301
303
  }
302
304
 
305
+ private setSelectedShape(shape: Shape | null) {
306
+ this.selectedShape = shape
307
+
308
+ if (!shape) {
309
+ this.shapes = this.shapes.map(s => {
310
+ return { ...s, selected: false }
311
+ })
312
+ } else {
313
+ this.selectedShape!.selected = true
314
+ }
315
+ }
316
+
303
317
  private getSvgPoint(event: MouseEvent | TouchEvent) {
304
318
  const { x, y } = this.getPointFromEvent(event)
305
319
 
@@ -328,8 +342,8 @@ export class OxImageMarker extends BaseImageMarker {
328
342
  y="${shape.y!}"
329
343
  fill="${commonAttrs.stroke}"
330
344
  style="cursor: ${commonAttrs.cursor}; font-size: 16px;"
331
- @mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
332
- @touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
345
+ @mousedown="${(e: MouseEvent) => this.onMouseDownOnShape(e, shape)}"
346
+ @touchstart="${(e: TouchEvent) => this.onMouseDownOnShape(e, shape)}"
333
347
  @dblclick="${(e: MouseEvent) => this.onTextDoubleClick(e, shape)}"
334
348
  >${shape.text}</text>
335
349
  `
@@ -345,8 +359,8 @@ export class OxImageMarker extends BaseImageMarker {
345
359
  stroke-width="${commonAttrs['stroke-width']}"
346
360
  fill="${commonAttrs.fill}"
347
361
  style="cursor: ${commonAttrs.cursor}"
348
- @mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
349
- @touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
362
+ @mousedown="${(e: MouseEvent) => this.onMouseDownOnShape(e, shape)}"
363
+ @touchstart="${(e: TouchEvent) => this.onMouseDownOnShape(e, shape)}"
350
364
  ></rect>
351
365
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
352
366
  `
@@ -361,8 +375,8 @@ export class OxImageMarker extends BaseImageMarker {
361
375
  stroke-width="${commonAttrs['stroke-width']}"
362
376
  fill="${commonAttrs.fill}"
363
377
  style="cursor: ${commonAttrs.cursor}"
364
- @mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
365
- @touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
378
+ @mousedown="${(e: MouseEvent) => this.onMouseDownOnShape(e, shape)}"
379
+ @touchstart="${(e: TouchEvent) => this.onMouseDownOnShape(e, shape)}"
366
380
  ></circle>
367
381
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
368
382
  `
@@ -375,8 +389,8 @@ export class OxImageMarker extends BaseImageMarker {
375
389
  stroke-width="${commonAttrs['stroke-width']}"
376
390
  fill="${commonAttrs.fill}"
377
391
  style="cursor: ${commonAttrs.cursor}"
378
- @mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
379
- @touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
392
+ @mousedown="${(e: MouseEvent) => this.onMouseDownOnShape(e, shape)}"
393
+ @touchstart="${(e: TouchEvent) => this.onMouseDownOnShape(e, shape)}"
380
394
  ></polygon>
381
395
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
382
396
  `
@@ -391,8 +405,20 @@ export class OxImageMarker extends BaseImageMarker {
391
405
  stroke="${commonAttrs.stroke}"
392
406
  stroke-width="${commonAttrs['stroke-width']}"
393
407
  style="cursor: ${commonAttrs.cursor}"
394
- @mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
395
- @touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
408
+ ></line>
409
+ <line
410
+ x1="${shape.x1!}"
411
+ y1="${shape.y1!}"
412
+ x2="${shape.x2 ?? shape.x1}"
413
+ y2="${shape.y2 ?? shape.y1}"
414
+ stroke="${commonAttrs.stroke}"
415
+ stroke-width="25"
416
+ stroke-opacity="0"
417
+ pointer-events="stroke"
418
+ @mousedown="${(e: MouseEvent) => this.onMouseDownOnShape(e, shape)}"
419
+ @touchstart="${(e: TouchEvent) => this.onMouseDownOnShape(e, shape)}"
420
+ @mouseenter="${() => (this.svg.style.cursor = 'pointer')}"
421
+ @mouseleave="${() => (this.svg.style.cursor = 'default')}"
396
422
  ></line>
397
423
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
398
424
  `
@@ -413,8 +439,20 @@ export class OxImageMarker extends BaseImageMarker {
413
439
  stroke-width="${commonAttrs['stroke-width']}"
414
440
  marker-end="url(#arrowhead-${shape.id})"
415
441
  style="cursor: ${commonAttrs.cursor}"
416
- @mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
417
- @touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
442
+ ></line>
443
+ <line
444
+ x1="${shape.x1!}"
445
+ y1="${shape.y1!}"
446
+ x2="${shape.x2 ?? shape.x1}"
447
+ y2="${shape.y2 ?? shape.y1}"
448
+ stroke="${commonAttrs.stroke}"
449
+ stroke-width="25"
450
+ stroke-opacity="0"
451
+ pointer-events="stroke"
452
+ @mousedown="${(e: MouseEvent) => this.onMouseDownOnShape(e, shape)}"
453
+ @touchstart="${(e: TouchEvent) => this.onMouseDownOnShape(e, shape)}"
454
+ @mouseenter="${() => (this.svg.style.cursor = 'pointer')}"
455
+ @mouseleave="${() => (this.svg.style.cursor = 'default')}"
418
456
  ></line>
419
457
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
420
458
  `
@@ -424,7 +462,15 @@ export class OxImageMarker extends BaseImageMarker {
424
462
  }
425
463
  }
426
464
 
427
- private onShapeMouseDown(event: MouseEvent | TouchEvent, shape: Shape) {
465
+ private onMouseDownOnShape(event: MouseEvent | TouchEvent, shape: Shape) {
466
+ if (this.currentMode !== 'edit') {
467
+ return
468
+ }
469
+
470
+ if ('touches' in event && event.touches.length > 1) {
471
+ return
472
+ }
473
+
428
474
  event.stopPropagation()
429
475
  event.preventDefault()
430
476
 
@@ -433,99 +479,100 @@ export class OxImageMarker extends BaseImageMarker {
433
479
  selected: s.id === shape.id
434
480
  }))
435
481
 
436
- this.selectedShape = this.shapes.find(s => s.id == shape.id)!
482
+ this.shapeMoveInitiated = false
483
+ this.setSelectedShape(this.shapes.find(s => s.id == shape.id)!)
437
484
 
438
485
  const { x, y } = this.getSvgPoint(event)
439
486
 
440
- switch (shape.type) {
441
- case 'text':
442
- case 'rectangle':
443
- case 'circle':
444
- this.offsetX = x - (shape.x || shape.cx || 0)
445
- this.offsetY = y - (shape.y || shape.cy || 0)
446
- break
447
-
448
- case 'triangle':
449
- const points = this.selectedShape.points!.split(' ').map(p => p.split(',').map(Number))
450
- const [px, py] = points[0] || [0, 0]
451
-
452
- this.offsetX = x - px
453
- this.offsetY = y - py
454
-
455
- break
456
-
457
- case 'line':
458
- case 'arrow':
459
- this.offsetX = x - shape.x1!
460
- this.offsetY = y - shape.y1!
461
- break
462
- }
487
+ this.offsetX = x
488
+ this.offsetY = y
463
489
 
464
490
  const svg = this.svg as SVGSVGElement
465
491
 
466
492
  if ('touches' in event) {
467
- svg.addEventListener('touchmove', this.onShapeMouseMove)
468
- svg.addEventListener('touchend', this.onShapeMouseUp)
493
+ svg.addEventListener('touchmove', this.onMouseMoveOnShape)
494
+ svg.addEventListener('touchend', this.onMouseUpOnShape)
469
495
  } else {
470
- svg.addEventListener('mousemove', this.onShapeMouseMove)
471
- svg.addEventListener('mouseup', this.onShapeMouseUp)
496
+ svg.addEventListener('mousemove', this.onMouseMoveOnShape)
497
+ svg.addEventListener('mouseup', this.onMouseUpOnShape)
472
498
  }
473
499
  }
474
500
 
475
- private onShapeMouseMove = (event: MouseEvent | TouchEvent) => {
501
+ private onMouseMoveOnShape = (event: MouseEvent | TouchEvent) => {
476
502
  if (!this.selectedShape) {
477
503
  return
478
504
  }
479
505
 
506
+ if ('touches' in event && event.touches.length > 1) {
507
+ return
508
+ }
509
+
480
510
  event.preventDefault()
481
511
 
482
512
  const { x, y } = this.getSvgPoint(event)
483
513
 
514
+ const dx = x - this.offsetX
515
+ const dy = y - this.offsetY
516
+
517
+ if (!this.shapeMoveInitiated) {
518
+ const distance = Math.sqrt(dx * dx + dy * dy)
519
+
520
+ if (distance < this.shapeMoveThreshold) {
521
+ return
522
+ }
523
+
524
+ this.shapeMoveInitiated = true
525
+ }
526
+
527
+ this.offsetX = x
528
+ this.offsetY = y
529
+
484
530
  switch (this.selectedShape.type) {
485
531
  case 'text':
486
532
  case 'rectangle':
487
- this.selectedShape.x = x - this.offsetX
488
- this.selectedShape.y = y - this.offsetY
533
+ this.selectedShape.x! += dx
534
+ this.selectedShape.y! += dy
489
535
  break
490
536
  case 'circle':
491
- this.selectedShape.cx = x - this.offsetX
492
- this.selectedShape.cy = y - this.offsetY
537
+ this.selectedShape.cx! += dx
538
+ this.selectedShape.cy! += dy
493
539
  break
494
540
  case 'triangle':
495
541
  const points = this.selectedShape.points!.split(' ').map(p => p.split(',').map(Number))
496
- const [ox, oy] = points[0]
497
542
 
498
- this.selectedShape.points = points
499
- .map(([px, py]) => [px - ox + x - this.offsetX, py - oy + y - this.offsetY].join(','))
500
- .join(' ')
543
+ this.selectedShape.points = points.map(([px, py]) => [px + dx, py + dy].join(',')).join(' ')
501
544
  break
502
545
  case 'line':
503
546
  case 'arrow':
504
- const dxLine = x - this.offsetX
505
- const dyLine = y - this.offsetY
506
- const deltaX = dxLine - this.selectedShape.x1!
507
- const deltaY = dyLine - this.selectedShape.y1!
508
- this.selectedShape.x1 = dxLine
509
- this.selectedShape.y1 = dyLine
510
- this.selectedShape.x2 = this.selectedShape.x2! + deltaX
511
- this.selectedShape.y2 = this.selectedShape.y2! + deltaY
547
+ this.selectedShape.x1! += dx
548
+ this.selectedShape.x2! += dx
549
+ this.selectedShape.y1! += dy
550
+ this.selectedShape.y2! += dy
512
551
  break
513
552
  }
514
553
 
515
554
  this.requestUpdate()
516
555
  }
517
556
 
518
- private onShapeMouseUp = (event: MouseEvent | TouchEvent) => {
557
+ private onMouseUpOnShape = (event: MouseEvent | TouchEvent) => {
558
+ if (!this.selectedShape) {
559
+ return
560
+ }
561
+
562
+ if ('touches' in event && event.touches.length > 1) {
563
+ return
564
+ }
565
+
519
566
  event.preventDefault()
520
567
 
521
568
  const svg = this.svg as SVGSVGElement
522
569
 
523
570
  if ('touches' in event) {
524
- svg.removeEventListener('touchmove', this.onShapeMouseMove)
525
- svg.removeEventListener('touchend', this.onShapeMouseUp)
571
+ svg.removeEventListener('touchmove', this.onMouseMoveOnShape)
572
+ svg.removeEventListener('touchend', this.onMouseUpOnShape)
526
573
  } else {
527
- svg.removeEventListener('mousemove', this.onShapeMouseMove)
528
- svg.removeEventListener('mouseup', this.onShapeMouseUp)
574
+ svg.removeEventListener('mousemove', this.onMouseMoveOnShape)
575
+ svg.removeEventListener('mouseup', this.onMouseUpOnShape)
529
576
  }
530
577
  }
531
578
 
@@ -579,8 +626,8 @@ export class OxImageMarker extends BaseImageMarker {
579
626
  stroke="black"
580
627
  class="resize-handle"
581
628
  style="cursor: ${handle.cursor};"
582
- @mousedown="${(e: MouseEvent) => this.onHandleMouseDown(e, shape, handle)}"
583
- @touchstart="${(e: TouchEvent) => this.onHandleMouseDown(e, shape, handle)}"
629
+ @mousedown="${(e: MouseEvent) => this.onResizeHandleMouseDown(e, shape, handle)}"
630
+ @touchstart="${(e: TouchEvent) => this.onResizeHandleMouseDown(e, shape, handle)}"
584
631
  ></rect>
585
632
  </g>
586
633
  `
@@ -588,25 +635,26 @@ export class OxImageMarker extends BaseImageMarker {
588
635
  `
589
636
  }
590
637
 
591
- private onHandleMouseDown(event: MouseEvent | TouchEvent, shape: Shape, handle: any) {
638
+ private onResizeHandleMouseDown(event: MouseEvent | TouchEvent, shape: Shape, handle: any) {
592
639
  event.stopPropagation()
593
640
  event.preventDefault()
594
641
 
595
- this.selectedShape = shape
642
+ this.setSelectedShape(shape)
643
+
596
644
  this.offsetX = handle.x
597
645
  this.offsetY = handle.y
598
646
  const svg = this.svg as SVGSVGElement
599
647
 
600
648
  if ('touches' in event) {
601
- svg.addEventListener('touchmove', this.onHandleMouseMove)
602
- svg.addEventListener('touchend', this.onHandleMouseUp)
649
+ svg.addEventListener('touchmove', this.onResizeHandleMouseMove)
650
+ svg.addEventListener('touchend', this.onResizeHandleMouseUp)
603
651
  } else {
604
- svg.addEventListener('mousemove', this.onHandleMouseMove)
605
- svg.addEventListener('mouseup', this.onHandleMouseUp)
652
+ svg.addEventListener('mousemove', this.onResizeHandleMouseMove)
653
+ svg.addEventListener('mouseup', this.onResizeHandleMouseUp)
606
654
  }
607
655
  }
608
656
 
609
- private onHandleMouseMove = (event: MouseEvent | TouchEvent) => {
657
+ private onResizeHandleMouseMove = (event: MouseEvent | TouchEvent) => {
610
658
  if (!this.selectedShape) {
611
659
  return
612
660
  }
@@ -616,12 +664,6 @@ export class OxImageMarker extends BaseImageMarker {
616
664
  const { x, y } = this.getSvgPoint(event)
617
665
 
618
666
  switch (this.selectedShape.type) {
619
- // case 'text':
620
- // this.selectedShape.width = Math.abs(x - this.selectedShape.x!)
621
- // this.selectedShape.height = Math.abs(y - this.selectedShape.y!)
622
- // if (x < this.selectedShape.x!) this.selectedShape.x = x
623
- // if (y < this.selectedShape.y!) this.selectedShape.y = y
624
- // break
625
667
  case 'rectangle':
626
668
  const startX = this.selectedShape.x!
627
669
  const startY = this.selectedShape.y!
@@ -691,20 +733,18 @@ export class OxImageMarker extends BaseImageMarker {
691
733
  this.requestUpdate()
692
734
  }
693
735
 
694
- private onHandleMouseUp = (event: MouseEvent | TouchEvent) => {
736
+ private onResizeHandleMouseUp = (event: MouseEvent | TouchEvent) => {
695
737
  event.preventDefault()
696
738
 
697
739
  const svg = this.svg as SVGSVGElement
698
740
 
699
741
  if ('touches' in event) {
700
- svg.removeEventListener('touchmove', this.onHandleMouseMove)
701
- svg.removeEventListener('touchend', this.onHandleMouseUp)
742
+ svg.removeEventListener('touchmove', this.onResizeHandleMouseMove)
743
+ svg.removeEventListener('touchend', this.onResizeHandleMouseUp)
702
744
  } else {
703
- svg.removeEventListener('mousemove', this.onHandleMouseMove)
704
- svg.removeEventListener('mouseup', this.onHandleMouseUp)
745
+ svg.removeEventListener('mousemove', this.onResizeHandleMouseMove)
746
+ svg.removeEventListener('mouseup', this.onResizeHandleMouseUp)
705
747
  }
706
-
707
- this.selectedShape = null
708
748
  }
709
749
 
710
750
  private onTextDoubleClick(event: MouseEvent, shape: Shape) {
@@ -849,7 +889,9 @@ export class OxImageMarker extends BaseImageMarker {
849
889
  private deleteSelectedShape() {
850
890
  if (this.selectedShape) {
851
891
  this.shapes = this.shapes.filter(s => s.id !== this.selectedShape!.id)
852
- this.selectedShape = null
892
+
893
+ this.setSelectedShape(null)
894
+
853
895
  this.requestUpdate()
854
896
  }
855
897
  }
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type ShapeType = 'text' | 'rectangle' | 'circle' | 'triangle' | 'line' | 'arrow'
2
- export type ImageMarkerMode = 'move' | 'select' | 'draw'
2
+ export type ImageMarkerMode = 'edit' | 'view' | 'shape'
3
3
  export interface Shape {
4
4
  id: string
5
5
  type: ShapeType