@operato/image-marker 8.0.0-alpha.33 → 8.0.0-alpha.38
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 +19 -0
- package/dist/src/base-image-marker.d.ts +21 -26
- package/dist/src/base-image-marker.js +119 -138
- 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/index.d.ts +5 -0
- package/dist/src/index.js +5 -1
- package/dist/src/index.js.map +1 -1
- 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 +13 -1
- 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 +42 -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 +136 -159
- package/src/default-image-provider.ts +7 -0
- package/src/index.ts +6 -0
- package/src/ox-image-marker-view.ts +4 -4
- package/src/ox-image-marker.ts +187 -235
- package/src/types.ts +15 -1
- package/stories/test-image-provider.stories.ts +135 -0
- package/stories/test-image-provider.ts +51 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
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.38](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.37...v8.0.0-alpha.38) (2024-10-20)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* support scaled images for ox-image-marker ([b908134](https://github.com/hatiolab/operato/commit/b908134c05bb33786bc4632ac3e9a980aa9a78a7))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [8.0.0-alpha.37](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.36...v8.0.0-alpha.37) (2024-10-20)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### :bug: Bug Fix
|
|
19
|
+
|
|
20
|
+
* pointer-event & pointer-event for ox-image-marker ([c503d0a](https://github.com/hatiolab/operato/commit/c503d0a235ddadd97fdcd84ae98a303a7ffe7a6f))
|
|
21
|
+
* update dev-dependencies version ([d6fe342](https://github.com/hatiolab/operato/commit/d6fe342de738c6bad3528550a862b5a1d2573161))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
## [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
26
|
|
|
8
27
|
**Note:** Version bump only for package @operato/image-marker
|
|
@@ -1,41 +1,36 @@
|
|
|
1
|
-
import { LitElement, nothing } from 'lit';
|
|
2
|
-
import {
|
|
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
|
|
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
|
+
protected image: SVGImageElement;
|
|
18
|
+
private gestureHelper;
|
|
19
|
+
connectedCallback(): void;
|
|
20
|
+
disconnectedCallback(): void;
|
|
21
|
+
protected updated(changes: PropertyValues): void;
|
|
22
|
+
setImageProvider(provider: ImageProvider): void;
|
|
23
23
|
protected onImageLoad(event: Event): void;
|
|
24
|
+
protected updateImage(): Promise<void>;
|
|
24
25
|
protected onSvgWheel(event: WheelEvent): void;
|
|
25
|
-
protected
|
|
26
|
-
protected
|
|
27
|
-
protected
|
|
28
|
-
|
|
29
|
-
protected
|
|
30
|
-
protected
|
|
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;
|
|
26
|
+
protected onSvgPinch(e: GestureEventPinch): void;
|
|
27
|
+
protected onSvgDoubleTap(e: GestureEventDoubleTap): void;
|
|
28
|
+
protected onSvgDrag(e: GestureEventDrag): void;
|
|
29
|
+
zoom(scale: number, offsetX: number, offsetY: number): void;
|
|
30
|
+
protected reset(): void;
|
|
31
|
+
protected handleLinkClick(shape: Shape): void;
|
|
37
32
|
protected renderShape(shape: Shape): import("lit-html").TemplateResult<2> | typeof nothing;
|
|
38
|
-
protected getPointFromEvent(event: MouseEvent |
|
|
33
|
+
protected getPointFromEvent(event: MouseEvent | PointerEvent | GestureEventDrag): {
|
|
39
34
|
x: number;
|
|
40
35
|
y: number;
|
|
41
36
|
};
|
|
@@ -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.
|
|
14
|
-
this.
|
|
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,102 @@ export class BaseImageMarker extends LitElement {
|
|
|
108
36
|
cursor: pointer;
|
|
109
37
|
width: 100%;
|
|
110
38
|
height: 100%;
|
|
39
|
+
touch-action: none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.link:hover {
|
|
43
|
+
cursor: pointer;
|
|
111
44
|
}
|
|
112
45
|
`
|
|
113
46
|
]; }
|
|
47
|
+
connectedCallback() {
|
|
48
|
+
super.connectedCallback();
|
|
49
|
+
requestAnimationFrame(() => {
|
|
50
|
+
this.gestureHelper = new GestureHelper(this.svg);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
disconnectedCallback() {
|
|
54
|
+
super.disconnectedCallback();
|
|
55
|
+
this.gestureHelper?.dispose();
|
|
56
|
+
this.gestureHelper = null;
|
|
57
|
+
}
|
|
58
|
+
updated(changes) {
|
|
59
|
+
if (changes.has('imageUrl') || changes.has('imageProvider')) {
|
|
60
|
+
this.initialViewBox = null;
|
|
61
|
+
this.updateImage();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
setImageProvider(provider) {
|
|
65
|
+
this.imageProvider = provider;
|
|
66
|
+
}
|
|
114
67
|
onImageLoad(event) {
|
|
68
|
+
const element = event.target;
|
|
115
69
|
const img = new Image();
|
|
116
70
|
img.onload = () => {
|
|
117
71
|
const width = img.naturalWidth;
|
|
118
72
|
const height = img.naturalHeight;
|
|
119
|
-
this.
|
|
120
|
-
|
|
73
|
+
if (!this.initialViewBox) {
|
|
74
|
+
this.initialViewBox = `0 0 ${width} ${height}`;
|
|
75
|
+
this.viewBox = this.initialViewBox;
|
|
76
|
+
element.setAttribute('width', width.toString());
|
|
77
|
+
element.setAttribute('height', height.toString());
|
|
78
|
+
element.setAttribute('preserveAspectRatio', 'xMidYMid meet');
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const [initialX, initialY, initialWidth, initialHeight] = this.initialViewBox.split(' ').map(Number);
|
|
82
|
+
const scale = initialWidth / width;
|
|
83
|
+
element.setAttribute('width', (width * scale).toString());
|
|
84
|
+
element.setAttribute('height', (height * scale).toString());
|
|
85
|
+
}
|
|
121
86
|
};
|
|
122
|
-
img.src = this.
|
|
87
|
+
img.src = this.currentImage;
|
|
88
|
+
}
|
|
89
|
+
async updateImage() {
|
|
90
|
+
if (!this.imageProvider) {
|
|
91
|
+
throw new Error('ImageProvider is not set');
|
|
92
|
+
}
|
|
93
|
+
if (!this.imageUrl) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const options = {
|
|
97
|
+
id: this.imageUrl, // 이미지 ID는 imageUrl 속성을 사용
|
|
98
|
+
scale: this.zoomLevel, // scale은 zoomLevel 속성을 사용
|
|
99
|
+
offsetX: 0, // offsetX는 0으로 설정
|
|
100
|
+
offsetY: 0, // offsetY는 0으로 설정
|
|
101
|
+
currentImage: this.currentImage // 기존 이미지 객체 전달
|
|
102
|
+
};
|
|
103
|
+
this.currentImage = await this.imageProvider.getImage(options);
|
|
123
104
|
}
|
|
124
105
|
onSvgWheel(event) {
|
|
125
106
|
event.preventDefault();
|
|
126
107
|
const { offsetX, offsetY, deltaY } = event;
|
|
127
108
|
const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor;
|
|
128
|
-
|
|
109
|
+
this.zoom(scale, offsetX, offsetY);
|
|
110
|
+
}
|
|
111
|
+
onSvgPinch(e) {
|
|
112
|
+
e.stopPropagation();
|
|
113
|
+
const { scale, centerX, centerY } = e.detail;
|
|
114
|
+
console.log('pinch', e.detail);
|
|
115
|
+
this.zoom(scale, centerX, centerY);
|
|
116
|
+
}
|
|
117
|
+
onSvgDoubleTap(e) {
|
|
118
|
+
e.stopPropagation();
|
|
119
|
+
this.reset();
|
|
120
|
+
}
|
|
121
|
+
onSvgDrag(e) {
|
|
122
|
+
const { deltaX, deltaY } = e.detail;
|
|
123
|
+
console.log('drag', e.detail);
|
|
124
|
+
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
125
|
+
const scaleX = vbWidth / this.svg.clientWidth;
|
|
126
|
+
const scaleY = vbHeight / this.svg.clientHeight;
|
|
127
|
+
const scale = Math.max(scaleX, scaleY);
|
|
128
|
+
const newVbX = vbX - deltaX * scale;
|
|
129
|
+
const newVbY = vbY - deltaY * scale;
|
|
130
|
+
this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`;
|
|
131
|
+
this.debouncedUpdateImage();
|
|
132
|
+
}
|
|
133
|
+
zoom(scale, offsetX, offsetY) {
|
|
134
|
+
if (Math.abs(scale) > this.zoomThreshold) {
|
|
129
135
|
this.zoomLevel *= scale;
|
|
130
136
|
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
131
137
|
const mouseX = vbX + (offsetX / this.svg.clientWidth) * vbWidth;
|
|
@@ -135,61 +141,20 @@ export class BaseImageMarker extends LitElement {
|
|
|
135
141
|
const newVbX = mouseX - (offsetX / this.svg.clientWidth) * newVbWidth;
|
|
136
142
|
const newVbY = mouseY - (offsetY / this.svg.clientHeight) * newVbHeight;
|
|
137
143
|
this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`;
|
|
144
|
+
this.debouncedUpdateImage();
|
|
138
145
|
}
|
|
139
146
|
}
|
|
140
|
-
|
|
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() {
|
|
147
|
+
reset() {
|
|
176
148
|
this.viewBox = this.initialViewBox;
|
|
177
149
|
this.zoomLevel = 1;
|
|
150
|
+
this.debouncedUpdateImage();
|
|
178
151
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
}
|
|
152
|
+
handleLinkClick(shape) {
|
|
153
|
+
this.dispatchEvent(new CustomEvent('link-clicked', {
|
|
154
|
+
detail: { shapeId: shape.id, link: shape.link },
|
|
155
|
+
bubbles: true,
|
|
156
|
+
composed: true
|
|
157
|
+
}));
|
|
193
158
|
}
|
|
194
159
|
renderShape(shape) {
|
|
195
160
|
const commonAttrs = {
|
|
@@ -214,21 +179,28 @@ export class BaseImageMarker extends LitElement {
|
|
|
214
179
|
</marker>
|
|
215
180
|
</defs>
|
|
216
181
|
<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>`;
|
|
182
|
+
case 'link':
|
|
183
|
+
return svg `
|
|
184
|
+
<rect class="link" x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}"
|
|
185
|
+
stroke="${commonAttrs.stroke}" stroke-width="${commonAttrs['stroke-width']}"
|
|
186
|
+
fill="${commonAttrs.fill}" fill-opacity="0.5" @click="${() => this.handleLinkClick(shape)}">
|
|
187
|
+
</rect>`;
|
|
217
188
|
default:
|
|
218
189
|
return nothing;
|
|
219
190
|
}
|
|
220
191
|
}
|
|
221
192
|
getPointFromEvent(event) {
|
|
222
|
-
if ('
|
|
193
|
+
if ('clientX' in event) {
|
|
223
194
|
return {
|
|
224
|
-
x: event.
|
|
225
|
-
y: event.
|
|
195
|
+
x: event.clientX,
|
|
196
|
+
y: event.clientY
|
|
226
197
|
};
|
|
227
198
|
}
|
|
228
199
|
else {
|
|
200
|
+
const { clientX, clientY } = event.detail;
|
|
229
201
|
return {
|
|
230
|
-
x:
|
|
231
|
-
y:
|
|
202
|
+
x: clientX,
|
|
203
|
+
y: clientY
|
|
232
204
|
};
|
|
233
205
|
}
|
|
234
206
|
}
|
|
@@ -239,13 +211,22 @@ __decorate([
|
|
|
239
211
|
__decorate([
|
|
240
212
|
property({ type: Array })
|
|
241
213
|
], BaseImageMarker.prototype, "shapes", void 0);
|
|
214
|
+
__decorate([
|
|
215
|
+
state()
|
|
216
|
+
], BaseImageMarker.prototype, "currentImage", void 0);
|
|
242
217
|
__decorate([
|
|
243
218
|
state()
|
|
244
219
|
], BaseImageMarker.prototype, "viewBox", void 0);
|
|
245
220
|
__decorate([
|
|
246
221
|
state()
|
|
247
222
|
], BaseImageMarker.prototype, "zoomLevel", void 0);
|
|
223
|
+
__decorate([
|
|
224
|
+
state()
|
|
225
|
+
], BaseImageMarker.prototype, "imageProvider", void 0);
|
|
248
226
|
__decorate([
|
|
249
227
|
query('svg')
|
|
250
228
|
], BaseImageMarker.prototype, "svg", void 0);
|
|
229
|
+
__decorate([
|
|
230
|
+
query('image')
|
|
231
|
+
], BaseImageMarker.prototype, "image", void 0);
|
|
251
232
|
//# sourceMappingURL=base-image-marker.js.map
|
|
@@ -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":"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","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 .link:hover {\n cursor: pointer;\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 @query('image') protected image!: SVGImageElement\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 element = event.target as SVGImageElement\n const img = new Image()\n\n img.onload = () => {\n const width = img.naturalWidth\n const height = img.naturalHeight\n\n if (!this.initialViewBox) {\n this.initialViewBox = `0 0 ${width} ${height}`\n this.viewBox = this.initialViewBox\n\n element.setAttribute('width', width.toString())\n element.setAttribute('height', height.toString())\n element.setAttribute('preserveAspectRatio', 'xMidYMid meet')\n } else {\n const [initialX, initialY, initialWidth, initialHeight] = this.initialViewBox.split(' ').map(Number)\n const scale = initialWidth / width\n\n element.setAttribute('width', (width * scale).toString())\n element.setAttribute('height', (height * scale).toString())\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 if (!this.imageUrl) {\n return\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 handleLinkClick(shape: Shape) {\n this.dispatchEvent(\n new CustomEvent('link-clicked', {\n detail: { shapeId: shape.id, link: shape.link },\n bubbles: true,\n composed: true\n })\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 case 'link':\n return svg`\n <rect class=\"link\" x=\"${shape.x}\" y=\"${shape.y}\" width=\"${shape.width}\" height=\"${shape.height}\" \n stroke=\"${commonAttrs.stroke}\" stroke-width=\"${commonAttrs['stroke-width']}\" \n fill=\"${commonAttrs.fill}\" fill-opacity=\"0.5\" @click=\"${() => this.handleLinkClick(shape)}\">\n </rect>`\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 @@
|
|
|
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"]}
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"","sourcesContent":[""]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,wBAAwB,CAAA;AAEtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA","sourcesContent":["export * from './types.js'\nexport * from './base-image-marker.js'\n\nexport * from './ox-image-marker.js'\nexport * from './ox-image-marker-view.js'\nexport * from './ox-image-marker-mode.js'\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
|
-
@
|
|
12
|
-
@
|
|
13
|
-
@
|
|
11
|
+
@doubletap=${this.onSvgDoubleTap}
|
|
12
|
+
@pinch=${this.onSvgPinch}
|
|
13
|
+
@drag=${this.onSvgDrag}
|
|
14
14
|
viewBox=${this.viewBox}
|
|
15
15
|
>
|
|
16
|
-
<image href=${this.
|
|
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;
|
|
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
|
-
|
|
27
|
-
|
|
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
|
|
32
|
-
private
|
|
33
|
-
private
|
|
31
|
+
private onPointerDownOnShape;
|
|
32
|
+
private onPointerMoveOnShape;
|
|
33
|
+
private onPointerUpOnShape;
|
|
34
34
|
private renderResizeHandles;
|
|
35
|
-
private
|
|
36
|
-
private
|
|
37
|
-
private
|
|
35
|
+
private onResizeHandlePointerDown;
|
|
36
|
+
private onResizeHandlePointerMove;
|
|
37
|
+
private onResizeHandlePointerUp;
|
|
38
38
|
private onTextDoubleClick;
|
|
39
39
|
private showTextInput;
|
|
40
40
|
private adjustInputWidth;
|