@operato/image-marker 8.0.0-alpha.29 → 8.0.0-alpha.37
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 +18 -0
- package/dist/src/base-image-marker.d.ts +19 -26
- package/dist/src/base-image-marker.js +93 -141
- package/dist/src/base-image-marker.js.map +1 -1
- package/dist/src/default-image-provider.d.ts +4 -0
- package/dist/src/default-image-provider.js +6 -0
- package/dist/src/default-image-provider.js.map +1 -0
- package/dist/src/ox-image-marker-view.js +4 -4
- package/dist/src/ox-image-marker-view.js.map +1 -1
- package/dist/src/ox-image-marker.d.ts +11 -11
- package/dist/src/ox-image-marker.js +173 -226
- package/dist/src/ox-image-marker.js.map +1 -1
- package/dist/src/types.d.ts +10 -0
- package/dist/src/types.js.map +1 -1
- package/dist/stories/test-image-provider.d.ts +7 -0
- package/dist/stories/test-image-provider.js +41 -0
- package/dist/stories/test-image-provider.js.map +1 -0
- package/dist/stories/test-image-provider.stories.d.ts +33 -0
- package/dist/stories/test-image-provider.stories.js +119 -0
- package/dist/stories/test-image-provider.stories.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -14
- package/src/base-image-marker.ts +105 -160
- package/src/default-image-provider.ts +7 -0
- package/src/ox-image-marker-view.ts +4 -4
- package/src/ox-image-marker.ts +187 -235
- package/src/types.ts +12 -0
- package/stories/test-image-provider.stories.ts +135 -0
- package/stories/test-image-provider.ts +49 -0
|
@@ -10,6 +10,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
10
10
|
super(...arguments);
|
|
11
11
|
this.currentMode = 'edit';
|
|
12
12
|
this.selectedShape = null;
|
|
13
|
+
// private drawingStarted: boolean = false
|
|
13
14
|
this.drawing = false;
|
|
14
15
|
this.startX = 0;
|
|
15
16
|
this.startY = 0;
|
|
@@ -17,142 +18,14 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
17
18
|
this.offsetY = 0;
|
|
18
19
|
this.shapeMoveThreshold = 10;
|
|
19
20
|
this.shapeMoveInitiated = false;
|
|
20
|
-
this.
|
|
21
|
-
event.preventDefault();
|
|
22
|
-
if (this.isDoubleTouch(event)) {
|
|
23
|
-
this.resetZoom();
|
|
24
|
-
}
|
|
25
|
-
if (event.touches.length === 1) {
|
|
26
|
-
this.setSelectedShape(null);
|
|
27
|
-
if (this.currentMode === 'shape') {
|
|
28
|
-
this.startDrawing(event);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
this.startPanning(event);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
else if (event.touches.length === 2) {
|
|
35
|
-
this.startPinchZooming(event);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
this.onMouseMoveForDrawing = (event) => {
|
|
39
|
-
if (!this.drawing) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
event.preventDefault();
|
|
43
|
-
const { x, y } = this.getSvgPoint(event);
|
|
44
|
-
const minDistance = 5;
|
|
45
|
-
const distance = Math.sqrt(Math.pow(x - this.startX, 2) + Math.pow(y - this.startY, 2));
|
|
46
|
-
if (!this.selectedShape && distance >= minDistance) {
|
|
47
|
-
let newShape;
|
|
48
|
-
switch (this.currentShapeType) {
|
|
49
|
-
case 'rectangle':
|
|
50
|
-
newShape = {
|
|
51
|
-
id: Date.now().toString(),
|
|
52
|
-
type: 'rectangle',
|
|
53
|
-
x: this.startX,
|
|
54
|
-
y: this.startY,
|
|
55
|
-
width: 0,
|
|
56
|
-
height: 0
|
|
57
|
-
};
|
|
58
|
-
break;
|
|
59
|
-
case 'circle':
|
|
60
|
-
newShape = {
|
|
61
|
-
id: Date.now().toString(),
|
|
62
|
-
type: 'circle',
|
|
63
|
-
cx: this.startX,
|
|
64
|
-
cy: this.startY,
|
|
65
|
-
r: 0
|
|
66
|
-
};
|
|
67
|
-
break;
|
|
68
|
-
case 'triangle':
|
|
69
|
-
newShape = {
|
|
70
|
-
id: Date.now().toString(),
|
|
71
|
-
type: 'triangle',
|
|
72
|
-
x1: this.startX,
|
|
73
|
-
y1: this.startY,
|
|
74
|
-
width: 0,
|
|
75
|
-
height: 0,
|
|
76
|
-
points: `${this.startX},${this.startY} ${this.startX},${this.startY} ${this.startX},${this.startY}`
|
|
77
|
-
};
|
|
78
|
-
break;
|
|
79
|
-
case 'line':
|
|
80
|
-
newShape = {
|
|
81
|
-
id: Date.now().toString(),
|
|
82
|
-
type: 'line',
|
|
83
|
-
x1: this.startX,
|
|
84
|
-
y1: this.startY,
|
|
85
|
-
width: 0,
|
|
86
|
-
height: 0
|
|
87
|
-
};
|
|
88
|
-
break;
|
|
89
|
-
case 'arrow':
|
|
90
|
-
newShape = {
|
|
91
|
-
id: Date.now().toString(),
|
|
92
|
-
type: 'arrow',
|
|
93
|
-
x1: this.startX,
|
|
94
|
-
y1: this.startY,
|
|
95
|
-
width: 0,
|
|
96
|
-
height: 0
|
|
97
|
-
};
|
|
98
|
-
break;
|
|
99
|
-
default:
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
this.shapes = [...this.shapes, newShape];
|
|
103
|
-
this.setSelectedShape(newShape);
|
|
104
|
-
}
|
|
105
|
-
if (this.selectedShape) {
|
|
106
|
-
switch (this.selectedShape.type) {
|
|
107
|
-
case 'rectangle':
|
|
108
|
-
this.selectedShape.x = Math.min(x, this.startX);
|
|
109
|
-
this.selectedShape.y = Math.min(y, this.startY);
|
|
110
|
-
this.selectedShape.width = Math.abs(x - this.startX);
|
|
111
|
-
this.selectedShape.height = Math.abs(y - this.startY);
|
|
112
|
-
break;
|
|
113
|
-
case 'circle':
|
|
114
|
-
const dx = x - this.selectedShape.cx;
|
|
115
|
-
const dy = y - this.selectedShape.cy;
|
|
116
|
-
this.selectedShape.r = Math.sqrt(dx * dx + dy * dy);
|
|
117
|
-
break;
|
|
118
|
-
case 'triangle':
|
|
119
|
-
const x2 = x;
|
|
120
|
-
const y2 = y;
|
|
121
|
-
const x3 = this.startX - (x - this.startX);
|
|
122
|
-
const y3 = y;
|
|
123
|
-
this.selectedShape.points = `${this.startX},${this.startY} ${x2},${y2} ${x3},${y3}`;
|
|
124
|
-
break;
|
|
125
|
-
case 'line':
|
|
126
|
-
case 'arrow':
|
|
127
|
-
this.selectedShape.x2 = x;
|
|
128
|
-
this.selectedShape.y2 = y;
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
this.requestUpdate();
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
this.onMouseUpForDrawing = (event) => {
|
|
135
|
-
event.preventDefault();
|
|
136
|
-
this.drawing = false;
|
|
137
|
-
const svg = this.svg;
|
|
138
|
-
if ('touches' in event) {
|
|
139
|
-
svg.removeEventListener('touchmove', this.onMouseMoveForDrawing);
|
|
140
|
-
svg.removeEventListener('touchend', this.onMouseUpForDrawing);
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
svg.removeEventListener('mousemove', this.onMouseMoveForDrawing);
|
|
144
|
-
svg.removeEventListener('mouseup', this.onMouseUpForDrawing);
|
|
145
|
-
}
|
|
146
|
-
this.imageMarkerMode.setMode('edit');
|
|
147
|
-
this.requestUpdate();
|
|
148
|
-
};
|
|
149
|
-
this.onMouseMoveOnShape = (event) => {
|
|
21
|
+
this.onPointerMoveOnShape = (event) => {
|
|
150
22
|
if (!this.selectedShape) {
|
|
151
23
|
return;
|
|
152
24
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
25
|
+
// TODO check if single touch ... (멀티터치를 제외해야한다).
|
|
26
|
+
// if ('touches' in event && event.touches.length > 1) {
|
|
27
|
+
// return
|
|
28
|
+
// }
|
|
156
29
|
event.preventDefault();
|
|
157
30
|
const { x, y } = this.getSvgPoint(event);
|
|
158
31
|
const dx = x - this.offsetX;
|
|
@@ -190,25 +63,19 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
190
63
|
}
|
|
191
64
|
this.requestUpdate();
|
|
192
65
|
};
|
|
193
|
-
this.
|
|
66
|
+
this.onPointerUpOnShape = (event) => {
|
|
194
67
|
if (!this.selectedShape) {
|
|
195
68
|
return;
|
|
196
69
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
70
|
+
// TODO
|
|
71
|
+
// if ('touches' in event && event.touches.length > 1) {
|
|
72
|
+
// return
|
|
73
|
+
// }
|
|
200
74
|
event.preventDefault();
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
svg.removeEventListener('touchmove', this.onMouseMoveOnShape);
|
|
204
|
-
svg.removeEventListener('touchend', this.onMouseUpOnShape);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
svg.removeEventListener('mousemove', this.onMouseMoveOnShape);
|
|
208
|
-
svg.removeEventListener('mouseup', this.onMouseUpOnShape);
|
|
209
|
-
}
|
|
75
|
+
document.removeEventListener('pointermove', this.onPointerMoveOnShape);
|
|
76
|
+
document.removeEventListener('pointerup', this.onPointerUpOnShape);
|
|
210
77
|
};
|
|
211
|
-
this.
|
|
78
|
+
this.onResizeHandlePointerMove = (event) => {
|
|
212
79
|
if (!this.selectedShape) {
|
|
213
80
|
return;
|
|
214
81
|
}
|
|
@@ -282,17 +149,10 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
282
149
|
}
|
|
283
150
|
this.requestUpdate();
|
|
284
151
|
};
|
|
285
|
-
this.
|
|
152
|
+
this.onResizeHandlePointerUp = (event) => {
|
|
286
153
|
event.preventDefault();
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
svg.removeEventListener('touchmove', this.onResizeHandleMouseMove);
|
|
290
|
-
svg.removeEventListener('touchend', this.onResizeHandleMouseUp);
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
svg.removeEventListener('mousemove', this.onResizeHandleMouseMove);
|
|
294
|
-
svg.removeEventListener('mouseup', this.onResizeHandleMouseUp);
|
|
295
|
-
}
|
|
154
|
+
document.removeEventListener('pointermove', this.onResizeHandlePointerMove);
|
|
155
|
+
document.removeEventListener('pointerup', this.onResizeHandlePointerUp);
|
|
296
156
|
};
|
|
297
157
|
this.onFocus = () => {
|
|
298
158
|
this.addEventListener('keydown', this.handleKeyDown);
|
|
@@ -350,14 +210,15 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
350
210
|
return html `
|
|
351
211
|
<div class="container">
|
|
352
212
|
<svg
|
|
353
|
-
@mousedown=${this.onSvgMouseDown}
|
|
354
|
-
@touchstart=${this.onSvgTouchStart}
|
|
355
213
|
@wheel=${this.onSvgWheel}
|
|
356
|
-
@
|
|
214
|
+
@doubletap=${this.onSvgDoubleTap}
|
|
215
|
+
@pinch=${this.onSvgPinch}
|
|
216
|
+
@drag=${this.onSvgDrag}
|
|
217
|
+
@click=${this.onSvgClick}
|
|
357
218
|
viewBox=${this.viewBox}
|
|
358
219
|
?drawing=${this.currentMode == 'shape'}
|
|
359
220
|
>
|
|
360
|
-
<image href=${this.
|
|
221
|
+
<image href=${this.currentImage} @load=${this.onImageLoad}></image>
|
|
361
222
|
${this.shapes.map(shape => keyed(shape.id, this.renderShape(shape)))}
|
|
362
223
|
</svg>
|
|
363
224
|
</div>
|
|
@@ -369,7 +230,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
369
230
|
const { mode, shapeType } = e.detail;
|
|
370
231
|
this.setMode(mode, shapeType);
|
|
371
232
|
}}
|
|
372
|
-
@tap-fit-size=${() => this.
|
|
233
|
+
@tap-fit-size=${() => this.reset()}
|
|
373
234
|
@tap-delete=${() => this.deleteSelectedShape()}
|
|
374
235
|
@tap-save=${() => {
|
|
375
236
|
this.dispatchEvent(new CustomEvent('shapes-changed', {
|
|
@@ -381,48 +242,152 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
381
242
|
></ox-image-marker-mode>
|
|
382
243
|
`;
|
|
383
244
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
245
|
+
setMode(mode, shapeType) {
|
|
246
|
+
if (mode == 'view') {
|
|
247
|
+
this.setSelectedShape(null);
|
|
248
|
+
}
|
|
249
|
+
this.currentMode = mode;
|
|
250
|
+
this.currentShapeType = shapeType;
|
|
251
|
+
}
|
|
252
|
+
onSvgPinch(e) {
|
|
253
|
+
e.stopPropagation();
|
|
254
|
+
const { scale, centerX, centerY } = e.detail;
|
|
255
|
+
this.zoom(scale, centerX, centerY);
|
|
256
|
+
}
|
|
257
|
+
onSvgDrag(e) {
|
|
258
|
+
const { deltaX, deltaY, end } = e.detail;
|
|
387
259
|
if (this.currentMode === 'shape') {
|
|
388
|
-
this.
|
|
260
|
+
this.drawShape(e);
|
|
389
261
|
}
|
|
390
262
|
else {
|
|
391
|
-
this.
|
|
263
|
+
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
264
|
+
const scaleX = vbWidth / this.svg.clientWidth;
|
|
265
|
+
const scaleY = vbHeight / this.svg.clientHeight;
|
|
266
|
+
const scale = Math.max(scaleX, scaleY);
|
|
267
|
+
const newVbX = vbX - deltaX * scale;
|
|
268
|
+
const newVbY = vbY - deltaY * scale;
|
|
269
|
+
this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`;
|
|
270
|
+
this.debouncedUpdateImage();
|
|
392
271
|
}
|
|
393
272
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
273
|
+
onSvgClick(e) {
|
|
274
|
+
if (this.currentMode === 'shape' && this.currentShapeType === 'text') {
|
|
275
|
+
const { x, y } = this.getSvgPoint(e);
|
|
397
276
|
const textElement = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
398
277
|
textElement.setAttribute('x', x.toString());
|
|
399
278
|
textElement.setAttribute('y', y.toString());
|
|
400
279
|
textElement.textContent = 'ABC';
|
|
401
280
|
this.svg.appendChild(textElement);
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
281
|
+
/* 강제 지연은 iOS에서 input focus를 받지 못하는 현상이 있다. */
|
|
282
|
+
this.showTextInput(textElement, null, { x, y });
|
|
283
|
+
this.imageMarkerMode.setMode('edit');
|
|
405
284
|
}
|
|
406
|
-
|
|
285
|
+
}
|
|
286
|
+
drawShape(e) {
|
|
287
|
+
const { end } = e.detail;
|
|
288
|
+
const { x, y } = this.getSvgPoint(e);
|
|
289
|
+
if (!this.drawing) {
|
|
407
290
|
this.startX = x;
|
|
408
291
|
this.startY = y;
|
|
292
|
+
this.setSelectedShape(null);
|
|
409
293
|
this.drawing = true;
|
|
410
294
|
}
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
295
|
+
else if (this.drawing) {
|
|
296
|
+
const minDistance = 5;
|
|
297
|
+
const distance = Math.sqrt(Math.pow(x - this.startX, 2) + Math.pow(y - this.startY, 2));
|
|
298
|
+
if (!this.selectedShape && distance >= minDistance) {
|
|
299
|
+
let newShape;
|
|
300
|
+
switch (this.currentShapeType) {
|
|
301
|
+
case 'rectangle':
|
|
302
|
+
newShape = {
|
|
303
|
+
id: Date.now().toString(),
|
|
304
|
+
type: 'rectangle',
|
|
305
|
+
x: this.startX,
|
|
306
|
+
y: this.startY,
|
|
307
|
+
width: 0,
|
|
308
|
+
height: 0
|
|
309
|
+
};
|
|
310
|
+
break;
|
|
311
|
+
case 'circle':
|
|
312
|
+
newShape = {
|
|
313
|
+
id: Date.now().toString(),
|
|
314
|
+
type: 'circle',
|
|
315
|
+
cx: this.startX,
|
|
316
|
+
cy: this.startY,
|
|
317
|
+
r: 0
|
|
318
|
+
};
|
|
319
|
+
break;
|
|
320
|
+
case 'triangle':
|
|
321
|
+
newShape = {
|
|
322
|
+
id: Date.now().toString(),
|
|
323
|
+
type: 'triangle',
|
|
324
|
+
x1: this.startX,
|
|
325
|
+
y1: this.startY,
|
|
326
|
+
width: 0,
|
|
327
|
+
height: 0,
|
|
328
|
+
points: `${this.startX},${this.startY} ${this.startX},${this.startY} ${this.startX},${this.startY}`
|
|
329
|
+
};
|
|
330
|
+
break;
|
|
331
|
+
case 'line':
|
|
332
|
+
newShape = {
|
|
333
|
+
id: Date.now().toString(),
|
|
334
|
+
type: 'line',
|
|
335
|
+
x1: this.startX,
|
|
336
|
+
y1: this.startY,
|
|
337
|
+
width: 0,
|
|
338
|
+
height: 0
|
|
339
|
+
};
|
|
340
|
+
break;
|
|
341
|
+
case 'arrow':
|
|
342
|
+
newShape = {
|
|
343
|
+
id: Date.now().toString(),
|
|
344
|
+
type: 'arrow',
|
|
345
|
+
x1: this.startX,
|
|
346
|
+
y1: this.startY,
|
|
347
|
+
width: 0,
|
|
348
|
+
height: 0
|
|
349
|
+
};
|
|
350
|
+
break;
|
|
351
|
+
default:
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
this.shapes = [...this.shapes, newShape];
|
|
355
|
+
this.setSelectedShape(newShape);
|
|
356
|
+
}
|
|
357
|
+
if (this.selectedShape) {
|
|
358
|
+
switch (this.selectedShape.type) {
|
|
359
|
+
case 'rectangle':
|
|
360
|
+
this.selectedShape.x = Math.min(x, this.startX);
|
|
361
|
+
this.selectedShape.y = Math.min(y, this.startY);
|
|
362
|
+
this.selectedShape.width = Math.abs(x - this.startX);
|
|
363
|
+
this.selectedShape.height = Math.abs(y - this.startY);
|
|
364
|
+
break;
|
|
365
|
+
case 'circle':
|
|
366
|
+
const dx = x - this.selectedShape.cx;
|
|
367
|
+
const dy = y - this.selectedShape.cy;
|
|
368
|
+
this.selectedShape.r = Math.sqrt(dx * dx + dy * dy);
|
|
369
|
+
break;
|
|
370
|
+
case 'triangle':
|
|
371
|
+
const x2 = x;
|
|
372
|
+
const y2 = y;
|
|
373
|
+
const x3 = this.startX - (x - this.startX);
|
|
374
|
+
const y3 = y;
|
|
375
|
+
this.selectedShape.points = `${this.startX},${this.startY} ${x2},${y2} ${x3},${y3}`;
|
|
376
|
+
break;
|
|
377
|
+
case 'line':
|
|
378
|
+
case 'arrow':
|
|
379
|
+
this.selectedShape.x2 = x;
|
|
380
|
+
this.selectedShape.y2 = y;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
this.requestUpdate();
|
|
384
|
+
}
|
|
385
|
+
if (end) {
|
|
386
|
+
this.drawing = false;
|
|
387
|
+
this.imageMarkerMode.setMode('edit');
|
|
388
|
+
this.requestUpdate();
|
|
389
|
+
}
|
|
423
390
|
}
|
|
424
|
-
this.currentMode = mode;
|
|
425
|
-
this.currentShapeType = shapeType;
|
|
426
391
|
}
|
|
427
392
|
setSelectedShape(shape) {
|
|
428
393
|
this.selectedShape = shape;
|
|
@@ -459,8 +424,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
459
424
|
y="${shape.y}"
|
|
460
425
|
fill="${commonAttrs.stroke}"
|
|
461
426
|
style="cursor: ${commonAttrs.cursor}; font-size: 16px;"
|
|
462
|
-
@
|
|
463
|
-
@touchstart="${(e) => this.onMouseDownOnShape(e, shape)}"
|
|
427
|
+
@pointerdown="${(e) => this.onPointerDownOnShape(e, shape)}"
|
|
464
428
|
@dblclick="${(e) => this.onTextDoubleClick(e, shape)}"
|
|
465
429
|
>${shape.text}</text>
|
|
466
430
|
`;
|
|
@@ -475,8 +439,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
475
439
|
stroke-width="${commonAttrs['stroke-width']}"
|
|
476
440
|
fill="${commonAttrs.fill}"
|
|
477
441
|
style="cursor: ${commonAttrs.cursor}"
|
|
478
|
-
@
|
|
479
|
-
@touchstart="${(e) => this.onMouseDownOnShape(e, shape)}"
|
|
442
|
+
@pointerdown="${(e) => this.onPointerDownOnShape(e, shape)}"
|
|
480
443
|
></rect>
|
|
481
444
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
482
445
|
`;
|
|
@@ -490,8 +453,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
490
453
|
stroke-width="${commonAttrs['stroke-width']}"
|
|
491
454
|
fill="${commonAttrs.fill}"
|
|
492
455
|
style="cursor: ${commonAttrs.cursor}"
|
|
493
|
-
@
|
|
494
|
-
@touchstart="${(e) => this.onMouseDownOnShape(e, shape)}"
|
|
456
|
+
@pointerdown="${(e) => this.onPointerDownOnShape(e, shape)}"
|
|
495
457
|
></circle>
|
|
496
458
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
497
459
|
`;
|
|
@@ -503,8 +465,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
503
465
|
stroke-width="${commonAttrs['stroke-width']}"
|
|
504
466
|
fill="${commonAttrs.fill}"
|
|
505
467
|
style="cursor: ${commonAttrs.cursor}"
|
|
506
|
-
@
|
|
507
|
-
@touchstart="${(e) => this.onMouseDownOnShape(e, shape)}"
|
|
468
|
+
@pointerdown="${(e) => this.onPointerDownOnShape(e, shape)}"
|
|
508
469
|
></polygon>
|
|
509
470
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
510
471
|
`;
|
|
@@ -528,8 +489,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
528
489
|
stroke-width="25"
|
|
529
490
|
stroke-opacity="0"
|
|
530
491
|
pointer-events="stroke"
|
|
531
|
-
@
|
|
532
|
-
@touchstart="${(e) => this.onMouseDownOnShape(e, shape)}"
|
|
492
|
+
@pointerdown="${(e) => this.onPointerDownOnShape(e, shape)}"
|
|
533
493
|
@mouseenter="${() => (this.svg.style.cursor = 'pointer')}"
|
|
534
494
|
@mouseleave="${() => (this.svg.style.cursor = 'default')}"
|
|
535
495
|
></line>
|
|
@@ -561,10 +521,10 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
561
521
|
stroke-width="25"
|
|
562
522
|
stroke-opacity="0"
|
|
563
523
|
pointer-events="stroke"
|
|
564
|
-
@mousedown="${(e) => this.
|
|
565
|
-
@touchstart="${(e) => this.onMouseDownOnShape(e, shape)}"
|
|
524
|
+
@mousedown="${(e) => this.onPointerDownOnShape(e, shape)}"
|
|
566
525
|
@mouseenter="${() => (this.svg.style.cursor = 'pointer')}"
|
|
567
526
|
@mouseleave="${() => (this.svg.style.cursor = 'default')}"
|
|
527
|
+
@pointerdown="${(e) => this.currentMode == 'edit' && e.stopPropagation()}"
|
|
568
528
|
></line>
|
|
569
529
|
${shape.selected ? this.renderResizeHandles(shape) : ''}
|
|
570
530
|
`;
|
|
@@ -572,13 +532,14 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
572
532
|
return nothing;
|
|
573
533
|
}
|
|
574
534
|
}
|
|
575
|
-
|
|
535
|
+
onPointerDownOnShape(event, shape) {
|
|
576
536
|
if (this.currentMode !== 'edit') {
|
|
577
537
|
return;
|
|
578
538
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
539
|
+
// TODO check if single touch ... (멀티터치를 제외해야한다).
|
|
540
|
+
// if ('touches' in event && event.touches.length > 1) {
|
|
541
|
+
// return
|
|
542
|
+
// }
|
|
582
543
|
event.stopPropagation();
|
|
583
544
|
event.preventDefault();
|
|
584
545
|
this.shapes = this.shapes.map(s => ({
|
|
@@ -590,15 +551,8 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
590
551
|
const { x, y } = this.getSvgPoint(event);
|
|
591
552
|
this.offsetX = x;
|
|
592
553
|
this.offsetY = y;
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
svg.addEventListener('touchmove', this.onMouseMoveOnShape);
|
|
596
|
-
svg.addEventListener('touchend', this.onMouseUpOnShape);
|
|
597
|
-
}
|
|
598
|
-
else {
|
|
599
|
-
svg.addEventListener('mousemove', this.onMouseMoveOnShape);
|
|
600
|
-
svg.addEventListener('mouseup', this.onMouseUpOnShape);
|
|
601
|
-
}
|
|
554
|
+
document.addEventListener('pointermove', this.onPointerMoveOnShape);
|
|
555
|
+
document.addEventListener('pointerup', this.onPointerUpOnShape);
|
|
602
556
|
}
|
|
603
557
|
renderResizeHandles(shape) {
|
|
604
558
|
let handles = [];
|
|
@@ -647,28 +601,20 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
647
601
|
stroke="black"
|
|
648
602
|
class="resize-handle"
|
|
649
603
|
style="cursor: ${handle.cursor};"
|
|
650
|
-
@
|
|
651
|
-
@touchstart="${(e) => this.onResizeHandleMouseDown(e, shape, handle)}"
|
|
604
|
+
@pointerdown="${(e) => this.onResizeHandlePointerDown(e, shape, handle)}"
|
|
652
605
|
></rect>
|
|
653
606
|
</g>
|
|
654
607
|
`)}
|
|
655
608
|
`;
|
|
656
609
|
}
|
|
657
|
-
|
|
610
|
+
onResizeHandlePointerDown(event, shape, handle) {
|
|
658
611
|
event.stopPropagation();
|
|
659
612
|
event.preventDefault();
|
|
660
613
|
this.setSelectedShape(shape);
|
|
661
614
|
this.offsetX = handle.x;
|
|
662
615
|
this.offsetY = handle.y;
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
svg.addEventListener('touchmove', this.onResizeHandleMouseMove);
|
|
666
|
-
svg.addEventListener('touchend', this.onResizeHandleMouseUp);
|
|
667
|
-
}
|
|
668
|
-
else {
|
|
669
|
-
svg.addEventListener('mousemove', this.onResizeHandleMouseMove);
|
|
670
|
-
svg.addEventListener('mouseup', this.onResizeHandleMouseUp);
|
|
671
|
-
}
|
|
616
|
+
document.addEventListener('pointermove', this.onResizeHandlePointerMove);
|
|
617
|
+
document.addEventListener('pointerup', this.onResizeHandlePointerUp);
|
|
672
618
|
}
|
|
673
619
|
onTextDoubleClick(event, shape) {
|
|
674
620
|
event.stopPropagation();
|
|
@@ -707,7 +653,8 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
|
|
|
707
653
|
textElement.style.visibility = 'hidden';
|
|
708
654
|
document.body.appendChild(input);
|
|
709
655
|
this.adjustInputWidth(input);
|
|
710
|
-
|
|
656
|
+
/* iOS에서는 딜레이를 주었을 때 focus()를 받지 못하는 현상이 있으므로, delay 없이 바로 focus를 설정함. */
|
|
657
|
+
input.focus();
|
|
711
658
|
input.addEventListener('input', () => {
|
|
712
659
|
this.adjustInputWidth(input);
|
|
713
660
|
});
|