@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.
- package/CHANGELOG.md +18 -0
- package/dist/src/base-image-marker.d.ts +19 -4
- package/dist/src/base-image-marker.js +116 -15
- package/dist/src/base-image-marker.js.map +1 -1
- package/dist/src/ox-image-marker-mode.d.ts +1 -0
- package/dist/src/ox-image-marker-mode.js +12 -2
- package/dist/src/ox-image-marker-mode.js.map +1 -1
- package/dist/src/ox-image-marker-view.js +3 -2
- package/dist/src/ox-image-marker-view.js.map +1 -1
- package/dist/src/ox-image-marker.d.ts +7 -6
- package/dist/src/ox-image-marker.js +165 -71
- package/dist/src/ox-image-marker.js.map +1 -1
- package/dist/stories/ox-image-marker.stories.js +16 -0
- package/dist/stories/ox-image-marker.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/base-image-marker.ts +143 -18
- package/src/ox-image-marker-mode.ts +15 -2
- package/src/ox-image-marker-view.ts +3 -2
- package/src/ox-image-marker.ts +193 -80
- package/stories/ox-image-marker.stories.ts +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
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.23](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.22...v8.0.0-alpha.23) (2024-10-05)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* support touch gesture for ox-image-markers ([14cd9da](https://github.com/hatiolab/operato/commit/14cd9da8001634305622b52e735b00d293409c35))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [8.0.0-alpha.22](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.21...v8.0.0-alpha.22) (2024-10-05)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### :bug: Bug Fix
|
|
19
|
+
|
|
20
|
+
* support touch gesture for ox-image-markers ([d1d8cc2](https://github.com/hatiolab/operato/commit/d1d8cc2fa385e2147172300f13cff49a195ce49f))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [8.0.0-alpha.18](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.17...v8.0.0-alpha.18) (2024-10-04)
|
|
7
25
|
|
|
8
26
|
|
|
@@ -13,12 +13,27 @@ export declare class BaseImageMarker extends LitElement {
|
|
|
13
13
|
y: number;
|
|
14
14
|
};
|
|
15
15
|
protected initialViewBox: string;
|
|
16
|
+
private initialPinchDistance;
|
|
17
|
+
private initialZoomLevel;
|
|
18
|
+
private lastTouchEnd;
|
|
16
19
|
protected svg: SVGSVGElement;
|
|
17
20
|
protected onImageLoad(event: Event): void;
|
|
18
|
-
protected
|
|
21
|
+
protected onSvgWheel(event: WheelEvent): void;
|
|
19
22
|
protected onSvgMouseDown(event: MouseEvent): void;
|
|
20
|
-
protected
|
|
21
|
-
protected
|
|
22
|
-
protected
|
|
23
|
+
protected isDoubleTouch(event: TouchEvent): boolean;
|
|
24
|
+
protected onSvgTouchStart: (event: TouchEvent) => void;
|
|
25
|
+
protected startPinchZooming(event: TouchEvent): void;
|
|
26
|
+
protected onZoomTouchMove: (event: TouchEvent) => void;
|
|
27
|
+
protected onZoomTouchEnd: (event: TouchEvent) => void;
|
|
28
|
+
protected applyZoom(): void;
|
|
29
|
+
protected onSvgDoubleClick(): void;
|
|
30
|
+
protected resetZoom(): void;
|
|
31
|
+
protected startPanning(event: MouseEvent | TouchEvent): void;
|
|
32
|
+
protected onPanMouseMove: (event: MouseEvent | TouchEvent) => void;
|
|
33
|
+
protected onPanMouseUp: (event: MouseEvent | TouchEvent) => void;
|
|
23
34
|
protected renderShape(shape: Shape): import("lit-html").TemplateResult<2> | typeof nothing;
|
|
35
|
+
protected getPointFromEvent(event: MouseEvent | TouchEvent): {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
};
|
|
24
39
|
}
|
|
@@ -12,11 +12,50 @@ export class BaseImageMarker extends LitElement {
|
|
|
12
12
|
this.isPanning = false;
|
|
13
13
|
this.panStart = { x: 0, y: 0 };
|
|
14
14
|
this.initialViewBox = '0 0 800 600';
|
|
15
|
+
this.initialPinchDistance = null;
|
|
16
|
+
this.initialZoomLevel = 1;
|
|
17
|
+
this.lastTouchEnd = 0;
|
|
18
|
+
this.onSvgTouchStart = (event) => {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
if (this.isDoubleTouch(event)) {
|
|
21
|
+
this.resetZoom();
|
|
22
|
+
}
|
|
23
|
+
if (event.touches.length === 1) {
|
|
24
|
+
this.startPanning(event);
|
|
25
|
+
}
|
|
26
|
+
else if (event.touches.length === 2) {
|
|
27
|
+
this.startPinchZooming(event);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
this.onZoomTouchMove = (event) => {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
if (event.touches.length === 2 && this.initialPinchDistance) {
|
|
33
|
+
const touch1 = event.touches[0];
|
|
34
|
+
const touch2 = event.touches[1];
|
|
35
|
+
const dx = touch2.clientX - touch1.clientX;
|
|
36
|
+
const dy = touch2.clientY - touch1.clientY;
|
|
37
|
+
const currentPinchDistance = Math.sqrt(dx * dx + dy * dy);
|
|
38
|
+
const scaleFactor = currentPinchDistance / this.initialPinchDistance;
|
|
39
|
+
this.zoomLevel = this.initialZoomLevel * scaleFactor;
|
|
40
|
+
this.applyZoom();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
this.onZoomTouchEnd = (event) => {
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
if (event.touches.length < 2) {
|
|
46
|
+
this.initialPinchDistance = null;
|
|
47
|
+
}
|
|
48
|
+
this.svg.removeEventListener('touchmove', this.onZoomTouchMove);
|
|
49
|
+
this.svg.removeEventListener('touchend', this.onZoomTouchEnd);
|
|
50
|
+
};
|
|
15
51
|
this.onPanMouseMove = (event) => {
|
|
16
|
-
if (!this.isPanning)
|
|
52
|
+
if (!this.isPanning) {
|
|
17
53
|
return;
|
|
18
|
-
|
|
19
|
-
|
|
54
|
+
}
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
const { x, y } = this.getPointFromEvent(event);
|
|
57
|
+
const dx = x - this.panStart.x;
|
|
58
|
+
const dy = y - this.panStart.y;
|
|
20
59
|
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
21
60
|
const scaleX = vbWidth / this.svg.clientWidth;
|
|
22
61
|
const scaleY = vbHeight / this.svg.clientHeight;
|
|
@@ -24,14 +63,21 @@ export class BaseImageMarker extends LitElement {
|
|
|
24
63
|
const newVbX = vbX - dx * scale;
|
|
25
64
|
const newVbY = vbY - dy * scale;
|
|
26
65
|
this.viewBox = `${newVbX} ${newVbY} ${vbWidth} ${vbHeight}`;
|
|
27
|
-
this.panStart = { x
|
|
66
|
+
this.panStart = { x, y };
|
|
28
67
|
};
|
|
29
|
-
this.onPanMouseUp = () => {
|
|
68
|
+
this.onPanMouseUp = (event) => {
|
|
69
|
+
event.preventDefault();
|
|
30
70
|
const svg = this.svg;
|
|
31
71
|
this.isPanning = false;
|
|
32
72
|
svg.classList.remove('dragging');
|
|
33
|
-
|
|
34
|
-
|
|
73
|
+
if ('touches' in event) {
|
|
74
|
+
svg.removeEventListener('touchmove', this.onPanMouseMove);
|
|
75
|
+
svg.removeEventListener('touchend', this.onPanMouseUp);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
svg.removeEventListener('mousemove', this.onPanMouseMove);
|
|
79
|
+
svg.removeEventListener('mouseup', this.onPanMouseUp);
|
|
80
|
+
}
|
|
35
81
|
};
|
|
36
82
|
}
|
|
37
83
|
static { this.styles = [
|
|
@@ -65,7 +111,7 @@ export class BaseImageMarker extends LitElement {
|
|
|
65
111
|
};
|
|
66
112
|
img.src = this.imageUrl;
|
|
67
113
|
}
|
|
68
|
-
|
|
114
|
+
onSvgWheel(event) {
|
|
69
115
|
event.preventDefault();
|
|
70
116
|
const { offsetX, offsetY, deltaY } = event;
|
|
71
117
|
const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor;
|
|
@@ -80,17 +126,58 @@ export class BaseImageMarker extends LitElement {
|
|
|
80
126
|
this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`;
|
|
81
127
|
}
|
|
82
128
|
onSvgMouseDown(event) {
|
|
83
|
-
|
|
84
|
-
this.
|
|
85
|
-
this.
|
|
86
|
-
svg.
|
|
87
|
-
|
|
88
|
-
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
this.startPanning(event);
|
|
131
|
+
this.svg.addEventListener('mousemove', this.onPanMouseMove);
|
|
132
|
+
this.svg.addEventListener('mouseup', this.onPanMouseUp);
|
|
133
|
+
}
|
|
134
|
+
isDoubleTouch(event) {
|
|
135
|
+
const currentTime = new Date().getTime();
|
|
136
|
+
const tapLength = currentTime - this.lastTouchEnd;
|
|
137
|
+
const result = tapLength < 300 && event.touches.length == 1;
|
|
138
|
+
this.lastTouchEnd = currentTime;
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
startPinchZooming(event) {
|
|
142
|
+
const touch1 = event.touches[0];
|
|
143
|
+
const touch2 = event.touches[1];
|
|
144
|
+
const dx = touch2.clientX - touch1.clientX;
|
|
145
|
+
const dy = touch2.clientY - touch1.clientY;
|
|
146
|
+
this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy);
|
|
147
|
+
this.initialZoomLevel = this.zoomLevel;
|
|
148
|
+
this.svg.addEventListener('touchmove', this.onZoomTouchMove);
|
|
149
|
+
this.svg.addEventListener('touchend', this.onZoomTouchEnd);
|
|
150
|
+
}
|
|
151
|
+
applyZoom() {
|
|
152
|
+
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
153
|
+
const initialViewBoxNumbers = this.initialViewBox.split(' ').map(Number);
|
|
154
|
+
const newVbWidth = initialViewBoxNumbers[2] / this.zoomLevel;
|
|
155
|
+
const newVbHeight = initialViewBoxNumbers[3] / this.zoomLevel;
|
|
156
|
+
const newVbX = vbX + (vbWidth - newVbWidth) / 2;
|
|
157
|
+
const newVbY = vbY + (vbHeight - newVbHeight) / 2;
|
|
158
|
+
this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`;
|
|
159
|
+
}
|
|
160
|
+
onSvgDoubleClick() {
|
|
161
|
+
this.resetZoom();
|
|
89
162
|
}
|
|
90
|
-
|
|
163
|
+
resetZoom() {
|
|
91
164
|
this.viewBox = this.initialViewBox;
|
|
92
165
|
this.zoomLevel = 1;
|
|
93
166
|
}
|
|
167
|
+
startPanning(event) {
|
|
168
|
+
const { x, y } = this.getPointFromEvent(event);
|
|
169
|
+
this.isPanning = true;
|
|
170
|
+
this.panStart = { x, y };
|
|
171
|
+
this.svg.classList.add('dragging');
|
|
172
|
+
if ('touches' in event) {
|
|
173
|
+
this.svg.addEventListener('touchmove', this.onPanMouseMove);
|
|
174
|
+
this.svg.addEventListener('touchend', this.onPanMouseUp);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.svg.addEventListener('mousemove', this.onPanMouseMove);
|
|
178
|
+
this.svg.addEventListener('mouseup', this.onPanMouseUp);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
94
181
|
renderShape(shape) {
|
|
95
182
|
const commonAttrs = {
|
|
96
183
|
stroke: 'red',
|
|
@@ -118,6 +205,20 @@ export class BaseImageMarker extends LitElement {
|
|
|
118
205
|
return nothing;
|
|
119
206
|
}
|
|
120
207
|
}
|
|
208
|
+
getPointFromEvent(event) {
|
|
209
|
+
if ('touches' in event) {
|
|
210
|
+
return {
|
|
211
|
+
x: event.touches[0].clientX,
|
|
212
|
+
y: event.touches[0].clientY
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
return {
|
|
217
|
+
x: event.clientX,
|
|
218
|
+
y: event.clientY
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
121
222
|
}
|
|
122
223
|
__decorate([
|
|
123
224
|
property({ type: String })
|
|
@@ -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 isPanning = false\n protected panStart = { x: 0, y: 0 }\n protected initialViewBox = '0 0 800 600'\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 onWheel(event: WheelEvent) {\n event.preventDefault()\n\n const { offsetX, offsetY, deltaY } = event\n const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor\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 protected onSvgMouseDown(event: MouseEvent) {\n const svg = this.svg\n\n this.isPanning = true\n this.panStart = { x: event.clientX, y: event.clientY }\n svg.classList.add('dragging')\n\n svg.addEventListener('mousemove', this.onPanMouseMove)\n svg.addEventListener('mouseup', this.onPanMouseUp)\n }\n\n protected onPanMouseMove = (event: MouseEvent) => {\n if (!this.isPanning) return\n\n const dx = event.clientX - this.panStart.x\n const dy = event.clientY - this.panStart.y\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: event.clientX, y: event.clientY }\n }\n\n protected onPanMouseUp = () => {\n const svg = this.svg\n\n this.isPanning = false\n svg.classList.remove('dragging')\n svg.removeEventListener('mousemove', this.onPanMouseMove)\n svg.removeEventListener('mouseup', this.onPanMouseUp)\n }\n\n protected onDoubleClick() {\n this.viewBox = this.initialViewBox\n this.zoomLevel = 1\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"]}
|
|
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 isPanning = false\n protected panStart = { x: 0, y: 0 }\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 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 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 this.zoomLevel = this.initialZoomLevel * scaleFactor\n\n this.applyZoom()\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.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 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"]}
|
|
@@ -91,6 +91,10 @@ let OxImageMarkerMode = class OxImageMarkerMode extends LitElement {
|
|
|
91
91
|
>
|
|
92
92
|
</div>
|
|
93
93
|
|
|
94
|
+
<div class="palette">
|
|
95
|
+
<md-icon title="Fit size" @click=${() => this.onClickFitSize()}>recenter</md-icon>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
94
98
|
<div class="palette">
|
|
95
99
|
<md-icon title="Delete" @click=${() => this.onClickDelete()}>delete</md-icon>
|
|
96
100
|
<md-icon title="Save" @click=${() => this.onClickSave()}>save</md-icon>
|
|
@@ -115,13 +119,19 @@ let OxImageMarkerMode = class OxImageMarkerMode extends LitElement {
|
|
|
115
119
|
}));
|
|
116
120
|
}
|
|
117
121
|
onClickDelete() {
|
|
118
|
-
this.dispatchEvent(new CustomEvent('
|
|
122
|
+
this.dispatchEvent(new CustomEvent('tap-delete', {
|
|
119
123
|
bubbles: true,
|
|
120
124
|
composed: true
|
|
121
125
|
}));
|
|
122
126
|
}
|
|
123
127
|
onClickSave() {
|
|
124
|
-
this.dispatchEvent(new CustomEvent('
|
|
128
|
+
this.dispatchEvent(new CustomEvent('tap-save', {
|
|
129
|
+
bubbles: true,
|
|
130
|
+
composed: true
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
onClickFitSize() {
|
|
134
|
+
this.dispatchEvent(new CustomEvent('tap-fit-size', {
|
|
125
135
|
bubbles: true,
|
|
126
136
|
composed: true
|
|
127
137
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-image-marker-mode.js","sourceRoot":"","sources":["../../src/ox-image-marker-mode.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAIpD,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,UAAU;IAA1C;;QAiCuB,gBAAW,GAAoB,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"ox-image-marker-mode.js","sourceRoot":"","sources":["../../src/ox-image-marker-mode.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ImageMarkerMode, ShapeType } from './types'\n\n@customElement('ox-image-marker-mode')\nexport class OxImageMarkerMode extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-medium);\n }\n\n .palette {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n justify-content: center;\n margin: var(--spacing-medium);\n\n --md-icon-size: 16px;\n }\n\n .palette > * {\n padding: var(--spacing-small);\n cursor: pointer;\n background-color: #f0f0f0;\n border: 1px solid #ccc;\n border-radius: 4px;\n width: 12px;\n height: 12px;\n }\n\n .palette [selected] {\n background-color: #d0d0d0;\n }\n `\n\n @property({ type: String }) currentMode: ImageMarkerMode = 'select'\n @property({ type: String }) currentShapeType?: ShapeType\n\n render() {\n return html`\n <div class=\"palette\">\n <md-icon\n title=\"Move or Select\"\n ?selected=${this.currentMode !== 'draw'}\n @click=${() => this.setMode(this.currentMode !== 'select' ? 'select' : 'move')}\n >${this.currentMode !== 'move' ? 'select' : 'drag_pan'}</md-icon\n >\n\n <md-icon\n title=\"Text\"\n ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'text'}\n @click=${() => this.setShape('text')}\n >match_case</md-icon\n >\n\n <md-icon\n title=\"Rectangle\"\n ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'rectangle'}\n @click=${() => this.setShape('rectangle')}\n >rectangle</md-icon\n >\n\n <md-icon\n title=\"Circle\"\n ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'circle'}\n @click=${() => this.setShape('circle')}\n >circle</md-icon\n >\n\n <md-icon\n title=\"Triangle\"\n ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'triangle'}\n @click=${() => this.setShape('triangle')}\n >change_history</md-icon\n >\n\n <md-icon\n title=\"Line\"\n ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'line'}\n @click=${() => this.setShape('line')}\n >shape_line</md-icon\n >\n\n <md-icon\n title=\"Arrow\"\n ?selected=${this.currentMode === 'draw' && this.currentShapeType === 'arrow'}\n @click=${() => this.setShape('arrow')}\n >line_end_arrow</md-icon\n >\n </div>\n\n <div class=\"palette\">\n <md-icon title=\"Fit size\" @click=${() => this.onClickFitSize()}>recenter</md-icon>\n </div>\n\n <div class=\"palette\">\n <md-icon title=\"Delete\" @click=${() => this.onClickDelete()}>delete</md-icon>\n <md-icon title=\"Save\" @click=${() => this.onClickSave()}>save</md-icon>\n </div>\n `\n }\n\n private setMode(mode: ImageMarkerMode) {\n this.currentMode = mode\n\n this.dispatchEvent(\n new CustomEvent('mode-changed', {\n detail: { mode: this.currentMode, shapeType: this.currentShapeType },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private setShape(shapeType: ShapeType) {\n this.currentMode = 'draw'\n this.currentShapeType = shapeType\n this.dispatchEvent(\n new CustomEvent('mode-changed', {\n detail: { mode: 'draw', shapeType: this.currentShapeType },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private onClickDelete() {\n this.dispatchEvent(\n new CustomEvent('tap-delete', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n private onClickSave() {\n this.dispatchEvent(\n new CustomEvent('tap-save', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n private onClickFitSize() {\n this.dispatchEvent(\n new CustomEvent('tap-fit-size', {\n bubbles: true,\n composed: true\n })\n )\n }\n}\n"]}
|
|
@@ -7,9 +7,10 @@ let OxImageMarkerView = class OxImageMarkerView extends BaseImageMarker {
|
|
|
7
7
|
return html `
|
|
8
8
|
<div class="container">
|
|
9
9
|
<svg
|
|
10
|
-
@wheel=${this.
|
|
10
|
+
@wheel=${this.onSvgWheel}
|
|
11
11
|
@mousedown=${this.onSvgMouseDown}
|
|
12
|
-
@
|
|
12
|
+
@touchstart=${this.onSvgTouchStart}
|
|
13
|
+
@dblclick=${this.onSvgDoubleClick}
|
|
13
14
|
viewBox=${this.viewBox}
|
|
14
15
|
>
|
|
15
16
|
<image href=${this.imageUrl} @load=${this.onImageLoad}></image>
|
|
@@ -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,
|
|
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"]}
|
|
@@ -14,21 +14,18 @@ export declare class OxImageMarker extends BaseImageMarker {
|
|
|
14
14
|
private offsetY;
|
|
15
15
|
connectedCallback(): void;
|
|
16
16
|
disconnectedCallback(): void;
|
|
17
|
-
private handleKeyDown;
|
|
18
|
-
private deleteSelectedShape;
|
|
19
17
|
render(): import("lit-html").TemplateResult<1>;
|
|
20
18
|
protected onSvgMouseDown(event: MouseEvent): void;
|
|
21
|
-
|
|
19
|
+
protected onSvgTouchStart: (event: TouchEvent) => void;
|
|
22
20
|
private startDrawing;
|
|
23
21
|
private setMode;
|
|
24
|
-
private
|
|
25
|
-
private
|
|
22
|
+
private onDrawingMouseMove;
|
|
23
|
+
private onDrawingMouseUp;
|
|
26
24
|
private getSvgPoint;
|
|
27
25
|
protected renderShape(shape: Shape): import("lit-html").TemplateResult<2> | typeof nothing;
|
|
28
26
|
private onShapeMouseDown;
|
|
29
27
|
private onShapeMouseMove;
|
|
30
28
|
private onShapeMouseUp;
|
|
31
|
-
private getScale;
|
|
32
29
|
private renderResizeHandles;
|
|
33
30
|
private onHandleMouseDown;
|
|
34
31
|
private onHandleMouseMove;
|
|
@@ -37,4 +34,8 @@ export declare class OxImageMarker extends BaseImageMarker {
|
|
|
37
34
|
private showTextInput;
|
|
38
35
|
private adjustInputWidth;
|
|
39
36
|
private measureTextWidth;
|
|
37
|
+
private onFocus;
|
|
38
|
+
private onBlur;
|
|
39
|
+
private handleKeyDown;
|
|
40
|
+
private deleteSelectedShape;
|
|
40
41
|
}
|