@operato/image-marker 8.0.0-alpha.23 → 8.0.0-alpha.25
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 +3 -0
- package/dist/src/base-image-marker.js +24 -11
- package/dist/src/base-image-marker.js.map +1 -1
- package/dist/src/ox-image-marker-mode.d.ts +2 -2
- package/dist/src/ox-image-marker-mode.js +13 -13
- package/dist/src/ox-image-marker-mode.js.map +1 -1
- package/dist/src/ox-image-marker.d.ts +13 -8
- package/dist/src/ox-image-marker.js +148 -116
- package/dist/src/ox-image-marker.js.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/base-image-marker.ts +27 -11
- package/src/ox-image-marker-mode.ts +15 -15
- package/src/ox-image-marker.ts +161 -119
- package/src/types.ts +1 -1
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.25](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.24...v8.0.0-alpha.25) (2024-10-06)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* support touch gesture for ox-image-markers ([66c35b2](https://github.com/hatiolab/operato/commit/66c35b2db4de5d3bd8d3b54d58e05f555856a381))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [8.0.0-alpha.24](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.23...v8.0.0-alpha.24) (2024-10-06)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### :bug: Bug Fix
|
|
19
|
+
|
|
20
|
+
* support touch gesture for ox-image-markers ([848bb9a](https://github.com/hatiolab/operato/commit/848bb9a31a303ca9e6db302a0294b4c0856b9471))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [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
25
|
|
|
8
26
|
|
|
@@ -7,11 +7,14 @@ export declare class BaseImageMarker extends LitElement {
|
|
|
7
7
|
protected viewBox: string;
|
|
8
8
|
protected zoomLevel: number;
|
|
9
9
|
protected zoomFactor: number;
|
|
10
|
+
protected zoomThreshold: number;
|
|
10
11
|
protected isPanning: boolean;
|
|
11
12
|
protected panStart: {
|
|
12
13
|
x: number;
|
|
13
14
|
y: number;
|
|
14
15
|
};
|
|
16
|
+
protected panInitiated: boolean;
|
|
17
|
+
protected panThreshold: number;
|
|
15
18
|
protected initialViewBox: string;
|
|
16
19
|
private initialPinchDistance;
|
|
17
20
|
private initialZoomLevel;
|
|
@@ -9,8 +9,11 @@ export class BaseImageMarker extends LitElement {
|
|
|
9
9
|
this.viewBox = '0 0 800 600';
|
|
10
10
|
this.zoomLevel = 1;
|
|
11
11
|
this.zoomFactor = 0.1;
|
|
12
|
+
this.zoomThreshold = 0.05;
|
|
12
13
|
this.isPanning = false;
|
|
13
14
|
this.panStart = { x: 0, y: 0 };
|
|
15
|
+
this.panInitiated = false;
|
|
16
|
+
this.panThreshold = 20;
|
|
14
17
|
this.initialViewBox = '0 0 800 600';
|
|
15
18
|
this.initialPinchDistance = null;
|
|
16
19
|
this.initialZoomLevel = 1;
|
|
@@ -36,8 +39,11 @@ export class BaseImageMarker extends LitElement {
|
|
|
36
39
|
const dy = touch2.clientY - touch1.clientY;
|
|
37
40
|
const currentPinchDistance = Math.sqrt(dx * dx + dy * dy);
|
|
38
41
|
const scaleFactor = currentPinchDistance / this.initialPinchDistance;
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
// 줌 threshold 확인 후 줌 적용
|
|
43
|
+
if (Math.abs(scaleFactor - 1) > this.zoomThreshold) {
|
|
44
|
+
this.zoomLevel = this.initialZoomLevel * scaleFactor;
|
|
45
|
+
this.applyZoom();
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
};
|
|
43
49
|
this.onZoomTouchEnd = (event) => {
|
|
@@ -56,6 +62,10 @@ export class BaseImageMarker extends LitElement {
|
|
|
56
62
|
const { x, y } = this.getPointFromEvent(event);
|
|
57
63
|
const dx = x - this.panStart.x;
|
|
58
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;
|
|
59
69
|
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
60
70
|
const scaleX = vbWidth / this.svg.clientWidth;
|
|
61
71
|
const scaleY = vbHeight / this.svg.clientHeight;
|
|
@@ -115,15 +125,17 @@ export class BaseImageMarker extends LitElement {
|
|
|
115
125
|
event.preventDefault();
|
|
116
126
|
const { offsetX, offsetY, deltaY } = event;
|
|
117
127
|
const scale = deltaY > 0 ? 1 - this.zoomFactor : 1 + this.zoomFactor;
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
if (Math.abs(scale - 1) > this.zoomThreshold) {
|
|
129
|
+
this.zoomLevel *= scale;
|
|
130
|
+
const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number);
|
|
131
|
+
const mouseX = vbX + (offsetX / this.svg.clientWidth) * vbWidth;
|
|
132
|
+
const mouseY = vbY + (offsetY / this.svg.clientHeight) * vbHeight;
|
|
133
|
+
const newVbWidth = vbWidth / scale;
|
|
134
|
+
const newVbHeight = vbHeight / scale;
|
|
135
|
+
const newVbX = mouseX - (offsetX / this.svg.clientWidth) * newVbWidth;
|
|
136
|
+
const newVbY = mouseY - (offsetY / this.svg.clientHeight) * newVbHeight;
|
|
137
|
+
this.viewBox = `${newVbX} ${newVbY} ${newVbWidth} ${newVbHeight}`;
|
|
138
|
+
}
|
|
127
139
|
}
|
|
128
140
|
onSvgMouseDown(event) {
|
|
129
141
|
event.preventDefault();
|
|
@@ -168,6 +180,7 @@ export class BaseImageMarker extends LitElement {
|
|
|
168
180
|
const { x, y } = this.getPointFromEvent(event);
|
|
169
181
|
this.isPanning = true;
|
|
170
182
|
this.panStart = { x, y };
|
|
183
|
+
this.panInitiated = false; // 팬 동작이 아직 시작되지 않았음을 나타냄
|
|
171
184
|
this.svg.classList.add('dragging');
|
|
172
185
|
if ('touches' in event) {
|
|
173
186
|
this.svg.addEventListener('touchmove', this.onPanMouseMove);
|
|
@@ -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 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"]}
|
|
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"]}
|
|
@@ -6,8 +6,8 @@ export declare class OxImageMarkerMode extends LitElement {
|
|
|
6
6
|
currentMode: ImageMarkerMode;
|
|
7
7
|
currentShapeType?: ShapeType;
|
|
8
8
|
render(): import("lit-html").TemplateResult<1>;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
setMode(mode: ImageMarkerMode): void;
|
|
10
|
+
protected setShape(shapeType: ShapeType): void;
|
|
11
11
|
private onClickDelete;
|
|
12
12
|
private onClickSave;
|
|
13
13
|
private onClickFitSize;
|
|
@@ -5,7 +5,7 @@ import { customElement, property } from 'lit/decorators.js';
|
|
|
5
5
|
let OxImageMarkerMode = class OxImageMarkerMode extends LitElement {
|
|
6
6
|
constructor() {
|
|
7
7
|
super(...arguments);
|
|
8
|
-
this.currentMode = '
|
|
8
|
+
this.currentMode = 'edit';
|
|
9
9
|
}
|
|
10
10
|
static { this.styles = css `
|
|
11
11
|
:host {
|
|
@@ -42,50 +42,50 @@ let OxImageMarkerMode = class OxImageMarkerMode extends LitElement {
|
|
|
42
42
|
return html `
|
|
43
43
|
<div class="palette">
|
|
44
44
|
<md-icon
|
|
45
|
-
title="
|
|
46
|
-
?selected=${this.currentMode !== '
|
|
47
|
-
@click=${() => this.setMode(this.currentMode !== '
|
|
48
|
-
>${this.currentMode !== '
|
|
45
|
+
title="Edit or View"
|
|
46
|
+
?selected=${this.currentMode !== 'shape'}
|
|
47
|
+
@click=${() => this.setMode(this.currentMode !== 'edit' ? 'edit' : 'view')}
|
|
48
|
+
>${this.currentMode !== 'view' ? 'brush' : 'drag_pan'}</md-icon
|
|
49
49
|
>
|
|
50
50
|
|
|
51
51
|
<md-icon
|
|
52
52
|
title="Text"
|
|
53
|
-
?selected=${this.currentMode === '
|
|
53
|
+
?selected=${this.currentMode === 'shape' && this.currentShapeType === 'text'}
|
|
54
54
|
@click=${() => this.setShape('text')}
|
|
55
55
|
>match_case</md-icon
|
|
56
56
|
>
|
|
57
57
|
|
|
58
58
|
<md-icon
|
|
59
59
|
title="Rectangle"
|
|
60
|
-
?selected=${this.currentMode === '
|
|
60
|
+
?selected=${this.currentMode === 'shape' && this.currentShapeType === 'rectangle'}
|
|
61
61
|
@click=${() => this.setShape('rectangle')}
|
|
62
62
|
>rectangle</md-icon
|
|
63
63
|
>
|
|
64
64
|
|
|
65
65
|
<md-icon
|
|
66
66
|
title="Circle"
|
|
67
|
-
?selected=${this.currentMode === '
|
|
67
|
+
?selected=${this.currentMode === 'shape' && this.currentShapeType === 'circle'}
|
|
68
68
|
@click=${() => this.setShape('circle')}
|
|
69
69
|
>circle</md-icon
|
|
70
70
|
>
|
|
71
71
|
|
|
72
72
|
<md-icon
|
|
73
73
|
title="Triangle"
|
|
74
|
-
?selected=${this.currentMode === '
|
|
74
|
+
?selected=${this.currentMode === 'shape' && this.currentShapeType === 'triangle'}
|
|
75
75
|
@click=${() => this.setShape('triangle')}
|
|
76
76
|
>change_history</md-icon
|
|
77
77
|
>
|
|
78
78
|
|
|
79
79
|
<md-icon
|
|
80
80
|
title="Line"
|
|
81
|
-
?selected=${this.currentMode === '
|
|
81
|
+
?selected=${this.currentMode === 'shape' && this.currentShapeType === 'line'}
|
|
82
82
|
@click=${() => this.setShape('line')}
|
|
83
83
|
>shape_line</md-icon
|
|
84
84
|
>
|
|
85
85
|
|
|
86
86
|
<md-icon
|
|
87
87
|
title="Arrow"
|
|
88
|
-
?selected=${this.currentMode === '
|
|
88
|
+
?selected=${this.currentMode === 'shape' && this.currentShapeType === 'arrow'}
|
|
89
89
|
@click=${() => this.setShape('arrow')}
|
|
90
90
|
>line_end_arrow</md-icon
|
|
91
91
|
>
|
|
@@ -110,10 +110,10 @@ let OxImageMarkerMode = class OxImageMarkerMode extends LitElement {
|
|
|
110
110
|
}));
|
|
111
111
|
}
|
|
112
112
|
setShape(shapeType) {
|
|
113
|
-
this.currentMode = '
|
|
113
|
+
this.currentMode = 'shape';
|
|
114
114
|
this.currentShapeType = shapeType;
|
|
115
115
|
this.dispatchEvent(new CustomEvent('mode-changed', {
|
|
116
|
-
detail: { mode: '
|
|
116
|
+
detail: { mode: 'shape', shapeType: this.currentShapeType },
|
|
117
117
|
bubbles: true,
|
|
118
118
|
composed: true
|
|
119
119
|
}));
|
|
@@ -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,
|
|
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 = 'edit'\n @property({ type: String }) currentShapeType?: ShapeType\n\n render() {\n return html`\n <div class=\"palette\">\n <md-icon\n title=\"Edit or View\"\n ?selected=${this.currentMode !== 'shape'}\n @click=${() => this.setMode(this.currentMode !== 'edit' ? 'edit' : 'view')}\n >${this.currentMode !== 'view' ? 'brush' : 'drag_pan'}</md-icon\n >\n\n <md-icon\n title=\"Text\"\n ?selected=${this.currentMode === 'shape' && 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 === 'shape' && this.currentShapeType === 'rectangle'}\n @click=${() => this.setShape('rectangle')}\n >rectangle</md-icon\n >\n\n <md-icon\n title=\"Circle\"\n ?selected=${this.currentMode === 'shape' && this.currentShapeType === 'circle'}\n @click=${() => this.setShape('circle')}\n >circle</md-icon\n >\n\n <md-icon\n title=\"Triangle\"\n ?selected=${this.currentMode === 'shape' && 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 === 'shape' && 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 === 'shape' && 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 public 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 protected setShape(shapeType: ShapeType) {\n this.currentMode = 'shape'\n this.currentShapeType = shapeType\n this.dispatchEvent(\n new CustomEvent('mode-changed', {\n detail: { mode: 'shape', 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"]}
|
|
@@ -2,16 +2,20 @@ import './ox-image-marker-mode';
|
|
|
2
2
|
import { nothing } from 'lit';
|
|
3
3
|
import { Shape } from './types';
|
|
4
4
|
import { BaseImageMarker } from './base-image-marker';
|
|
5
|
+
import { OxImageMarkerMode } from './ox-image-marker-mode';
|
|
5
6
|
export declare class OxImageMarker extends BaseImageMarker {
|
|
6
7
|
static styles: import("lit").CSSResult[];
|
|
7
8
|
private currentShapeType?;
|
|
8
9
|
private currentMode;
|
|
9
10
|
private selectedShape;
|
|
11
|
+
imageMarkerMode: OxImageMarkerMode;
|
|
10
12
|
private drawing;
|
|
11
13
|
private startX;
|
|
12
14
|
private startY;
|
|
13
15
|
private offsetX;
|
|
14
16
|
private offsetY;
|
|
17
|
+
private shapeMoveThreshold;
|
|
18
|
+
private shapeMoveInitiated;
|
|
15
19
|
connectedCallback(): void;
|
|
16
20
|
disconnectedCallback(): void;
|
|
17
21
|
render(): import("lit-html").TemplateResult<1>;
|
|
@@ -19,17 +23,18 @@ export declare class OxImageMarker extends BaseImageMarker {
|
|
|
19
23
|
protected onSvgTouchStart: (event: TouchEvent) => void;
|
|
20
24
|
private startDrawing;
|
|
21
25
|
private setMode;
|
|
22
|
-
private
|
|
23
|
-
private
|
|
26
|
+
private onMouseMoveForDrawing;
|
|
27
|
+
private onMouseUpForDrawing;
|
|
28
|
+
private setSelectedShape;
|
|
24
29
|
private getSvgPoint;
|
|
25
30
|
protected renderShape(shape: Shape): import("lit-html").TemplateResult<2> | typeof nothing;
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private
|
|
31
|
+
private onMouseDownOnShape;
|
|
32
|
+
private onMouseMoveOnShape;
|
|
33
|
+
private onMouseUpOnShape;
|
|
29
34
|
private renderResizeHandles;
|
|
30
|
-
private
|
|
31
|
-
private
|
|
32
|
-
private
|
|
35
|
+
private onResizeHandleMouseDown;
|
|
36
|
+
private onResizeHandleMouseMove;
|
|
37
|
+
private onResizeHandleMouseUp;
|
|
33
38
|
private onTextDoubleClick;
|
|
34
39
|
private showTextInput;
|
|
35
40
|
private adjustInputWidth;
|