@operato/image-marker 8.0.0-alpha.33 → 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 CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [8.0.0-alpha.37](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.36...v8.0.0-alpha.37) (2024-10-20)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * pointer-event & pointer-event for ox-image-marker ([c503d0a](https://github.com/hatiolab/operato/commit/c503d0a235ddadd97fdcd84ae98a303a7ffe7a6f))
12
+ * update dev-dependencies version ([d6fe342](https://github.com/hatiolab/operato/commit/d6fe342de738c6bad3528550a862b5a1d2573161))
13
+
14
+
15
+
6
16
  ## [8.0.0-alpha.33](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.32...v8.0.0-alpha.33) (2024-10-14)
7
17
 
8
18
  **Note:** Version bump only for package @operato/image-marker
@@ -1,41 +1,34 @@
1
- import { LitElement, nothing } from 'lit';
2
- import { Shape } from './types';
1
+ import { LitElement, nothing, PropertyValues } from 'lit';
2
+ import { GestureEventDoubleTap, GestureEventDrag, GestureEventPinch } from '@operato/utils/gesture-helper.js';
3
+ import { ImageProvider, Shape } from './types';
3
4
  export declare class BaseImageMarker extends LitElement {
4
5
  static styles: import("lit").CSSResult[];
5
6
  imageUrl: string;
6
7
  shapes: Shape[];
8
+ protected currentImage?: string;
7
9
  protected viewBox: string;
8
10
  protected zoomLevel: number;
11
+ private imageProvider?;
12
+ protected debouncedUpdateImage: import("lodash").DebouncedFunc<() => Promise<void>>;
9
13
  protected zoomFactor: number;
10
14
  protected zoomThreshold: number;
11
- protected isPanning: boolean;
12
- protected panStart: {
13
- x: number;
14
- y: number;
15
- };
16
- protected panInitiated: boolean;
17
- protected panThreshold: number;
18
- protected initialViewBox: string;
19
- private initialPinchDistance;
20
- private initialZoomLevel;
21
- private lastTouchEnd;
15
+ protected initialViewBox: string | null;
22
16
  protected svg: SVGSVGElement;
17
+ private gestureHelper;
18
+ connectedCallback(): void;
19
+ disconnectedCallback(): void;
20
+ protected updated(changes: PropertyValues): void;
21
+ setImageProvider(provider: ImageProvider): void;
23
22
  protected onImageLoad(event: Event): void;
23
+ protected updateImage(): Promise<void>;
24
24
  protected onSvgWheel(event: WheelEvent): void;
25
- protected onSvgMouseDown(event: MouseEvent): void;
26
- protected isDoubleTouch(event: TouchEvent): boolean;
27
- protected onSvgTouchStart: (event: TouchEvent) => void;
28
- protected startPinchZooming(event: TouchEvent): void;
29
- protected onZoomTouchMove: (event: TouchEvent) => void;
30
- protected onZoomTouchEnd: (event: TouchEvent) => void;
31
- protected applyZoom(): void;
32
- protected onSvgDoubleClick(): void;
33
- protected resetZoom(): void;
34
- protected startPanning(event: MouseEvent | TouchEvent): void;
35
- protected onPanMouseMove: (event: MouseEvent | TouchEvent) => void;
36
- protected onPanMouseUp: (event: MouseEvent | TouchEvent) => void;
25
+ protected onSvgPinch(e: GestureEventPinch): void;
26
+ protected onSvgDoubleTap(e: GestureEventDoubleTap): void;
27
+ protected onSvgDrag(e: GestureEventDrag): void;
28
+ zoom(scale: number, offsetX: number, offsetY: number): void;
29
+ protected reset(): void;
37
30
  protected renderShape(shape: Shape): import("lit-html").TemplateResult<2> | typeof nothing;
38
- protected getPointFromEvent(event: MouseEvent | TouchEvent): {
31
+ protected getPointFromEvent(event: MouseEvent | PointerEvent | GestureEventDrag): {
39
32
  x: number;
40
33
  y: number;
41
34
  };
@@ -1,6 +1,9 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { LitElement, css, svg, nothing } from 'lit';
3
3
  import { property, state, query } from 'lit/decorators.js';
4
+ import { debounce } from 'lodash-es';
5
+ import { GestureHelper } from '@operato/utils/gesture-helper.js';
6
+ import { DefaultImageProvider } from './default-image-provider';
4
7
  export class BaseImageMarker extends LitElement {
5
8
  constructor() {
6
9
  super(...arguments);
@@ -8,87 +11,12 @@ export class BaseImageMarker extends LitElement {
8
11
  this.shapes = [];
9
12
  this.viewBox = '0 0 800 600';
10
13
  this.zoomLevel = 1;
14
+ this.imageProvider = new DefaultImageProvider();
15
+ this.debouncedUpdateImage = debounce(this.updateImage.bind(this), 300);
11
16
  this.zoomFactor = 0.1;
12
17
  this.zoomThreshold = 0.05;
13
- this.isPanning = false;
14
- this.panStart = { x: 0, y: 0 };
15
- this.panInitiated = false;
16
- this.panThreshold = 20;
17
- this.initialViewBox = '0 0 800 600';
18
- this.initialPinchDistance = null;
19
- this.initialZoomLevel = 1;
20
- this.lastTouchEnd = 0;
21
- this.onSvgTouchStart = (event) => {
22
- event.preventDefault();
23
- if (this.isDoubleTouch(event)) {
24
- this.resetZoom();
25
- }
26
- if (event.touches.length === 1) {
27
- this.startPanning(event);
28
- }
29
- else if (event.touches.length === 2) {
30
- this.startPinchZooming(event);
31
- }
32
- };
33
- this.onZoomTouchMove = (event) => {
34
- event.preventDefault();
35
- if (event.touches.length === 2 && this.initialPinchDistance) {
36
- const touch1 = event.touches[0];
37
- const touch2 = event.touches[1];
38
- const dx = touch2.clientX - touch1.clientX;
39
- const dy = touch2.clientY - touch1.clientY;
40
- const currentPinchDistance = Math.sqrt(dx * dx + dy * dy);
41
- const scaleFactor = currentPinchDistance / this.initialPinchDistance;
42
- // 줌 threshold 확인 후 줌 적용
43
- if (Math.abs(scaleFactor - 1) > this.zoomThreshold) {
44
- this.zoomLevel = this.initialZoomLevel * scaleFactor;
45
- this.applyZoom();
46
- }
47
- }
48
- };
49
- this.onZoomTouchEnd = (event) => {
50
- event.preventDefault();
51
- if (event.touches.length < 2) {
52
- this.initialPinchDistance = null;
53
- }
54
- this.svg.removeEventListener('touchmove', this.onZoomTouchMove);
55
- this.svg.removeEventListener('touchend', this.onZoomTouchEnd);
56
- };
57
- this.onPanMouseMove = (event) => {
58
- if (!this.isPanning) {
59
- return;
60
- }
61
- event.preventDefault();
62
- const { x, y } = this.getPointFromEvent(event);
63
- const dx = x - this.panStart.x;
64
- const dy = y - this.panStart.y;
65
- if (!this.panInitiated && Math.sqrt(dx * dx + dy * dy) < this.panThreshold) {
66
- return;
67
- }
68
- this.panInitiated = true;
69
- const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
70
- const scaleX = vbWidth / this.svg.clientWidth;
71
- const scaleY = vbHeight / this.svg.clientHeight;
72
- const scale = Math.max(scaleX, scaleY);
73
- const newVbX = vbX - dx * scale;
74
- const newVbY = vbY - dy * scale;
75
- this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`;
76
- this.panStart = { x, y };
77
- };
78
- this.onPanMouseUp = (event) => {
79
- event.preventDefault();
80
- const svg = this.svg;
81
- this.isPanning = false;
82
- svg.classList.remove('dragging');
83
- if ('touches' in event) {
84
- svg.removeEventListener('touchmove', this.onPanMouseMove);
85
- svg.removeEventListener('touchend', this.onPanMouseUp);
86
- }
87
- else {
88
- svg.removeEventListener('mousemove', this.onPanMouseMove);
89
- svg.removeEventListener('mouseup', this.onPanMouseUp);
90
- }
91
- };
18
+ this.initialViewBox = null;
19
+ this.gestureHelper = null;
92
20
  }
93
21
  static { this.styles = [
94
22
  css `
@@ -108,24 +36,89 @@ export class BaseImageMarker extends LitElement {
108
36
  cursor: pointer;
109
37
  width: 100%;
110
38
  height: 100%;
39
+ touch-action: none;
111
40
  }
112
41
  `
113
42
  ]; }
43
+ connectedCallback() {
44
+ super.connectedCallback();
45
+ requestAnimationFrame(() => {
46
+ this.gestureHelper = new GestureHelper(this.svg);
47
+ });
48
+ }
49
+ disconnectedCallback() {
50
+ super.disconnectedCallback();
51
+ this.gestureHelper?.dispose();
52
+ this.gestureHelper = null;
53
+ }
54
+ updated(changes) {
55
+ if (changes.has('imageUrl') || changes.has('imageProvider')) {
56
+ this.initialViewBox = null;
57
+ this.updateImage();
58
+ }
59
+ }
60
+ setImageProvider(provider) {
61
+ this.imageProvider = provider;
62
+ }
114
63
  onImageLoad(event) {
115
64
  const img = new Image();
116
65
  img.onload = () => {
117
- const width = img.naturalWidth;
118
- const height = img.naturalHeight;
119
- this.viewBox = `0 0 ${width} ${height}`;
120
- this.initialViewBox = `0 0 ${width} ${height}`;
66
+ const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
67
+ if (!this.initialViewBox) {
68
+ const width = img.naturalWidth;
69
+ const height = img.naturalHeight;
70
+ this.initialViewBox = `0 0 ${width} ${height}`;
71
+ this.viewBox = this.initialViewBox;
72
+ }
73
+ else {
74
+ this.viewBox = `${vbX} ${vbY} ${vbWidth} ${vbHeight}`;
75
+ }
76
+ };
77
+ img.src = this.currentImage;
78
+ }
79
+ async updateImage() {
80
+ if (!this.imageProvider) {
81
+ throw new Error('ImageProvider is not set');
82
+ }
83
+ const options = {
84
+ id: this.imageUrl, // 이미지 ID는 imageUrl 속성을 사용
85
+ scale: this.zoomLevel, // scale은 zoomLevel 속성을 사용
86
+ offsetX: 0, // offsetX는 0으로 설정
87
+ offsetY: 0, // offsetY는 0으로 설정
88
+ currentImage: this.currentImage // 기존 이미지 객체 전달
121
89
  };
122
- img.src = this.imageUrl;
90
+ this.currentImage = await this.imageProvider.getImage(options);
123
91
  }
124
92
  onSvgWheel(event) {
125
93
  event.preventDefault();
126
94
  const { offsetX, offsetY, deltaY } = event;
127
95
  const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor;
128
- if (Math.abs(scale - 1) > this.zoomThreshold) {
96
+ this.zoom(scale, offsetX, offsetY);
97
+ }
98
+ onSvgPinch(e) {
99
+ e.stopPropagation();
100
+ const { scale, centerX, centerY } = e.detail;
101
+ console.log('pinch', e.detail);
102
+ this.zoom(scale, centerX, centerY);
103
+ }
104
+ onSvgDoubleTap(e) {
105
+ e.stopPropagation();
106
+ this.reset();
107
+ }
108
+ onSvgDrag(e) {
109
+ const { deltaX, deltaY } = e.detail;
110
+ console.log('drag', e.detail);
111
+ const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
112
+ const scaleX = vbWidth / this.svg.clientWidth;
113
+ const scaleY = vbHeight / this.svg.clientHeight;
114
+ const scale = Math.max(scaleX, scaleY);
115
+ const newVbX = vbX - deltaX * scale;
116
+ const newVbY = vbY - deltaY * scale;
117
+ this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`;
118
+ this.debouncedUpdateImage();
119
+ }
120
+ zoom(scale, offsetX, offsetY) {
121
+ if (Math.abs(scale) > this.zoomThreshold) {
129
122
  this.zoomLevel *= scale;
130
123
  const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
131
124
  const mouseX = vbX + (offsetX / this.svg.clientWidth) * vbWidth;
@@ -135,61 +128,13 @@ export class BaseImageMarker extends LitElement {
135
128
  const newVbX = mouseX - (offsetX / this.svg.clientWidth) * newVbWidth;
136
129
  const newVbY = mouseY - (offsetY / this.svg.clientHeight) * newVbHeight;
137
130
  this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`;
131
+ this.debouncedUpdateImage();
138
132
  }
139
133
  }
140
- onSvgMouseDown(event) {
141
- event.preventDefault();
142
- this.startPanning(event);
143
- this.svg.addEventListener('mousemove', this.onPanMouseMove);
144
- this.svg.addEventListener('mouseup', this.onPanMouseUp);
145
- }
146
- isDoubleTouch(event) {
147
- const currentTime = new Date().getTime();
148
- const tapLength = currentTime - this.lastTouchEnd;
149
- const result = tapLength < 300 && event.touches.length == 1;
150
- this.lastTouchEnd = currentTime;
151
- return result;
152
- }
153
- startPinchZooming(event) {
154
- const touch1 = event.touches[0];
155
- const touch2 = event.touches[1];
156
- const dx = touch2.clientX - touch1.clientX;
157
- const dy = touch2.clientY - touch1.clientY;
158
- this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy);
159
- this.initialZoomLevel = this.zoomLevel;
160
- this.svg.addEventListener('touchmove', this.onZoomTouchMove);
161
- this.svg.addEventListener('touchend', this.onZoomTouchEnd);
162
- }
163
- applyZoom() {
164
- const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
165
- const initialViewBoxNumbers = this.initialViewBox.split(' ').map(Number);
166
- const newVbWidth = initialViewBoxNumbers[2] / this.zoomLevel;
167
- const newVbHeight = initialViewBoxNumbers[3] / this.zoomLevel;
168
- const newVbX = vbX + (vbWidth - newVbWidth) / 2;
169
- const newVbY = vbY + (vbHeight - newVbHeight) / 2;
170
- this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`;
171
- }
172
- onSvgDoubleClick() {
173
- this.resetZoom();
174
- }
175
- resetZoom() {
134
+ reset() {
176
135
  this.viewBox = this.initialViewBox;
177
136
  this.zoomLevel = 1;
178
- }
179
- startPanning(event) {
180
- const { x, y } = this.getPointFromEvent(event);
181
- this.isPanning = true;
182
- this.panStart = { x, y };
183
- this.panInitiated = false; // 팬 동작이 아직 시작되지 않았음을 나타냄
184
- this.svg.classList.add('dragging');
185
- if ('touches' in event) {
186
- this.svg.addEventListener('touchmove', this.onPanMouseMove);
187
- this.svg.addEventListener('touchend', this.onPanMouseUp);
188
- }
189
- else {
190
- this.svg.addEventListener('mousemove', this.onPanMouseMove);
191
- this.svg.addEventListener('mouseup', this.onPanMouseUp);
192
- }
137
+ this.debouncedUpdateImage();
193
138
  }
194
139
  renderShape(shape) {
195
140
  const commonAttrs = {
@@ -219,16 +164,17 @@ export class BaseImageMarker extends LitElement {
219
164
  }
220
165
  }
221
166
  getPointFromEvent(event) {
222
- if ('touches' in event) {
167
+ if ('clientX' in event) {
223
168
  return {
224
- x: event.touches[0].clientX,
225
- y: event.touches[0].clientY
169
+ x: event.clientX,
170
+ y: event.clientY
226
171
  };
227
172
  }
228
173
  else {
174
+ const { clientX, clientY } = event.detail;
229
175
  return {
230
- x: event.clientX,
231
- y: event.clientY
176
+ x: clientX,
177
+ y: clientY
232
178
  };
233
179
  }
234
180
  }
@@ -239,12 +185,18 @@ __decorate([
239
185
  __decorate([
240
186
  property({ type: Array })
241
187
  ], BaseImageMarker.prototype, "shapes", void 0);
188
+ __decorate([
189
+ state()
190
+ ], BaseImageMarker.prototype, "currentImage", void 0);
242
191
  __decorate([
243
192
  state()
244
193
  ], BaseImageMarker.prototype, "viewBox", void 0);
245
194
  __decorate([
246
195
  state()
247
196
  ], BaseImageMarker.prototype, "zoomLevel", void 0);
197
+ __decorate([
198
+ state()
199
+ ], BaseImageMarker.prototype, "imageProvider", void 0);
248
200
  __decorate([
249
201
  query('svg')
250
202
  ], BaseImageMarker.prototype, "svg", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"base-image-marker.js","sourceRoot":"","sources":["../../src/base-image-marker.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, svg, nothing } from 'lit'\nimport { property, state, query } from 'lit/decorators.js'\n\nimport { Shape } from './types'\n\nexport class BaseImageMarker extends LitElement {\n static styles = [\n css`\n :host {\n display: flex;\n }\n\n .container {\n flex: 1;\n position: relative;\n }\n\n svg {\n position: absolute;\n top: 0;\n left: 0;\n cursor: pointer;\n width: 100%;\n height: 100%;\n }\n `\n ]\n\n @property({ type: String }) imageUrl: string = ''\n @property({ type: Array }) shapes: Shape[] = []\n\n @state() protected viewBox = '0 0 800 600'\n @state() protected zoomLevel = 1\n\n protected zoomFactor = 0.1\n protected zoomThreshold = 0.05\n protected isPanning = false\n protected panStart = { x: 0, y: 0 }\n protected panInitiated = false\n protected panThreshold = 20\n\n protected initialViewBox = '0 0 800 600'\n private initialPinchDistance: number | null = null\n private initialZoomLevel: number = 1\n private lastTouchEnd: number = 0\n\n @query('svg') protected svg!: SVGSVGElement\n\n protected onImageLoad(event: Event) {\n const img = new Image()\n img.onload = () => {\n const width = img.naturalWidth\n const height = img.naturalHeight\n this.viewBox = `0 0 ${width} ${height}`\n this.initialViewBox = `0 0 ${width} ${height}`\n }\n img.src = this.imageUrl\n }\n\n protected onSvgWheel(event: WheelEvent) {\n event.preventDefault()\n\n const { offsetX, offsetY, deltaY } = event\n const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor\n if (Math.abs(scale - 1) > this.zoomThreshold) {\n this.zoomLevel *= scale\n\n const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)\n const mouseX = vbX + (offsetX / this.svg.clientWidth) * vbWidth\n const mouseY = vbY + (offsetY / this.svg.clientHeight) * vbHeight\n\n const newVbWidth = vbWidth / scale\n const newVbHeight = vbHeight / scale\n\n const newVbX = mouseX - (offsetX / this.svg.clientWidth) * newVbWidth\n const newVbY = mouseY - (offsetY / this.svg.clientHeight) * newVbHeight\n\n this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`\n }\n }\n\n protected onSvgMouseDown(event: MouseEvent) {\n event.preventDefault()\n\n this.startPanning(event)\n\n this.svg.addEventListener('mousemove', this.onPanMouseMove)\n this.svg.addEventListener('mouseup', this.onPanMouseUp)\n }\n\n protected isDoubleTouch(event: TouchEvent) {\n const currentTime = new Date().getTime()\n const tapLength = currentTime - this.lastTouchEnd\n\n const result = tapLength < 300 && event.touches.length == 1\n this.lastTouchEnd = currentTime\n\n return result\n }\n\n protected onSvgTouchStart = (event: TouchEvent) => {\n event.preventDefault()\n\n if (this.isDoubleTouch(event)) {\n this.resetZoom()\n }\n\n if (event.touches.length === 1) {\n this.startPanning(event)\n } else if (event.touches.length === 2) {\n this.startPinchZooming(event)\n }\n }\n\n protected startPinchZooming(event: TouchEvent) {\n const touch1 = event.touches[0]\n const touch2 = event.touches[1]\n\n const dx = touch2.clientX - touch1.clientX\n const dy = touch2.clientY - touch1.clientY\n\n this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy)\n this.initialZoomLevel = this.zoomLevel\n\n this.svg.addEventListener('touchmove', this.onZoomTouchMove)\n this.svg.addEventListener('touchend', this.onZoomTouchEnd)\n }\n\n protected onZoomTouchMove = (event: TouchEvent) => {\n event.preventDefault()\n\n if (event.touches.length === 2 && this.initialPinchDistance) {\n const touch1 = event.touches[0]\n const touch2 = event.touches[1]\n const dx = touch2.clientX - touch1.clientX\n const dy = touch2.clientY - touch1.clientY\n const currentPinchDistance = Math.sqrt(dx * dx + dy * dy)\n\n const scaleFactor = currentPinchDistance / this.initialPinchDistance\n\n // 줌 threshold 확인 후 줌 적용\n if (Math.abs(scaleFactor - 1) > this.zoomThreshold) {\n this.zoomLevel = this.initialZoomLevel * scaleFactor\n this.applyZoom()\n }\n }\n }\n\n protected onZoomTouchEnd = (event: TouchEvent) => {\n event.preventDefault()\n\n if (event.touches.length < 2) {\n this.initialPinchDistance = null\n }\n\n this.svg.removeEventListener('touchmove', this.onZoomTouchMove)\n this.svg.removeEventListener('touchend', this.onZoomTouchEnd)\n }\n\n protected applyZoom() {\n const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)\n const initialViewBoxNumbers = this.initialViewBox.split(' ').map(Number)\n const newVbWidth = initialViewBoxNumbers[2] / this.zoomLevel\n const newVbHeight = initialViewBoxNumbers[3] / this.zoomLevel\n const newVbX = vbX + (vbWidth - newVbWidth) / 2\n const newVbY = vbY + (vbHeight - newVbHeight) / 2\n\n this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`\n }\n\n protected onSvgDoubleClick() {\n this.resetZoom()\n }\n\n protected resetZoom() {\n this.viewBox = this.initialViewBox\n this.zoomLevel = 1\n }\n\n protected startPanning(event: MouseEvent | TouchEvent) {\n const { x, y } = this.getPointFromEvent(event)\n\n this.isPanning = true\n this.panStart = { x, y }\n this.panInitiated = false // 팬 동작이 아직 시작되지 않았음을 나타냄\n this.svg.classList.add('dragging')\n\n if ('touches' in event) {\n this.svg.addEventListener('touchmove', this.onPanMouseMove)\n this.svg.addEventListener('touchend', this.onPanMouseUp)\n } else {\n this.svg.addEventListener('mousemove', this.onPanMouseMove)\n this.svg.addEventListener('mouseup', this.onPanMouseUp)\n }\n }\n\n protected onPanMouseMove = (event: MouseEvent | TouchEvent) => {\n if (!this.isPanning) {\n return\n }\n event.preventDefault()\n\n const { x, y } = this.getPointFromEvent(event)\n\n const dx = x - this.panStart.x\n const dy = y - this.panStart.y\n\n if (!this.panInitiated && Math.sqrt(dx * dx + dy * dy) < this.panThreshold) {\n return\n }\n\n this.panInitiated = true\n\n const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)\n const scaleX = vbWidth / this.svg.clientWidth\n const scaleY = vbHeight / this.svg.clientHeight\n const scale = Math.max(scaleX, scaleY)\n\n const newVbX = vbX - dx * scale\n const newVbY = vbY - dy * scale\n\n this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`\n this.panStart = { x, y }\n }\n\n protected onPanMouseUp = (event: MouseEvent | TouchEvent) => {\n event.preventDefault()\n\n const svg = this.svg\n\n this.isPanning = false\n svg.classList.remove('dragging')\n\n if ('touches' in event) {\n svg.removeEventListener('touchmove', this.onPanMouseMove)\n svg.removeEventListener('touchend', this.onPanMouseUp)\n } else {\n svg.removeEventListener('mousemove', this.onPanMouseMove)\n svg.removeEventListener('mouseup', this.onPanMouseUp)\n }\n }\n\n protected renderShape(shape: Shape) {\n const commonAttrs = {\n stroke: 'red',\n 'stroke-width': 1,\n fill: 'transparent'\n }\n\n switch (shape.type) {\n case 'text':\n return svg`<text x=\"${shape.x}\" y=\"${shape.y}\" text-anchor=\"middle\" alignment-baseline=\"middle\" fill=\"black\">${shape.text}</text>`\n case 'rectangle':\n return svg`<rect x=\"${shape.x}\" y=\"${shape.y}\" width=\"${shape.width}\" height=\"${shape.height}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" fill=\"${commonAttrs.fill}\"></rect>`\n case 'circle':\n return svg`<circle cx=\"${shape.cx}\" cy=\"${shape.cy}\" r=\"${shape.r}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" fill=\"${commonAttrs.fill}\"></circle>`\n case 'line':\n return svg`<line x1=\"${shape.x1}\" y1=\"${shape.y1}\" x2=\"${shape.x2}\" y2=\"${shape.y2}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\"></line>`\n case 'arrow':\n return svg`\n <defs>\n <marker id=\"arrowhead-${shape.id}\" markerWidth=\"10\" markerHeight=\"7\" refX=\"10\" refY=\"3.5\" orient=\"auto\">\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"${commonAttrs.stroke}\"></polygon>\n </marker>\n </defs>\n <line x1=\"${shape.x1}\" y1=\"${shape.y1}\" x2=\"${shape.x2}\" y2=\"${shape.y2}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" marker-end=\"url(#arrowhead-${shape.id})\"></line>`\n default:\n return nothing\n }\n }\n\n protected getPointFromEvent(event: MouseEvent | TouchEvent) {\n if ('touches' in event) {\n return {\n x: event.touches[0].clientX,\n y: event.touches[0].clientY\n }\n } else {\n return {\n x: event.clientX,\n y: event.clientY\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"base-image-marker.js","sourceRoot":"","sources":["../../src/base-image-marker.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAQ,GAAG,EAAE,OAAO,EAAkB,MAAM,KAAK,CAAA;AACzE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,EAIL,aAAa,EACd,MAAM,kCAAkC,CAAA;AAEzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAE/D,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAA/C;;QAwB8B,aAAQ,GAAW,EAAE,CAAA;QACtB,WAAM,GAAY,EAAE,CAAA;QAG5B,YAAO,GAAG,aAAa,CAAA;QACvB,cAAS,GAAG,CAAC,CAAA;QACf,kBAAa,GAAmB,IAAI,oBAAoB,EAAE,CAAA;QAEjE,yBAAoB,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACjE,eAAU,GAAG,GAAG,CAAA;QAChB,kBAAa,GAAG,IAAI,CAAA;QAEpB,mBAAc,GAAkB,IAAI,CAAA;QAItC,kBAAa,GAAyB,IAAI,CAAA;IAgLpD,CAAC;aAvNQ,WAAM,GAAG;QACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;KAmBF;KACF,AArBY,CAqBZ;IAoBD,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QACzB,qBAAqB,CAAC,GAAG,EAAE;YACzB,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;IAC3B,CAAC;IAES,OAAO,CAAC,OAAuB;QACvC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;YAC1B,IAAI,CAAC,WAAW,EAAE,CAAA;QACpB,CAAC;IACH,CAAC;IAEM,gBAAgB,CAAC,QAAuB;QAC7C,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAA;IAC/B,CAAC;IAES,WAAW,CAAC,KAAY;QAChC,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAA;QAEvB,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;YAChB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAEzE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAA;gBAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAA;gBAEhC,IAAI,CAAC,cAAc,GAAG,OAAO,KAAK,IAAI,MAAM,EAAE,CAAA;gBAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAA;YACpC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAA;YACvD,CAAC;QACH,CAAC,CAAA;QAED,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,YAAa,CAAA;IAC9B,CAAC;IAES,KAAK,CAAC,WAAW;QACzB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QAED,MAAM,OAAO,GAAG;YACd,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,0BAA0B;YAC7C,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,0BAA0B;YACjD,OAAO,EAAE,CAAC,EAAE,kBAAkB;YAC9B,OAAO,EAAE,CAAC,EAAE,kBAAkB;YAC9B,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,eAAe;SAChD,CAAA;QAED,IAAI,CAAC,YAAY,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAChE,CAAC;IAES,UAAU,CAAC,KAAiB;QACpC,KAAK,CAAC,cAAc,EAAE,CAAA;QAEtB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;QAC1C,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAA;QAEpE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACpC,CAAC;IAES,UAAU,CAAC,CAAoB;QACvC,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,CAAA;QAE5C,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;QAE9B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACpC,CAAC;IAES,cAAc,CAAC,CAAwB;QAC/C,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAES,SAAS,CAAC,CAAmB;QACrC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAAA;QACnC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;QAE7B,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAEzE,MAAM,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAA;QAC7C,MAAM,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAA;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAEtC,MAAM,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK,CAAA;QACnC,MAAM,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK,CAAA;QAEnC,IAAI,CAAC,OAAO,GAAG,GAAG,MAAM,IAAI,MAAM,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAA;QAE3D,IAAI,CAAC,oBAAoB,EAAE,CAAA;IAC7B,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,OAAe,EAAE,OAAe;QAClD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAA;YAEvB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACzE,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,OAAO,CAAA;YAC/D,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,QAAQ,CAAA;YAEjE,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,CAAA;YAClC,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,CAAA;YAEpC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,UAAU,CAAA;YACrE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,WAAW,CAAA;YAEvE,IAAI,CAAC,OAAO,GAAG,GAAG,MAAM,IAAI,MAAM,IAAI,UAAU,IAAI,WAAW,EAAE,CAAA;YAEjE,IAAI,CAAC,oBAAoB,EAAE,CAAA;QAC7B,CAAC;IACH,CAAC;IAES,KAAK;QACb,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,cAAe,CAAA;QACnC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;QAElB,IAAI,CAAC,oBAAoB,EAAE,CAAA;IAC7B,CAAC;IAES,WAAW,CAAC,KAAY;QAChC,MAAM,WAAW,GAAG;YAClB,MAAM,EAAE,KAAK;YACb,cAAc,EAAE,CAAC;YACjB,IAAI,EAAE,aAAa;SACpB,CAAA;QAED,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,MAAM;gBACT,OAAO,GAAG,CAAA,YAAY,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,mEAAmE,KAAK,CAAC,IAAI,SAAS,CAAA;YACpI,KAAK,WAAW;gBACd,OAAO,GAAG,CAAA,YAAY,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,KAAK,aAAa,KAAK,CAAC,MAAM,aAAa,WAAW,CAAC,MAAM,mBAAmB,WAAW,CAAC,cAAc,CAAC,WAAW,WAAW,CAAC,IAAI,WAAW,CAAA;YACjN,KAAK,QAAQ;gBACX,OAAO,GAAG,CAAA,eAAe,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,QAAQ,KAAK,CAAC,CAAC,aAAa,WAAW,CAAC,MAAM,mBAAmB,WAAW,CAAC,cAAc,CAAC,WAAW,WAAW,CAAC,IAAI,aAAa,CAAA;YACxL,KAAK,MAAM;gBACT,OAAO,GAAG,CAAA,aAAa,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,aAAa,WAAW,CAAC,MAAM,mBAAmB,WAAW,CAAC,cAAc,CAAC,WAAW,CAAA;YAC5K,KAAK,OAAO;gBACV,OAAO,GAAG,CAAA;;oCAEkB,KAAK,CAAC,EAAE;yDACa,WAAW,CAAC,MAAM;;;sBAGrD,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,EAAE,aAAa,WAAW,CAAC,MAAM,mBAAmB,WAAW,CAAC,cAAc,CAAC,gCAAgC,KAAK,CAAC,EAAE,YAAY,CAAA;YAC5M;gBACE,OAAO,OAAO,CAAA;QAClB,CAAC;IACH,CAAC;IAES,iBAAiB,CAAC,KAAmD;QAC7E,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;YACvB,OAAO;gBACL,CAAC,EAAE,KAAK,CAAC,OAAO;gBAChB,CAAC,EAAE,KAAK,CAAC,OAAO;aACjB,CAAA;QACH,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,CAAA;YACzC,OAAO;gBACL,CAAC,EAAE,OAAO;gBACV,CAAC,EAAE,OAAO;aACX,CAAA;QACH,CAAC;IACH,CAAC;;AA/L2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;iDAAsB;AACtB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;+CAAqB;AAE5B;IAAlB,KAAK,EAAE;qDAAgC;AACrB;IAAlB,KAAK,EAAE;gDAAkC;AACvB;IAAlB,KAAK,EAAE;kDAAwB;AACf;IAAhB,KAAK,EAAE;sDAAmE;AAQnD;IAAvB,KAAK,CAAC,KAAK,CAAC;4CAA8B","sourcesContent":["import { LitElement, css, html, svg, nothing, PropertyValues } from 'lit'\nimport { property, state, query } from 'lit/decorators.js'\nimport { debounce } from 'lodash-es'\n\nimport {\n GestureEventDoubleTap,\n GestureEventDrag,\n GestureEventPinch,\n GestureHelper\n} from '@operato/utils/gesture-helper.js'\nimport { ImageProvider, Shape } from './types'\nimport { DefaultImageProvider } from './default-image-provider'\n\nexport class BaseImageMarker extends LitElement {\n static styles = [\n css`\n :host {\n display: flex;\n }\n\n .container {\n flex: 1;\n position: relative;\n }\n\n svg {\n position: absolute;\n top: 0;\n left: 0;\n cursor: pointer;\n width: 100%;\n height: 100%;\n touch-action: none;\n }\n `\n ]\n\n @property({ type: String }) imageUrl: string = ''\n @property({ type: Array }) shapes: Shape[] = []\n\n @state() protected currentImage?: string\n @state() protected viewBox = '0 0 800 600'\n @state() protected zoomLevel = 1\n @state() private imageProvider?: ImageProvider = new DefaultImageProvider()\n\n protected debouncedUpdateImage = debounce(this.updateImage.bind(this), 300)\n protected zoomFactor = 0.1\n protected zoomThreshold = 0.05\n\n protected initialViewBox: string | null = null\n\n @query('svg') protected svg!: SVGSVGElement\n\n private gestureHelper: GestureHelper | null = null\n\n connectedCallback(): void {\n super.connectedCallback()\n requestAnimationFrame(() => {\n this.gestureHelper = new GestureHelper(this.svg)\n })\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback()\n\n this.gestureHelper?.dispose()\n this.gestureHelper = null\n }\n\n protected updated(changes: PropertyValues): void {\n if (changes.has('imageUrl') || changes.has('imageProvider')) {\n this.initialViewBox = null\n this.updateImage()\n }\n }\n\n public setImageProvider(provider: ImageProvider) {\n this.imageProvider = provider\n }\n\n protected onImageLoad(event: Event) {\n const img = new Image()\n\n img.onload = () => {\n const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)\n\n if (!this.initialViewBox) {\n const width = img.naturalWidth\n const height = img.naturalHeight\n\n this.initialViewBox = `0 0 ${width} ${height}`\n this.viewBox = this.initialViewBox\n } else {\n this.viewBox = `${vbX} ${vbY} ${vbWidth} ${vbHeight}`\n }\n }\n\n img.src = this.currentImage!\n }\n\n protected async updateImage() {\n if (!this.imageProvider) {\n throw new Error('ImageProvider is not set')\n }\n\n const options = {\n id: this.imageUrl, // 이미지 ID는 imageUrl 속성을 사용\n scale: this.zoomLevel, // scale은 zoomLevel 속성을 사용\n offsetX: 0, // offsetX는 0으로 설정\n offsetY: 0, // offsetY는 0으로 설정\n currentImage: this.currentImage // 기존 이미지 객체 전달\n }\n\n this.currentImage = await this.imageProvider.getImage(options)\n }\n\n protected onSvgWheel(event: WheelEvent) {\n event.preventDefault()\n\n const { offsetX, offsetY, deltaY } = event\n const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor\n\n this.zoom(scale, offsetX, offsetY)\n }\n\n protected onSvgPinch(e: GestureEventPinch) {\n e.stopPropagation()\n\n const { scale, centerX, centerY } = e.detail\n\n console.log('pinch', e.detail)\n\n this.zoom(scale, centerX, centerY)\n }\n\n protected onSvgDoubleTap(e: GestureEventDoubleTap) {\n e.stopPropagation()\n\n this.reset()\n }\n\n protected onSvgDrag(e: GestureEventDrag) {\n const { deltaX, deltaY } = e.detail\n console.log('drag', e.detail)\n\n const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)\n\n const scaleX = vbWidth / this.svg.clientWidth\n const scaleY = vbHeight / this.svg.clientHeight\n const scale = Math.max(scaleX, scaleY)\n\n const newVbX = vbX - deltaX * scale\n const newVbY = vbY - deltaY * scale\n\n this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`\n\n this.debouncedUpdateImage()\n }\n\n zoom(scale: number, offsetX: number, offsetY: number) {\n if (Math.abs(scale) > this.zoomThreshold) {\n this.zoomLevel *= scale\n\n const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)\n const mouseX = vbX + (offsetX / this.svg.clientWidth) * vbWidth\n const mouseY = vbY + (offsetY / this.svg.clientHeight) * vbHeight\n\n const newVbWidth = vbWidth / scale\n const newVbHeight = vbHeight / scale\n\n const newVbX = mouseX - (offsetX / this.svg.clientWidth) * newVbWidth\n const newVbY = mouseY - (offsetY / this.svg.clientHeight) * newVbHeight\n\n this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`\n\n this.debouncedUpdateImage()\n }\n }\n\n protected reset() {\n this.viewBox = this.initialViewBox!\n this.zoomLevel = 1\n\n this.debouncedUpdateImage()\n }\n\n protected renderShape(shape: Shape) {\n const commonAttrs = {\n stroke: 'red',\n 'stroke-width': 1,\n fill: 'transparent'\n }\n\n switch (shape.type) {\n case 'text':\n return svg`<text x=\"${shape.x}\" y=\"${shape.y}\" text-anchor=\"middle\" alignment-baseline=\"middle\" fill=\"black\">${shape.text}</text>`\n case 'rectangle':\n return svg`<rect x=\"${shape.x}\" y=\"${shape.y}\" width=\"${shape.width}\" height=\"${shape.height}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" fill=\"${commonAttrs.fill}\"></rect>`\n case 'circle':\n return svg`<circle cx=\"${shape.cx}\" cy=\"${shape.cy}\" r=\"${shape.r}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" fill=\"${commonAttrs.fill}\"></circle>`\n case 'line':\n return svg`<line x1=\"${shape.x1}\" y1=\"${shape.y1}\" x2=\"${shape.x2}\" y2=\"${shape.y2}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\"></line>`\n case 'arrow':\n return svg`\n <defs>\n <marker id=\"arrowhead-${shape.id}\" markerWidth=\"10\" markerHeight=\"7\" refX=\"10\" refY=\"3.5\" orient=\"auto\">\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"${commonAttrs.stroke}\"></polygon>\n </marker>\n </defs>\n <line x1=\"${shape.x1}\" y1=\"${shape.y1}\" x2=\"${shape.x2}\" y2=\"${shape.y2}\" stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" marker-end=\"url(#arrowhead-${shape.id})\"></line>`\n default:\n return nothing\n }\n }\n\n protected getPointFromEvent(event: MouseEvent | PointerEvent | GestureEventDrag) {\n if ('clientX' in event) {\n return {\n x: event.clientX,\n y: event.clientY\n }\n } else {\n const { clientX, clientY } = event.detail\n return {\n x: clientX,\n y: clientY\n }\n }\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { ImageOptions, ImageProvider } from './types';
2
+ export declare class DefaultImageProvider implements ImageProvider {
3
+ getImage(options: ImageOptions): Promise<string>;
4
+ }
@@ -0,0 +1,6 @@
1
+ export class DefaultImageProvider {
2
+ async getImage(options) {
3
+ return options.id;
4
+ }
5
+ }
6
+ //# sourceMappingURL=default-image-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-image-provider.js","sourceRoot":"","sources":["../../src/default-image-provider.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,oBAAoB;IAC/B,KAAK,CAAC,QAAQ,CAAC,OAAqB;QAClC,OAAO,OAAO,CAAC,EAAE,CAAA;IACnB,CAAC;CACF","sourcesContent":["import { ImageOptions, ImageProvider } from './types'\n\nexport class DefaultImageProvider implements ImageProvider {\n async getImage(options: ImageOptions): Promise<string> {\n return options.id\n }\n}\n"]}
@@ -8,12 +8,12 @@ let OxImageMarkerView = class OxImageMarkerView extends BaseImageMarker {
8
8
  <div class="container">
9
9
  <svg
10
10
  @wheel=${this.onSvgWheel}
11
- @mousedown=${this.onSvgMouseDown}
12
- @touchstart=${this.onSvgTouchStart}
13
- @dblclick=${this.onSvgDoubleClick}
11
+ @doubletap=${this.onSvgDoubleTap}
12
+ @pinch=${this.onSvgPinch}
13
+ @drag=${this.onSvgDrag}
14
14
  viewBox=${this.viewBox}
15
15
  >
16
- <image href=${this.imageUrl} @load=${this.onImageLoad}></image>
16
+ <image href=${this.currentImage} @load=${this.onImageLoad}></image>
17
17
  ${this.shapes.map(shape => this.renderShape(shape))}
18
18
  </svg>
19
19
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"ox-image-marker-view.js","sourceRoot":"","sources":["../../src/ox-image-marker-view.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAGjD,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,eAAe;IACpD,MAAM;QACJ,OAAO,IAAI,CAAA;;;mBAGI,IAAI,CAAC,UAAU;uBACX,IAAI,CAAC,cAAc;wBAClB,IAAI,CAAC,eAAe;sBACtB,IAAI,CAAC,gBAAgB;oBACvB,IAAI,CAAC,OAAO;;wBAER,IAAI,CAAC,QAAQ,UAAU,IAAI,CAAC,WAAW;YACnD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;;;KAGxD,CAAA;IACH,CAAC;CACF,CAAA;AAjBY,iBAAiB;IAD7B,aAAa,CAAC,sBAAsB,CAAC;GACzB,iBAAiB,CAiB7B","sourcesContent":["import { html } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\nimport { BaseImageMarker } from './base-image-marker.js'\n\n@customElement('ox-image-marker-view')\nexport class OxImageMarkerView extends BaseImageMarker {\n render() {\n return html`\n <div class=\"container\">\n <svg\n @wheel=${this.onSvgWheel}\n @mousedown=${this.onSvgMouseDown}\n @touchstart=${this.onSvgTouchStart}\n @dblclick=${this.onSvgDoubleClick}\n viewBox=${this.viewBox}\n >\n <image href=${this.imageUrl} @load=${this.onImageLoad}></image>\n ${this.shapes.map(shape => this.renderShape(shape))}\n </svg>\n </div>\n `\n }\n}\n"]}
1
+ {"version":3,"file":"ox-image-marker-view.js","sourceRoot":"","sources":["../../src/ox-image-marker-view.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAGjD,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,eAAe;IACpD,MAAM;QACJ,OAAO,IAAI,CAAA;;;mBAGI,IAAI,CAAC,UAAU;uBACX,IAAI,CAAC,cAAc;mBACvB,IAAI,CAAC,UAAU;kBAChB,IAAI,CAAC,SAAS;oBACZ,IAAI,CAAC,OAAO;;wBAER,IAAI,CAAC,YAAY,UAAU,IAAI,CAAC,WAAW;YACvD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;;;KAGxD,CAAA;IACH,CAAC;CACF,CAAA;AAjBY,iBAAiB;IAD7B,aAAa,CAAC,sBAAsB,CAAC;GACzB,iBAAiB,CAiB7B","sourcesContent":["import { html } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\nimport { BaseImageMarker } from './base-image-marker.js'\n\n@customElement('ox-image-marker-view')\nexport class OxImageMarkerView extends BaseImageMarker {\n render() {\n return html`\n <div class=\"container\">\n <svg\n @wheel=${this.onSvgWheel}\n @doubletap=${this.onSvgDoubleTap}\n @pinch=${this.onSvgPinch}\n @drag=${this.onSvgDrag}\n viewBox=${this.viewBox}\n >\n <image href=${this.currentImage} @load=${this.onImageLoad}></image>\n ${this.shapes.map(shape => this.renderShape(shape))}\n </svg>\n </div>\n `\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import './ox-image-marker-mode';
2
2
  import { nothing } from 'lit';
3
+ import { GestureEventDrag, GestureEventPinch } from '@operato/utils/gesture-helper.js';
3
4
  import { Shape } from './types';
4
5
  import { BaseImageMarker } from './base-image-marker';
5
6
  import { OxImageMarkerMode } from './ox-image-marker-mode';
@@ -19,22 +20,21 @@ export declare class OxImageMarker extends BaseImageMarker {
19
20
  connectedCallback(): void;
20
21
  disconnectedCallback(): void;
21
22
  render(): import("lit-html").TemplateResult<1>;
22
- protected onSvgMouseDown(event: MouseEvent): void;
23
- protected onSvgTouchStart: (event: TouchEvent) => void;
24
- private startDrawing;
25
23
  private setMode;
26
- private onMouseMoveForDrawing;
27
- private onMouseUpForDrawing;
24
+ protected onSvgPinch(e: GestureEventPinch): void;
25
+ protected onSvgDrag(e: GestureEventDrag): void;
26
+ protected onSvgClick(e: MouseEvent): void;
27
+ private drawShape;
28
28
  private setSelectedShape;
29
29
  private getSvgPoint;
30
30
  protected renderShape(shape: Shape): import("lit-html").TemplateResult<2> | typeof nothing;
31
- private onMouseDownOnShape;
32
- private onMouseMoveOnShape;
33
- private onMouseUpOnShape;
31
+ private onPointerDownOnShape;
32
+ private onPointerMoveOnShape;
33
+ private onPointerUpOnShape;
34
34
  private renderResizeHandles;
35
- private onResizeHandleMouseDown;
36
- private onResizeHandleMouseMove;
37
- private onResizeHandleMouseUp;
35
+ private onResizeHandlePointerDown;
36
+ private onResizeHandlePointerMove;
37
+ private onResizeHandlePointerUp;
38
38
  private onTextDoubleClick;
39
39
  private showTextInput;
40
40
  private adjustInputWidth;