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

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.
@@ -15,14 +15,32 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
15
15
  this.startY = 0;
16
16
  this.offsetX = 0;
17
17
  this.offsetY = 0;
18
- this.handleKeyDown = (event) => {
19
- if ((event.key === 'Delete' || event.key === 'Backspace') && this.selectedShape) {
20
- this.deleteSelectedShape();
18
+ this.onSvgTouchStart = (event) => {
19
+ event.preventDefault();
20
+ if (this.isDoubleTouch(event)) {
21
+ this.resetZoom();
22
+ }
23
+ if (event.touches.length === 1) {
24
+ this.selectedShape = null;
25
+ this.shapes = this.shapes.map(s => {
26
+ return { ...s, selected: false };
27
+ });
28
+ if (this.currentMode === 'move') {
29
+ this.startPanning(event);
30
+ }
31
+ else if (this.currentMode === 'draw') {
32
+ this.startDrawing(event);
33
+ }
34
+ }
35
+ else if (event.touches.length === 2) {
36
+ this.startPinchZooming(event);
21
37
  }
22
38
  };
23
- this.onMouseMove = (event) => {
24
- if (!this.drawing)
39
+ this.onDrawingMouseMove = (event) => {
40
+ if (!this.drawing) {
25
41
  return;
42
+ }
43
+ event.preventDefault();
26
44
  const { x, y } = this.getSvgPoint(event);
27
45
  const minDistance = 5;
28
46
  const distance = Math.sqrt(Math.pow(x - this.startX, 2) + Math.pow(y - this.startY, 2));
@@ -114,19 +132,28 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
114
132
  this.requestUpdate();
115
133
  }
116
134
  };
117
- this.onMouseUp = () => {
135
+ this.onDrawingMouseUp = (event) => {
136
+ event.preventDefault();
118
137
  this.drawing = false;
119
138
  const svg = this.svg;
120
- svg.removeEventListener('mousemove', this.onMouseMove);
121
- svg.removeEventListener('mouseup', this.onMouseUp);
139
+ if ('touches' in event) {
140
+ svg.removeEventListener('touchmove', this.onDrawingMouseMove);
141
+ svg.removeEventListener('touchend', this.onDrawingMouseUp);
142
+ }
143
+ else {
144
+ svg.removeEventListener('mousemove', this.onDrawingMouseMove);
145
+ svg.removeEventListener('mouseup', this.onDrawingMouseUp);
146
+ }
122
147
  if (this.selectedShape) {
123
148
  this.selectedShape.selected = true;
124
149
  }
125
150
  this.requestUpdate();
126
151
  };
127
152
  this.onShapeMouseMove = (event) => {
128
- if (!this.selectedShape)
153
+ if (!this.selectedShape) {
129
154
  return;
155
+ }
156
+ event.preventDefault();
130
157
  const { x, y } = this.getSvgPoint(event);
131
158
  switch (this.selectedShape.type) {
132
159
  case 'text':
@@ -159,24 +186,66 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
159
186
  }
160
187
  this.requestUpdate();
161
188
  };
162
- this.onShapeMouseUp = () => {
189
+ this.onShapeMouseUp = (event) => {
190
+ event.preventDefault();
163
191
  const svg = this.svg;
164
- svg.removeEventListener('mousemove', this.onShapeMouseMove);
165
- svg.removeEventListener('mouseup', this.onShapeMouseUp);
192
+ if ('touches' in event) {
193
+ svg.removeEventListener('touchmove', this.onShapeMouseMove);
194
+ svg.removeEventListener('touchend', this.onShapeMouseUp);
195
+ }
196
+ else {
197
+ svg.removeEventListener('mousemove', this.onShapeMouseMove);
198
+ svg.removeEventListener('mouseup', this.onShapeMouseUp);
199
+ }
166
200
  };
167
201
  this.onHandleMouseMove = (event) => {
168
- if (!this.selectedShape)
202
+ if (!this.selectedShape) {
169
203
  return;
204
+ }
205
+ event.preventDefault();
170
206
  const { x, y } = this.getSvgPoint(event);
171
207
  switch (this.selectedShape.type) {
172
- case 'text':
208
+ // case 'text':
209
+ // this.selectedShape.width = Math.abs(x - this.selectedShape.x!)
210
+ // this.selectedShape.height = Math.abs(y - this.selectedShape.y!)
211
+ // if (x < this.selectedShape.x!) this.selectedShape.x = x
212
+ // if (y < this.selectedShape.y!) this.selectedShape.y = y
213
+ // break
173
214
  case 'rectangle':
174
- this.selectedShape.width = Math.abs(x - this.selectedShape.x);
175
- this.selectedShape.height = Math.abs(y - this.selectedShape.y);
176
- if (x < this.selectedShape.x)
215
+ const startX = this.selectedShape.x;
216
+ const startY = this.selectedShape.y;
217
+ const width = this.selectedShape.width;
218
+ const height = this.selectedShape.height;
219
+ // 핸들의 좌표에 따라 너비 및 높이 조정
220
+ if (this.offsetX === startX && this.offsetY === startY) {
221
+ // 상좌 핸들 (왼쪽 위)
177
222
  this.selectedShape.x = x;
178
- if (y < this.selectedShape.y)
179
223
  this.selectedShape.y = y;
224
+ this.selectedShape.width = width + (startX - x);
225
+ this.selectedShape.height = height + (startY - y);
226
+ }
227
+ else if (this.offsetX === startX + width && this.offsetY === startY) {
228
+ // 상우 핸들 (오른쪽 위)
229
+ this.selectedShape.y = y;
230
+ this.selectedShape.width = Math.abs(x - startX);
231
+ this.selectedShape.height = height + (startY - y);
232
+ }
233
+ else if (this.offsetX === startX && this.offsetY === startY + height) {
234
+ // 하좌 핸들 (왼쪽 아래)
235
+ this.selectedShape.x = x;
236
+ this.selectedShape.width = width + (startX - x);
237
+ this.selectedShape.height = Math.abs(y - startY);
238
+ }
239
+ else if (this.offsetX === startX + width && this.offsetY === startY + height) {
240
+ // 하우 핸들 (오른쪽 아래)
241
+ this.selectedShape.width = Math.abs(x - startX);
242
+ this.selectedShape.height = Math.abs(y - startY);
243
+ }
244
+ // 최소 너비 및 높이 유지
245
+ this.selectedShape.width = Math.max(10, this.selectedShape.width);
246
+ this.selectedShape.height = Math.max(10, this.selectedShape.height);
247
+ this.offsetX = x;
248
+ this.offsetY = y;
180
249
  break;
181
250
  case 'circle':
182
251
  const dx = x - this.selectedShape.cx;
@@ -209,12 +278,30 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
209
278
  }
210
279
  this.requestUpdate();
211
280
  };
212
- this.onHandleMouseUp = () => {
281
+ this.onHandleMouseUp = (event) => {
282
+ event.preventDefault();
213
283
  const svg = this.svg;
214
- svg.removeEventListener('mousemove', this.onHandleMouseMove);
215
- svg.removeEventListener('mouseup', this.onHandleMouseUp);
284
+ if ('touches' in event) {
285
+ svg.removeEventListener('touchmove', this.onHandleMouseMove);
286
+ svg.removeEventListener('touchend', this.onHandleMouseUp);
287
+ }
288
+ else {
289
+ svg.removeEventListener('mousemove', this.onHandleMouseMove);
290
+ svg.removeEventListener('mouseup', this.onHandleMouseUp);
291
+ }
216
292
  this.selectedShape = null;
217
293
  };
294
+ this.onFocus = () => {
295
+ this.addEventListener('keydown', this.handleKeyDown);
296
+ };
297
+ this.onBlur = () => {
298
+ this.removeEventListener('keydown', this.handleKeyDown);
299
+ };
300
+ this.handleKeyDown = (event) => {
301
+ if ((event.key === 'Delete' || event.key === 'Backspace') && this.selectedShape) {
302
+ this.deleteSelectedShape();
303
+ }
304
+ };
218
305
  }
219
306
  static { this.styles = [
220
307
  ...BaseImageMarker.styles,
@@ -247,28 +334,23 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
247
334
  ]; }
248
335
  connectedCallback() {
249
336
  super.connectedCallback();
250
- // 키다운 이벤트 리스너 추가
251
- window.addEventListener('keydown', this.handleKeyDown);
337
+ this.setAttribute('tabindex', '0');
338
+ this.addEventListener('focus', this.onFocus);
339
+ this.addEventListener('blur', this.onBlur);
252
340
  }
253
341
  disconnectedCallback() {
254
342
  super.disconnectedCallback();
255
- // 키다운 이벤트 리스너 제거
256
- window.removeEventListener('keydown', this.handleKeyDown);
257
- }
258
- deleteSelectedShape() {
259
- if (this.selectedShape) {
260
- this.shapes = this.shapes.filter(s => s.id !== this.selectedShape.id);
261
- this.selectedShape = null;
262
- this.requestUpdate();
263
- }
343
+ this.removeEventListener('focus', this.onFocus);
344
+ this.removeEventListener('blur', this.onBlur);
264
345
  }
265
346
  render() {
266
347
  return html `
267
348
  <div class="container">
268
349
  <svg
269
350
  @mousedown=${this.onSvgMouseDown}
270
- @wheel=${this.onWheel}
271
- @dblclick=${this.onDoubleClick}
351
+ @touchstart=${this.onSvgTouchStart}
352
+ @wheel=${this.onSvgWheel}
353
+ @dblclick=${this.onSvgDoubleClick}
272
354
  viewBox=${this.viewBox}
273
355
  >
274
356
  <image href=${this.imageUrl} @load=${this.onImageLoad}></image>
@@ -283,8 +365,9 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
283
365
  const { mode, shapeType } = e.detail;
284
366
  this.setMode(mode, shapeType);
285
367
  }}
286
- @clicked-delete=${() => this.deleteSelectedShape()}
287
- @clicked-save=${() => {
368
+ @tap-fit-size=${() => this.resetZoom()}
369
+ @tap-delete=${() => this.deleteSelectedShape()}
370
+ @tap-save=${() => {
288
371
  this.dispatchEvent(new CustomEvent('shapes-changed', {
289
372
  detail: this.shapes,
290
373
  bubbles: true,
@@ -295,35 +378,16 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
295
378
  `;
296
379
  }
297
380
  onSvgMouseDown(event) {
298
- const svg = this.svg;
381
+ event.preventDefault();
299
382
  this.selectedShape = null;
300
383
  this.shapes = this.shapes.map(s => {
301
384
  return { ...s, selected: false };
302
385
  });
303
- this.selectedShape = null;
304
386
  if (this.currentMode === 'move') {
305
- this.isPanning = true;
306
- this.panStart = { x: event.clientX, y: event.clientY };
307
- svg.classList.add('dragging');
308
- svg.addEventListener('mousemove', this.onPanMouseMove);
309
- svg.addEventListener('mouseup', this.onPanMouseUp);
310
- }
311
- else if (this.currentMode === 'select') {
312
- this.startShapeDragging(event);
313
- svg.addEventListener('mousemove', this.onShapeMouseMove);
314
- svg.addEventListener('mouseup', this.onShapeMouseUp);
387
+ this.startPanning(event);
315
388
  }
316
389
  else if (this.currentMode === 'draw') {
317
390
  this.startDrawing(event);
318
- svg.addEventListener('mousemove', this.onMouseMove);
319
- svg.addEventListener('mouseup', this.onMouseUp);
320
- }
321
- }
322
- startShapeDragging(event) {
323
- const { x, y } = this.getSvgPoint(event);
324
- if (this.selectedShape) {
325
- this.offsetX = x - (this.selectedShape.x || this.selectedShape.cx || 0);
326
- this.offsetY = y - (this.selectedShape.y || this.selectedShape.cy || 0);
327
391
  }
328
392
  }
329
393
  startDrawing(event) {
@@ -343,16 +407,25 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
343
407
  this.startY = y;
344
408
  this.drawing = true;
345
409
  }
410
+ if ('touches' in event) {
411
+ this.svg.addEventListener('touchmove', this.onDrawingMouseMove);
412
+ this.svg.addEventListener('touchend', this.onDrawingMouseUp);
413
+ }
414
+ else {
415
+ this.svg.addEventListener('mousemove', this.onDrawingMouseMove);
416
+ this.svg.addEventListener('mouseup', this.onDrawingMouseUp);
417
+ }
346
418
  }
347
419
  setMode(mode, shapeType) {
348
420
  this.currentMode = mode;
349
421
  this.currentShapeType = shapeType;
350
422
  }
351
423
  getSvgPoint(event) {
424
+ const { x, y } = this.getPointFromEvent(event);
352
425
  const svg = this.svg;
353
426
  const point = svg.createSVGPoint();
354
- point.x = event.clientX;
355
- point.y = event.clientY;
427
+ point.x = x;
428
+ point.y = y;
356
429
  const ctm = svg.getScreenCTM().inverse();
357
430
  return point.matrixTransform(ctm);
358
431
  }
@@ -372,6 +445,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
372
445
  fill="${commonAttrs.stroke}"
373
446
  style="cursor: ${commonAttrs.cursor}; font-size: 16px;"
374
447
  @mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
448
+ @touchstart="${(e) => this.onShapeMouseDown(e, shape)}"
375
449
  @dblclick="${(e) => this.onTextDoubleClick(e, shape)}"
376
450
  >${shape.text}</text>
377
451
  `;
@@ -387,6 +461,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
387
461
  fill="${commonAttrs.fill}"
388
462
  style="cursor: ${commonAttrs.cursor}"
389
463
  @mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
464
+ @touchstart="${(e) => this.onShapeMouseDown(e, shape)}"
390
465
  ></rect>
391
466
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
392
467
  `;
@@ -401,6 +476,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
401
476
  fill="${commonAttrs.fill}"
402
477
  style="cursor: ${commonAttrs.cursor}"
403
478
  @mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
479
+ @touchstart="${(e) => this.onShapeMouseDown(e, shape)}"
404
480
  ></circle>
405
481
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
406
482
  `;
@@ -413,6 +489,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
413
489
  fill="${commonAttrs.fill}"
414
490
  style="cursor: ${commonAttrs.cursor}"
415
491
  @mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
492
+ @touchstart="${(e) => this.onShapeMouseDown(e, shape)}"
416
493
  ></polygon>
417
494
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
418
495
  `;
@@ -427,6 +504,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
427
504
  stroke-width="${commonAttrs['stroke-width']}"
428
505
  style="cursor: ${commonAttrs.cursor}"
429
506
  @mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
507
+ @touchstart="${(e) => this.onShapeMouseDown(e, shape)}"
430
508
  ></line>
431
509
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
432
510
  `;
@@ -447,6 +525,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
447
525
  marker-end="url(#arrowhead-${shape.id})"
448
526
  style="cursor: ${commonAttrs.cursor}"
449
527
  @mousedown="${(e) => this.onShapeMouseDown(e, shape)}"
528
+ @touchstart="${(e) => this.onShapeMouseDown(e, shape)}"
450
529
  ></line>
451
530
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
452
531
  `;
@@ -456,6 +535,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
456
535
  }
457
536
  onShapeMouseDown(event, shape) {
458
537
  event.stopPropagation();
538
+ event.preventDefault();
459
539
  this.shapes = this.shapes.map(s => ({
460
540
  ...s,
461
541
  selected: s.id === shape.id
@@ -482,16 +562,14 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
482
562
  break;
483
563
  }
484
564
  const svg = this.svg;
485
- svg.addEventListener('mousemove', this.onShapeMouseMove);
486
- svg.addEventListener('mouseup', this.onShapeMouseUp);
487
- }
488
- getScale() {
489
- if (!this.svg)
490
- return 1;
491
- const [vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
492
- const scaleX = vbWidth / this.svg.clientWidth;
493
- const scaleY = vbHeight / this.svg.clientHeight;
494
- return Math.max(scaleX, scaleY);
565
+ if ('touches' in event) {
566
+ svg.addEventListener('touchmove', this.onShapeMouseMove);
567
+ svg.addEventListener('touchend', this.onShapeMouseUp);
568
+ }
569
+ else {
570
+ svg.addEventListener('mousemove', this.onShapeMouseMove);
571
+ svg.addEventListener('mouseup', this.onShapeMouseUp);
572
+ }
495
573
  }
496
574
  renderResizeHandles(shape) {
497
575
  let handles = [];
@@ -541,6 +619,7 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
541
619
  class="resize-handle"
542
620
  style="cursor: ${handle.cursor};"
543
621
  @mousedown="${(e) => this.onHandleMouseDown(e, shape, handle)}"
622
+ @touchstart="${(e) => this.onHandleMouseDown(e, shape, handle)}"
544
623
  ></rect>
545
624
  </g>
546
625
  `)}
@@ -548,15 +627,23 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
548
627
  }
549
628
  onHandleMouseDown(event, shape, handle) {
550
629
  event.stopPropagation();
630
+ event.preventDefault();
551
631
  this.selectedShape = shape;
552
632
  this.offsetX = handle.x;
553
633
  this.offsetY = handle.y;
554
634
  const svg = this.svg;
555
- svg.addEventListener('mousemove', this.onHandleMouseMove);
556
- svg.addEventListener('mouseup', this.onHandleMouseUp);
635
+ if ('touches' in event) {
636
+ svg.addEventListener('touchmove', this.onHandleMouseMove);
637
+ svg.addEventListener('touchend', this.onHandleMouseUp);
638
+ }
639
+ else {
640
+ svg.addEventListener('mousemove', this.onHandleMouseMove);
641
+ svg.addEventListener('mouseup', this.onHandleMouseUp);
642
+ }
557
643
  }
558
644
  onTextDoubleClick(event, shape) {
559
645
  event.stopPropagation();
646
+ event.preventDefault();
560
647
  const textElement = event.target;
561
648
  this.showTextInput(textElement, shape);
562
649
  }
@@ -660,6 +747,13 @@ let OxImageMarker = class OxImageMarker extends BaseImageMarker {
660
747
  context.font = window.getComputedStyle(input).font;
661
748
  return context.measureText(text).width;
662
749
  }
750
+ deleteSelectedShape() {
751
+ if (this.selectedShape) {
752
+ this.shapes = this.shapes.filter(s => s.id !== this.selectedShape.id);
753
+ this.selectedShape = null;
754
+ this.requestUpdate();
755
+ }
756
+ }
663
757
  };
664
758
  __decorate([
665
759
  state()