@operato/image-marker 8.0.0-alpha.18 → 8.0.0-alpha.22
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/CHANGELOG.md +9 -0
- package/dist/src/base-image-marker.d.ts +16 -4
- package/dist/src/base-image-marker.js +96 -15
- package/dist/src/base-image-marker.js.map +1 -1
- package/dist/src/ox-image-marker-mode.js +2 -2
- package/dist/src/ox-image-marker-mode.js.map +1 -1
- package/dist/src/ox-image-marker-view.js +2 -2
- package/dist/src/ox-image-marker-view.js.map +1 -1
- package/dist/src/ox-image-marker.d.ts +7 -6
- package/dist/src/ox-image-marker.js +150 -71
- package/dist/src/ox-image-marker.js.map +1 -1
- package/dist/stories/ox-image-marker.stories.js +16 -0
- package/dist/stories/ox-image-marker.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/base-image-marker.ts +114 -19
- package/src/ox-image-marker-mode.ts +2 -2
- package/src/ox-image-marker-view.ts +2 -2
- package/src/ox-image-marker.ts +170 -81
- package/stories/ox-image-marker.stories.ts +16 -0
package/src/ox-image-marker.ts
CHANGED
|
@@ -52,28 +52,15 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
52
52
|
|
|
53
53
|
connectedCallback() {
|
|
54
54
|
super.connectedCallback()
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
this.setAttribute('tabindex', '0')
|
|
56
|
+
this.addEventListener('focus', this.onFocus)
|
|
57
|
+
this.addEventListener('blur', this.onBlur)
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
disconnectedCallback() {
|
|
60
61
|
super.disconnectedCallback()
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private handleKeyDown = (event: KeyboardEvent) => {
|
|
66
|
-
if ((event.key === 'Delete' || event.key === 'Backspace') && this.selectedShape) {
|
|
67
|
-
this.deleteSelectedShape()
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private deleteSelectedShape() {
|
|
72
|
-
if (this.selectedShape) {
|
|
73
|
-
this.shapes = this.shapes.filter(s => s.id !== this.selectedShape!.id)
|
|
74
|
-
this.selectedShape = null
|
|
75
|
-
this.requestUpdate()
|
|
76
|
-
}
|
|
62
|
+
this.removeEventListener('focus', this.onFocus)
|
|
63
|
+
this.removeEventListener('blur', this.onBlur)
|
|
77
64
|
}
|
|
78
65
|
|
|
79
66
|
render() {
|
|
@@ -81,8 +68,9 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
81
68
|
<div class="container">
|
|
82
69
|
<svg
|
|
83
70
|
@mousedown=${this.onSvgMouseDown}
|
|
84
|
-
@
|
|
85
|
-
@
|
|
71
|
+
@touchstart=${this.onSvgTouchStart}
|
|
72
|
+
@wheel=${this.onSvgWheel}
|
|
73
|
+
@dblclick=${this.onSvgDoubleClick}
|
|
86
74
|
viewBox=${this.viewBox}
|
|
87
75
|
>
|
|
88
76
|
<image href=${this.imageUrl} @load=${this.onImageLoad}></image>
|
|
@@ -97,8 +85,8 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
97
85
|
const { mode, shapeType } = e.detail
|
|
98
86
|
this.setMode(mode, shapeType)
|
|
99
87
|
}}
|
|
100
|
-
@
|
|
101
|
-
@
|
|
88
|
+
@tap-delete=${() => this.deleteSelectedShape()}
|
|
89
|
+
@tap-save=${() => {
|
|
102
90
|
this.dispatchEvent(
|
|
103
91
|
new CustomEvent('shapes-changed', {
|
|
104
92
|
detail: this.shapes,
|
|
@@ -112,40 +100,36 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
112
100
|
}
|
|
113
101
|
|
|
114
102
|
protected onSvgMouseDown(event: MouseEvent) {
|
|
115
|
-
const svg = this.svg
|
|
116
|
-
|
|
117
103
|
this.selectedShape = null
|
|
118
104
|
this.shapes = this.shapes.map(s => {
|
|
119
105
|
return { ...s, selected: false }
|
|
120
106
|
})
|
|
121
107
|
|
|
122
|
-
this.selectedShape = null
|
|
123
108
|
if (this.currentMode === 'move') {
|
|
124
|
-
this.
|
|
125
|
-
this.panStart = { x: event.clientX, y: event.clientY }
|
|
126
|
-
svg.classList.add('dragging')
|
|
127
|
-
svg.addEventListener('mousemove', this.onPanMouseMove)
|
|
128
|
-
svg.addEventListener('mouseup', this.onPanMouseUp)
|
|
129
|
-
} else if (this.currentMode === 'select') {
|
|
130
|
-
this.startShapeDragging(event)
|
|
131
|
-
svg.addEventListener('mousemove', this.onShapeMouseMove)
|
|
132
|
-
svg.addEventListener('mouseup', this.onShapeMouseUp)
|
|
109
|
+
this.startPanning(event)
|
|
133
110
|
} else if (this.currentMode === 'draw') {
|
|
134
111
|
this.startDrawing(event)
|
|
135
|
-
svg.addEventListener('mousemove', this.onMouseMove)
|
|
136
|
-
svg.addEventListener('mouseup', this.onMouseUp)
|
|
137
112
|
}
|
|
138
113
|
}
|
|
139
114
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this.
|
|
144
|
-
|
|
115
|
+
protected onSvgTouchStart = (event: TouchEvent) => {
|
|
116
|
+
if (event.touches.length === 1) {
|
|
117
|
+
this.selectedShape = null
|
|
118
|
+
this.shapes = this.shapes.map(s => {
|
|
119
|
+
return { ...s, selected: false }
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
if (this.currentMode === 'move') {
|
|
123
|
+
this.startPanning(event)
|
|
124
|
+
} else if (this.currentMode === 'draw') {
|
|
125
|
+
this.startDrawing(event)
|
|
126
|
+
}
|
|
127
|
+
} else if (event.touches.length === 2) {
|
|
128
|
+
this.startPinchZooming(event)
|
|
145
129
|
}
|
|
146
130
|
}
|
|
147
131
|
|
|
148
|
-
private startDrawing(event: MouseEvent) {
|
|
132
|
+
private startDrawing(event: MouseEvent | TouchEvent) {
|
|
149
133
|
const { x, y } = this.getSvgPoint(event)
|
|
150
134
|
|
|
151
135
|
if (this.currentShapeType === 'text') {
|
|
@@ -165,6 +149,14 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
165
149
|
this.startY = y
|
|
166
150
|
this.drawing = true
|
|
167
151
|
}
|
|
152
|
+
|
|
153
|
+
if ('touches' in event) {
|
|
154
|
+
this.svg.addEventListener('touchmove', this.onDrawingMouseMove)
|
|
155
|
+
this.svg.addEventListener('touchend', this.onDrawingMouseUp)
|
|
156
|
+
} else {
|
|
157
|
+
this.svg.addEventListener('mousemove', this.onDrawingMouseMove)
|
|
158
|
+
this.svg.addEventListener('mouseup', this.onDrawingMouseUp)
|
|
159
|
+
}
|
|
168
160
|
}
|
|
169
161
|
|
|
170
162
|
private setMode(mode: ImageMarkerMode, shapeType: ShapeType) {
|
|
@@ -172,8 +164,10 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
172
164
|
this.currentShapeType = shapeType
|
|
173
165
|
}
|
|
174
166
|
|
|
175
|
-
private
|
|
176
|
-
if (!this.drawing)
|
|
167
|
+
private onDrawingMouseMove = (event: MouseEvent | TouchEvent) => {
|
|
168
|
+
if (!this.drawing) {
|
|
169
|
+
return
|
|
170
|
+
}
|
|
177
171
|
|
|
178
172
|
const { x, y } = this.getSvgPoint(event)
|
|
179
173
|
|
|
@@ -273,11 +267,18 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
273
267
|
}
|
|
274
268
|
}
|
|
275
269
|
|
|
276
|
-
private
|
|
270
|
+
private onDrawingMouseUp = (event: MouseEvent | TouchEvent) => {
|
|
277
271
|
this.drawing = false
|
|
272
|
+
|
|
278
273
|
const svg = this.svg as SVGSVGElement
|
|
279
|
-
|
|
280
|
-
|
|
274
|
+
|
|
275
|
+
if ('touches' in event) {
|
|
276
|
+
svg.removeEventListener('touchmove', this.onDrawingMouseMove)
|
|
277
|
+
svg.removeEventListener('touchend', this.onDrawingMouseUp)
|
|
278
|
+
} else {
|
|
279
|
+
svg.removeEventListener('mousemove', this.onDrawingMouseMove)
|
|
280
|
+
svg.removeEventListener('mouseup', this.onDrawingMouseUp)
|
|
281
|
+
}
|
|
281
282
|
|
|
282
283
|
if (this.selectedShape) {
|
|
283
284
|
this.selectedShape.selected = true
|
|
@@ -286,12 +287,15 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
286
287
|
this.requestUpdate()
|
|
287
288
|
}
|
|
288
289
|
|
|
289
|
-
private getSvgPoint(event: MouseEvent) {
|
|
290
|
+
private getSvgPoint(event: MouseEvent | TouchEvent) {
|
|
291
|
+
const { x, y } = this.getPointFromEvent(event)
|
|
292
|
+
|
|
290
293
|
const svg = this.svg
|
|
291
294
|
const point = svg.createSVGPoint()
|
|
292
|
-
point.x =
|
|
293
|
-
point.y =
|
|
295
|
+
point.x = x
|
|
296
|
+
point.y = y
|
|
294
297
|
const ctm = svg.getScreenCTM()!.inverse()
|
|
298
|
+
|
|
295
299
|
return point.matrixTransform(ctm)
|
|
296
300
|
}
|
|
297
301
|
|
|
@@ -312,6 +316,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
312
316
|
fill="${commonAttrs.stroke}"
|
|
313
317
|
style="cursor: ${commonAttrs.cursor}; font-size: 16px;"
|
|
314
318
|
@mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
|
|
319
|
+
@touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
|
|
315
320
|
@dblclick="${(e: MouseEvent) => this.onTextDoubleClick(e, shape)}"
|
|
316
321
|
>${shape.text}</text>
|
|
317
322
|
`
|
|
@@ -328,6 +333,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
328
333
|
fill="${commonAttrs.fill}"
|
|
329
334
|
style="cursor: ${commonAttrs.cursor}"
|
|
330
335
|
@mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
|
|
336
|
+
@touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
|
|
331
337
|
></rect>
|
|
332
338
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
333
339
|
`
|
|
@@ -343,6 +349,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
343
349
|
fill="${commonAttrs.fill}"
|
|
344
350
|
style="cursor: ${commonAttrs.cursor}"
|
|
345
351
|
@mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
|
|
352
|
+
@touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
|
|
346
353
|
></circle>
|
|
347
354
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
348
355
|
`
|
|
@@ -356,6 +363,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
356
363
|
fill="${commonAttrs.fill}"
|
|
357
364
|
style="cursor: ${commonAttrs.cursor}"
|
|
358
365
|
@mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
|
|
366
|
+
@touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
|
|
359
367
|
></polygon>
|
|
360
368
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
361
369
|
`
|
|
@@ -371,6 +379,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
371
379
|
stroke-width="${commonAttrs['stroke-width']}"
|
|
372
380
|
style="cursor: ${commonAttrs.cursor}"
|
|
373
381
|
@mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
|
|
382
|
+
@touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
|
|
374
383
|
></line>
|
|
375
384
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
376
385
|
`
|
|
@@ -392,6 +401,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
392
401
|
marker-end="url(#arrowhead-${shape.id})"
|
|
393
402
|
style="cursor: ${commonAttrs.cursor}"
|
|
394
403
|
@mousedown="${(e: MouseEvent) => this.onShapeMouseDown(e, shape)}"
|
|
404
|
+
@touchstart="${(e: TouchEvent) => this.onShapeMouseDown(e, shape)}"
|
|
395
405
|
></line>
|
|
396
406
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
397
407
|
`
|
|
@@ -401,7 +411,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
401
411
|
}
|
|
402
412
|
}
|
|
403
413
|
|
|
404
|
-
private onShapeMouseDown(event: MouseEvent, shape: Shape) {
|
|
414
|
+
private onShapeMouseDown(event: MouseEvent | TouchEvent, shape: Shape) {
|
|
405
415
|
event.stopPropagation()
|
|
406
416
|
|
|
407
417
|
this.shapes = this.shapes.map(s => ({
|
|
@@ -438,12 +448,20 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
438
448
|
}
|
|
439
449
|
|
|
440
450
|
const svg = this.svg as SVGSVGElement
|
|
441
|
-
|
|
442
|
-
|
|
451
|
+
|
|
452
|
+
if ('touches' in event) {
|
|
453
|
+
svg.addEventListener('touchmove', this.onShapeMouseMove)
|
|
454
|
+
svg.addEventListener('touchend', this.onShapeMouseUp)
|
|
455
|
+
} else {
|
|
456
|
+
svg.addEventListener('mousemove', this.onShapeMouseMove)
|
|
457
|
+
svg.addEventListener('mouseup', this.onShapeMouseUp)
|
|
458
|
+
}
|
|
443
459
|
}
|
|
444
460
|
|
|
445
|
-
private onShapeMouseMove = (event: MouseEvent) => {
|
|
446
|
-
if (!this.selectedShape)
|
|
461
|
+
private onShapeMouseMove = (event: MouseEvent | TouchEvent) => {
|
|
462
|
+
if (!this.selectedShape) {
|
|
463
|
+
return
|
|
464
|
+
}
|
|
447
465
|
|
|
448
466
|
const { x, y } = this.getSvgPoint(event)
|
|
449
467
|
|
|
@@ -481,21 +499,16 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
481
499
|
this.requestUpdate()
|
|
482
500
|
}
|
|
483
501
|
|
|
484
|
-
private onShapeMouseUp = () => {
|
|
502
|
+
private onShapeMouseUp = (event: MouseEvent | TouchEvent) => {
|
|
485
503
|
const svg = this.svg as SVGSVGElement
|
|
486
|
-
svg.removeEventListener('mousemove', this.onShapeMouseMove)
|
|
487
|
-
svg.removeEventListener('mouseup', this.onShapeMouseUp)
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
private getScale(): number {
|
|
491
|
-
if (!this.svg) return 1
|
|
492
|
-
|
|
493
|
-
const [vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)
|
|
494
504
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
505
|
+
if ('touches' in event) {
|
|
506
|
+
svg.removeEventListener('touchmove', this.onShapeMouseMove)
|
|
507
|
+
svg.removeEventListener('touchend', this.onShapeMouseUp)
|
|
508
|
+
} else {
|
|
509
|
+
svg.removeEventListener('mousemove', this.onShapeMouseMove)
|
|
510
|
+
svg.removeEventListener('mouseup', this.onShapeMouseUp)
|
|
511
|
+
}
|
|
499
512
|
}
|
|
500
513
|
|
|
501
514
|
private renderResizeHandles(shape: Shape) {
|
|
@@ -549,6 +562,7 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
549
562
|
class="resize-handle"
|
|
550
563
|
style="cursor: ${handle.cursor};"
|
|
551
564
|
@mousedown="${(e: MouseEvent) => this.onHandleMouseDown(e, shape, handle)}"
|
|
565
|
+
@touchstart="${(e: TouchEvent) => this.onHandleMouseDown(e, shape, handle)}"
|
|
552
566
|
></rect>
|
|
553
567
|
</g>
|
|
554
568
|
`
|
|
@@ -556,27 +570,73 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
556
570
|
`
|
|
557
571
|
}
|
|
558
572
|
|
|
559
|
-
private onHandleMouseDown(event: MouseEvent, shape: Shape, handle: any) {
|
|
573
|
+
private onHandleMouseDown(event: MouseEvent | TouchEvent, shape: Shape, handle: any) {
|
|
560
574
|
event.stopPropagation()
|
|
575
|
+
|
|
561
576
|
this.selectedShape = shape
|
|
562
577
|
this.offsetX = handle.x
|
|
563
578
|
this.offsetY = handle.y
|
|
564
579
|
const svg = this.svg as SVGSVGElement
|
|
565
|
-
|
|
566
|
-
|
|
580
|
+
|
|
581
|
+
if ('touches' in event) {
|
|
582
|
+
svg.addEventListener('touchmove', this.onHandleMouseMove)
|
|
583
|
+
svg.addEventListener('touchend', this.onHandleMouseUp)
|
|
584
|
+
} else {
|
|
585
|
+
svg.addEventListener('mousemove', this.onHandleMouseMove)
|
|
586
|
+
svg.addEventListener('mouseup', this.onHandleMouseUp)
|
|
587
|
+
}
|
|
567
588
|
}
|
|
568
589
|
|
|
569
|
-
private onHandleMouseMove = (event: MouseEvent) => {
|
|
570
|
-
if (!this.selectedShape)
|
|
590
|
+
private onHandleMouseMove = (event: MouseEvent | TouchEvent) => {
|
|
591
|
+
if (!this.selectedShape) {
|
|
592
|
+
return
|
|
593
|
+
}
|
|
594
|
+
|
|
571
595
|
const { x, y } = this.getSvgPoint(event)
|
|
572
596
|
|
|
573
597
|
switch (this.selectedShape.type) {
|
|
574
|
-
case 'text':
|
|
598
|
+
// case 'text':
|
|
599
|
+
// this.selectedShape.width = Math.abs(x - this.selectedShape.x!)
|
|
600
|
+
// this.selectedShape.height = Math.abs(y - this.selectedShape.y!)
|
|
601
|
+
// if (x < this.selectedShape.x!) this.selectedShape.x = x
|
|
602
|
+
// if (y < this.selectedShape.y!) this.selectedShape.y = y
|
|
603
|
+
// break
|
|
575
604
|
case 'rectangle':
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
605
|
+
const startX = this.selectedShape.x!
|
|
606
|
+
const startY = this.selectedShape.y!
|
|
607
|
+
const width = this.selectedShape.width!
|
|
608
|
+
const height = this.selectedShape.height!
|
|
609
|
+
|
|
610
|
+
// 핸들의 좌표에 따라 너비 및 높이 조정
|
|
611
|
+
if (this.offsetX === startX && this.offsetY === startY) {
|
|
612
|
+
// 상좌 핸들 (왼쪽 위)
|
|
613
|
+
this.selectedShape.x = x
|
|
614
|
+
this.selectedShape.y = y
|
|
615
|
+
this.selectedShape.width = width + (startX - x)
|
|
616
|
+
this.selectedShape.height = height + (startY - y)
|
|
617
|
+
} else if (this.offsetX === startX + width && this.offsetY === startY) {
|
|
618
|
+
// 상우 핸들 (오른쪽 위)
|
|
619
|
+
this.selectedShape.y = y
|
|
620
|
+
this.selectedShape.width = Math.abs(x - startX)
|
|
621
|
+
this.selectedShape.height = height + (startY - y)
|
|
622
|
+
} else if (this.offsetX === startX && this.offsetY === startY + height) {
|
|
623
|
+
// 하좌 핸들 (왼쪽 아래)
|
|
624
|
+
this.selectedShape.x = x
|
|
625
|
+
this.selectedShape.width = width + (startX - x)
|
|
626
|
+
this.selectedShape.height = Math.abs(y - startY)
|
|
627
|
+
} else if (this.offsetX === startX + width && this.offsetY === startY + height) {
|
|
628
|
+
// 하우 핸들 (오른쪽 아래)
|
|
629
|
+
this.selectedShape.width = Math.abs(x - startX)
|
|
630
|
+
this.selectedShape.height = Math.abs(y - startY)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// 최소 너비 및 높이 유지
|
|
634
|
+
this.selectedShape.width = Math.max(10, this.selectedShape.width!)
|
|
635
|
+
this.selectedShape.height = Math.max(10, this.selectedShape.height!)
|
|
636
|
+
|
|
637
|
+
this.offsetX = x
|
|
638
|
+
this.offsetY = y
|
|
639
|
+
|
|
580
640
|
break
|
|
581
641
|
case 'circle':
|
|
582
642
|
const dx = x - this.selectedShape.cx!
|
|
@@ -610,10 +670,17 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
610
670
|
this.requestUpdate()
|
|
611
671
|
}
|
|
612
672
|
|
|
613
|
-
private onHandleMouseUp = () => {
|
|
673
|
+
private onHandleMouseUp = (event: MouseEvent | TouchEvent) => {
|
|
614
674
|
const svg = this.svg as SVGSVGElement
|
|
615
|
-
|
|
616
|
-
|
|
675
|
+
|
|
676
|
+
if ('touches' in event) {
|
|
677
|
+
svg.removeEventListener('touchmove', this.onHandleMouseMove)
|
|
678
|
+
svg.removeEventListener('touchend', this.onHandleMouseUp)
|
|
679
|
+
} else {
|
|
680
|
+
svg.removeEventListener('mousemove', this.onHandleMouseMove)
|
|
681
|
+
svg.removeEventListener('mouseup', this.onHandleMouseUp)
|
|
682
|
+
}
|
|
683
|
+
|
|
617
684
|
this.selectedShape = null
|
|
618
685
|
}
|
|
619
686
|
|
|
@@ -740,4 +807,26 @@ export class OxImageMarker extends BaseImageMarker {
|
|
|
740
807
|
|
|
741
808
|
return context.measureText(text).width
|
|
742
809
|
}
|
|
810
|
+
|
|
811
|
+
private onFocus = () => {
|
|
812
|
+
this.addEventListener('keydown', this.handleKeyDown)
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
private onBlur = () => {
|
|
816
|
+
this.removeEventListener('keydown', this.handleKeyDown)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
private handleKeyDown = (event: KeyboardEvent) => {
|
|
820
|
+
if ((event.key === 'Delete' || event.key === 'Backspace') && this.selectedShape) {
|
|
821
|
+
this.deleteSelectedShape()
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
private deleteSelectedShape() {
|
|
826
|
+
if (this.selectedShape) {
|
|
827
|
+
this.shapes = this.shapes.filter(s => s.id !== this.selectedShape!.id)
|
|
828
|
+
this.selectedShape = null
|
|
829
|
+
this.requestUpdate()
|
|
830
|
+
}
|
|
831
|
+
}
|
|
743
832
|
}
|
|
@@ -55,6 +55,22 @@ const Template: Story<ArgTypes> = ({ imageUrl, shapes = [] }: ArgTypes) => html`
|
|
|
55
55
|
</style>
|
|
56
56
|
|
|
57
57
|
<style>
|
|
58
|
+
html,
|
|
59
|
+
body {
|
|
60
|
+
margin: 0;
|
|
61
|
+
padding: 0;
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
|
|
64
|
+
overscroll-behavior-y: none;
|
|
65
|
+
|
|
66
|
+
/* This is a font-stack that tries to use the system-default sans-serifs first */
|
|
67
|
+
font-family: Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
|
68
|
+
line-height: 1.5;
|
|
69
|
+
-webkit-font-smoothing: antialiased;
|
|
70
|
+
|
|
71
|
+
accent-color: var(--md-sys-color-primary);
|
|
72
|
+
}
|
|
73
|
+
|
|
58
74
|
body {
|
|
59
75
|
width: 100%;
|
|
60
76
|
height: 800px;
|