@annotorious/annotorious 3.0.0-rc.3 → 3.0.0-rc.31
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/dist/Annotorious.d.ts +10 -7
- package/dist/Annotorious.d.ts.map +1 -1
- package/dist/AnnotoriousOpts.d.ts +8 -6
- package/dist/AnnotoriousOpts.d.ts.map +1 -1
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts +4 -2
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts.map +1 -1
- package/dist/annotation/editors/Handle.svelte.d.ts +1 -0
- package/dist/annotation/editors/editorsRegistry.d.ts +4 -3
- package/dist/annotation/editors/editorsRegistry.d.ts.map +1 -1
- package/dist/annotation/editors/index.d.ts +1 -1
- package/dist/annotation/editors/index.d.ts.map +1 -1
- package/dist/annotation/tools/DrawingToolConfig.d.ts +2 -1
- package/dist/annotation/tools/drawingToolsRegistry.d.ts +5 -4
- package/dist/annotation/tools/drawingToolsRegistry.d.ts.map +1 -1
- package/dist/annotation/utils/responsive.d.ts +1 -1
- package/dist/annotation/utils/styling.d.ts +4 -3
- package/dist/annotation/utils/styling.d.ts.map +1 -1
- package/dist/annotation/utils/touch.d.ts.map +1 -1
- package/dist/annotorious.css +1 -1
- package/dist/annotorious.es.js +2540 -2178
- package/dist/annotorious.es.js.map +1 -1
- package/dist/annotorious.js +1 -1
- package/dist/annotorious.js.map +1 -1
- package/dist/index.d.ts +1 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/keyboardCommands.d.ts +3 -2
- package/dist/keyboardCommands.d.ts.map +1 -1
- package/dist/model/core/ImageAnnotation.d.ts +3 -2
- package/dist/model/core/Shape.d.ts +2 -1
- package/dist/model/core/ellipse/Ellipse.d.ts +2 -1
- package/dist/model/core/polygon/Polygon.d.ts +2 -1
- package/dist/model/core/rectangle/Rectangle.d.ts +2 -1
- package/dist/model/core/rectangle/rectangleUtils.d.ts +3 -2
- package/dist/model/core/shapeUtils.d.ts +3 -5
- package/dist/model/core/shapeUtils.d.ts.map +1 -1
- package/dist/model/w3c/W3CImageAnnotation.d.ts +12 -0
- package/dist/model/w3c/W3CImageAnnotation.d.ts.map +1 -0
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts +12 -6
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts.map +1 -1
- package/dist/model/w3c/fragment/FragmentSelector.d.ts +3 -3
- package/dist/model/w3c/fragment/FragmentSelector.d.ts.map +1 -1
- package/dist/model/w3c/index.d.ts +1 -0
- package/dist/model/w3c/index.d.ts.map +1 -1
- package/dist/model/w3c/svg/SVG.d.ts.map +1 -1
- package/dist/model/w3c/svg/SVGSelector.d.ts +3 -3
- package/dist/model/w3c/svg/SVGSelector.d.ts.map +1 -1
- package/dist/state/ImageAnnotationStore.d.ts +3 -2
- package/dist/state/ImageAnnotatorState.d.ts +5 -4
- package/dist/state/ImageAnnotatorState.d.ts.map +1 -1
- package/dist/state/spatialTree.d.ts +3 -2
- package/dist/state/spatialTree.d.ts.map +1 -1
- package/dist/themes/smart/setTheme.d.ts +4 -1
- package/dist/themes/smart/setTheme.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/Annotorious.css +9 -5
- package/src/Annotorious.ts +52 -36
- package/src/AnnotoriousOpts.ts +16 -15
- package/src/annotation/SVGAnnotationLayer.svelte +71 -36
- package/src/annotation/SVGAnnotationLayerPointerEvent.ts +2 -3
- package/src/annotation/Transform.ts +1 -1
- package/src/annotation/editors/Editor.svelte +10 -11
- package/src/annotation/editors/EditorMount.svelte +3 -3
- package/src/annotation/editors/Handle.svelte +66 -0
- package/src/annotation/editors/editorsRegistry.ts +2 -2
- package/src/annotation/editors/index.ts +2 -2
- package/src/annotation/editors/polygon/PolygonEditor.svelte +16 -16
- package/src/annotation/editors/rectangle/RectangleEditor.svelte +46 -43
- package/src/annotation/shapes/Ellipse.svelte +3 -3
- package/src/annotation/shapes/Polygon.svelte +3 -3
- package/src/annotation/shapes/Rectangle.svelte +3 -3
- package/src/annotation/tools/ToolMount.svelte +3 -3
- package/src/annotation/tools/drawingToolsRegistry.ts +2 -1
- package/src/annotation/tools/polygon/RubberbandPolygon.svelte +40 -13
- package/src/annotation/tools/rectangle/RubberbandRectangle.svelte +27 -11
- package/src/annotation/utils/responsive.ts +1 -1
- package/src/annotation/utils/styling.ts +5 -2
- package/src/annotation/utils/touch.ts +4 -1
- package/src/index.ts +22 -16
- package/src/keyboardCommands.ts +11 -7
- package/src/model/w3c/W3CImageAnnotation.ts +17 -0
- package/src/model/w3c/W3CImageFormatAdapter.ts +79 -31
- package/src/model/w3c/fragment/FragmentSelector.ts +5 -6
- package/src/model/w3c/index.ts +1 -0
- package/src/model/w3c/svg/SVG.ts +1 -2
- package/src/model/w3c/svg/SVGSelector.ts +11 -13
- package/src/state/ImageAnnotatorState.ts +4 -5
- package/src/state/spatialTree.ts +13 -6
- package/src/themes/dark/index.css +2 -2
- package/src/themes/light/index.css +2 -2
- package/src/themes/smart/setTheme.ts +10 -6
- package/dist/annotation/editors/Handle.d.ts +0 -14
- package/dist/annotation/editors/Handle.d.ts.map +0 -1
- package/src/annotation/editors/Handle.ts +0 -21
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import {
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { SvelteComponent, onMount } from 'svelte';
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
-
import type {
|
|
4
|
+
import type { DrawingStyleExpression, StoreChangeEvent, User } from '@annotorious/core';
|
|
5
5
|
import { ShapeType } from '../model';
|
|
6
6
|
import type { ImageAnnotation, Shape} from '../model';
|
|
7
|
-
import { getEditor, EditorMount } from './editors';
|
|
7
|
+
import { getEditor as _getEditor, EditorMount } from './editors';
|
|
8
8
|
import { Ellipse, Polygon, Rectangle} from './shapes';
|
|
9
|
-
import { getTool, ToolMount } from './tools';
|
|
9
|
+
import { getTool, listDrawingTools, ToolMount } from './tools';
|
|
10
10
|
import { enableResponsive } from './utils';
|
|
11
11
|
import { createSVGTransform } from './Transform';
|
|
12
|
-
import { addEventListeners } from './SVGAnnotationLayerPointerEvent';
|
|
12
|
+
import { addEventListeners, getSVGPoint } from './SVGAnnotationLayerPointerEvent';
|
|
13
13
|
import type { SvelteImageAnnotatorState } from 'src/state';
|
|
14
14
|
import type { DrawingMode } from 'src/AnnotoriousOpts';
|
|
15
15
|
|
|
@@ -18,9 +18,12 @@
|
|
|
18
18
|
export let image: HTMLImageElement | HTMLCanvasElement;
|
|
19
19
|
export let preferredDrawingMode: DrawingMode;
|
|
20
20
|
export let state: SvelteImageAnnotatorState;
|
|
21
|
-
export let style:
|
|
22
|
-
export let
|
|
21
|
+
export let style: DrawingStyleExpression<ImageAnnotation> | undefined = undefined;
|
|
22
|
+
export let toolName: string = listDrawingTools()[0];
|
|
23
23
|
export let user: User;
|
|
24
|
+
export let visible = true;
|
|
25
|
+
|
|
26
|
+
$: ({ tool, opts } = getTool(toolName) || { tool: undefined, opts: undefined });
|
|
24
27
|
|
|
25
28
|
$: drawingMode = opts?.drawingMode || preferredDrawingMode;
|
|
26
29
|
|
|
@@ -37,20 +40,21 @@
|
|
|
37
40
|
$: transform = createSVGTransform(svgEl);
|
|
38
41
|
|
|
39
42
|
/** Selection tracking */
|
|
40
|
-
const { selection, store } = state;
|
|
43
|
+
const { hover, selection, store } = state;
|
|
41
44
|
|
|
42
45
|
$: ({ onPointerDown, onPointerUp } = addEventListeners(svgEl, store));
|
|
43
46
|
|
|
44
|
-
let storeObserver
|
|
47
|
+
let storeObserver: (event: StoreChangeEvent<ImageAnnotation>) => void | undefined;
|
|
45
48
|
|
|
46
|
-
let editableAnnotations: ImageAnnotation[]
|
|
49
|
+
let editableAnnotations: ImageAnnotation[] | undefined;
|
|
47
50
|
|
|
48
51
|
$: isEditable = (a: ImageAnnotation) => $selection.selected.find(s => s.id === a.id && s.editable);
|
|
49
52
|
|
|
50
53
|
$: trackSelection($selection.selected);
|
|
51
54
|
|
|
52
55
|
const trackSelection = (selected: { id: string, editable?: boolean }[]) => {
|
|
53
|
-
|
|
56
|
+
if (storeObserver)
|
|
57
|
+
store.unobserve(storeObserver);
|
|
54
58
|
|
|
55
59
|
// Track only editable annotations
|
|
56
60
|
const editableIds =
|
|
@@ -58,17 +62,17 @@
|
|
|
58
62
|
|
|
59
63
|
if (editableIds.length > 0) {
|
|
60
64
|
// Resolve selected IDs from the store
|
|
61
|
-
editableAnnotations = editableIds.map(id => store.getAnnotation(id));
|
|
65
|
+
editableAnnotations = editableIds.map(id => store.getAnnotation(id)!).filter(Boolean);
|
|
62
66
|
|
|
63
67
|
// Track updates on the editable annotations
|
|
64
68
|
storeObserver = (event: StoreChangeEvent<ImageAnnotation>) => {
|
|
65
69
|
const { updated } = event.changes;
|
|
66
|
-
editableAnnotations = updated
|
|
70
|
+
editableAnnotations = updated?.map(change => change.newValue);
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
store.observe(storeObserver, { annotations: editableIds });
|
|
70
74
|
} else {
|
|
71
|
-
editableAnnotations =
|
|
75
|
+
editableAnnotations = undefined;
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
|
|
@@ -106,30 +110,58 @@
|
|
|
106
110
|
...target,
|
|
107
111
|
selector: event.detail,
|
|
108
112
|
created: isUpdate ? target.created : new Date(),
|
|
109
|
-
updated: isUpdate ? new Date() :
|
|
110
|
-
updatedBy: isUpdate ? user :
|
|
113
|
+
updated: isUpdate ? new Date() : undefined,
|
|
114
|
+
updatedBy: isUpdate ? user : undefined
|
|
111
115
|
});
|
|
112
116
|
}
|
|
117
|
+
|
|
118
|
+
const onPointerMove = (evt: PointerEvent) => {
|
|
119
|
+
const { x, y } = getSVGPoint(evt, svgEl);
|
|
120
|
+
|
|
121
|
+
const hit = store.getAt(x, y);
|
|
122
|
+
if (hit) {
|
|
123
|
+
if ($hover !== hit.id) {
|
|
124
|
+
hover.set(hit.id);
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
hover.set(undefined);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// To get around lack of TypeScript support in Svelte markup
|
|
132
|
+
const getEditor = (shape: Shape): typeof SvelteComponent => _getEditor(shape)!;
|
|
113
133
|
</script>
|
|
114
134
|
|
|
115
135
|
<svg
|
|
116
136
|
bind:this={svgEl}
|
|
117
137
|
class="a9s-annotationlayer"
|
|
118
138
|
class:drawing={tool}
|
|
139
|
+
class:hidden={!visible}
|
|
140
|
+
class:hover={$hover}
|
|
119
141
|
on:pointerup={onPointerUp}
|
|
120
|
-
on:pointerdown={onPointerDown}
|
|
142
|
+
on:pointerdown={onPointerDown}
|
|
143
|
+
on:pointermove={onPointerMove}>
|
|
121
144
|
|
|
122
145
|
<g>
|
|
123
146
|
{#each $store as annotation}
|
|
124
147
|
{#if !isEditable(annotation)}
|
|
125
148
|
{@const selector = annotation.target.selector}
|
|
126
149
|
{#key annotation.id}
|
|
127
|
-
{#if (selector
|
|
128
|
-
<Ellipse
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
150
|
+
{#if (selector?.type === ShapeType.ELLIPSE)}
|
|
151
|
+
<Ellipse
|
|
152
|
+
annotation={annotation}
|
|
153
|
+
geom={selector?.geometry}
|
|
154
|
+
style={style} />
|
|
155
|
+
{:else if (selector?.type === ShapeType.RECTANGLE)}
|
|
156
|
+
<Rectangle
|
|
157
|
+
annotation={annotation}
|
|
158
|
+
geom={selector.geometry}
|
|
159
|
+
style={style} />
|
|
160
|
+
{:else if (selector?.type === ShapeType.POLYGON)}
|
|
161
|
+
<Polygon
|
|
162
|
+
annotation={annotation}
|
|
163
|
+
geom={selector.geometry}
|
|
164
|
+
style={style} />
|
|
133
165
|
{/if}
|
|
134
166
|
{/key}
|
|
135
167
|
{/if}
|
|
@@ -142,19 +174,22 @@
|
|
|
142
174
|
{#if drawingEl}
|
|
143
175
|
{#if editableAnnotations}
|
|
144
176
|
{#each editableAnnotations as editable}
|
|
145
|
-
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
177
|
+
{@const editor = getEditor(editable.target.selector)}
|
|
178
|
+
{#if editor}
|
|
179
|
+
{#key editable.id}
|
|
180
|
+
<EditorMount
|
|
181
|
+
target={drawingEl}
|
|
182
|
+
editor={getEditor(editable.target.selector)}
|
|
183
|
+
annotation={editable}
|
|
184
|
+
style={style}
|
|
185
|
+
transform={transform}
|
|
186
|
+
viewportScale={$scale}
|
|
187
|
+
on:change={onChangeSelected(editable)} />
|
|
188
|
+
{/key}
|
|
189
|
+
{/if}
|
|
155
190
|
{/each}
|
|
156
191
|
{:else if (tool && drawingEnabled)}
|
|
157
|
-
{#key
|
|
192
|
+
{#key toolName}
|
|
158
193
|
<ToolMount
|
|
159
194
|
target={drawingEl}
|
|
160
195
|
tool={tool}
|
|
@@ -166,4 +201,4 @@
|
|
|
166
201
|
{/if}
|
|
167
202
|
{/if}
|
|
168
203
|
</g>
|
|
169
|
-
</svg>
|
|
204
|
+
</svg>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createEventDispatcher } from 'svelte';
|
|
2
2
|
import type { SvelteImageAnnotationStore } from '../state';
|
|
3
3
|
import type { ImageAnnotation } from '../model';
|
|
4
|
-
import { isTouch } from './utils';
|
|
5
4
|
|
|
6
5
|
export interface SVGAnnotationLayerPointerEvent {
|
|
7
6
|
|
|
@@ -40,7 +39,7 @@ export const addEventListeners = (svg: SVGSVGElement, store: SvelteImageAnnotati
|
|
|
40
39
|
return { onPointerDown, onPointerUp };
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
|
|
42
|
+
export const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
|
|
44
43
|
const pt = svg.createSVGPoint();
|
|
45
44
|
const bbox = svg.getBoundingClientRect();
|
|
46
45
|
|
|
@@ -51,5 +50,5 @@ const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
|
|
|
51
50
|
pt.x = x + left;
|
|
52
51
|
pt.y = y + top;
|
|
53
52
|
|
|
54
|
-
return pt.matrixTransform(svg.getScreenCTM()
|
|
53
|
+
return pt.matrixTransform(svg.getScreenCTM()!.inverse());
|
|
55
54
|
}
|
|
@@ -19,7 +19,7 @@ export const createSVGTransform = (svg: SVGSVGElement): Transform => ({
|
|
|
19
19
|
pt.x = offsetX + bbox.x;
|
|
20
20
|
pt.y = offsetY + bbox.y;
|
|
21
21
|
|
|
22
|
-
const { x, y } = pt.matrixTransform(svg.getScreenCTM()
|
|
22
|
+
const { x, y } = pt.matrixTransform(svg.getScreenCTM()!.inverse());
|
|
23
23
|
return [x, y];
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { createEventDispatcher } from 'svelte';
|
|
3
3
|
import type { Shape } from '../../model';
|
|
4
|
-
import type { Handle } from './Handle';
|
|
5
4
|
import type { Transform } from '../Transform';
|
|
6
5
|
|
|
7
|
-
const dispatch = createEventDispatcher<{ grab:
|
|
6
|
+
const dispatch = createEventDispatcher<{ grab: PointerEvent, release: PointerEvent, change: Shape }>();
|
|
8
7
|
|
|
9
8
|
/** Props */
|
|
10
9
|
export let shape: Shape;
|
|
11
|
-
export let editor: (shape: Shape, handle:
|
|
10
|
+
export let editor: (shape: Shape, handle: string, delta: [number, number]) => Shape;
|
|
12
11
|
export let transform: Transform;
|
|
13
12
|
|
|
14
|
-
let grabbedHandle:
|
|
13
|
+
let grabbedHandle: string | undefined;
|
|
15
14
|
|
|
16
15
|
let origin: [number, number];
|
|
17
16
|
|
|
18
|
-
let initialShape: Shape
|
|
17
|
+
let initialShape: Shape | undefined;
|
|
19
18
|
|
|
20
|
-
const onGrab = (handle:
|
|
19
|
+
const onGrab = (handle: string) => (evt: PointerEvent) => {
|
|
21
20
|
grabbedHandle = handle;
|
|
22
21
|
origin = transform.elementToImage(evt.offsetX, evt.offsetY);
|
|
23
22
|
initialShape = shape;
|
|
@@ -25,7 +24,7 @@
|
|
|
25
24
|
const target = evt.target as Element;
|
|
26
25
|
target.setPointerCapture(evt.pointerId);
|
|
27
26
|
|
|
28
|
-
dispatch('grab');
|
|
27
|
+
dispatch('grab', evt);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
const onPointerMove = (evt: PointerEvent) => {
|
|
@@ -34,7 +33,7 @@
|
|
|
34
33
|
|
|
35
34
|
const delta: [number, number] = [x - origin[0], y - origin[1]];
|
|
36
35
|
|
|
37
|
-
shape = editor(initialShape
|
|
36
|
+
shape = editor(initialShape!, grabbedHandle, delta);
|
|
38
37
|
|
|
39
38
|
dispatch('change', shape);
|
|
40
39
|
}
|
|
@@ -44,11 +43,11 @@
|
|
|
44
43
|
const target = evt.target as Element;
|
|
45
44
|
target.releasePointerCapture(evt.pointerId);
|
|
46
45
|
|
|
47
|
-
grabbedHandle =
|
|
46
|
+
grabbedHandle = undefined;
|
|
48
47
|
|
|
49
48
|
initialShape = shape;
|
|
50
49
|
|
|
51
|
-
dispatch('release');
|
|
50
|
+
dispatch('release', evt);
|
|
52
51
|
}
|
|
53
52
|
</script>
|
|
54
53
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type {
|
|
2
|
+
import type { DrawingStyleExpression } from '@annotorious/core';
|
|
3
3
|
import { createEventDispatcher, onMount, type SvelteComponent } from 'svelte';
|
|
4
4
|
import type { ImageAnnotation, Shape } from '../../model';
|
|
5
5
|
import { computeStyle } from '../utils/styling';
|
|
6
6
|
import type { Transform } from '../Transform';
|
|
7
7
|
|
|
8
|
-
const dispatch = createEventDispatcher<{ grab:
|
|
8
|
+
const dispatch = createEventDispatcher<{ grab: PointerEvent, release: PointerEvent, change: Shape }>();
|
|
9
9
|
|
|
10
10
|
/** Props */
|
|
11
11
|
export let annotation: ImageAnnotation;
|
|
12
12
|
export let editor: typeof SvelteComponent;
|
|
13
|
-
export let style:
|
|
13
|
+
export let style: DrawingStyleExpression<ImageAnnotation> | undefined;
|
|
14
14
|
export let target: SVGGElement;
|
|
15
15
|
export let transform: Transform;
|
|
16
16
|
export let viewportScale: number;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { isTouch } from '../utils';
|
|
3
|
+
|
|
4
|
+
/** props **/
|
|
5
|
+
export let x: number;
|
|
6
|
+
export let y: number;
|
|
7
|
+
export let scale: number;
|
|
8
|
+
export let radius: number = 30;
|
|
9
|
+
|
|
10
|
+
let touched = false;
|
|
11
|
+
|
|
12
|
+
const onPointerDown = (event: PointerEvent) => {
|
|
13
|
+
if (event.pointerType === 'touch')
|
|
14
|
+
touched = true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const onPointerUp = () =>
|
|
18
|
+
touched = false;
|
|
19
|
+
|
|
20
|
+
$: handleSize = 10 / scale;
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
{#if isTouch}
|
|
24
|
+
<g class="a9s-touch-handle">
|
|
25
|
+
<circle
|
|
26
|
+
cx={x}
|
|
27
|
+
cy={y}
|
|
28
|
+
r={radius / scale}
|
|
29
|
+
class="a9s-touch-halo"
|
|
30
|
+
class:touched={touched}
|
|
31
|
+
on:pointerdown
|
|
32
|
+
on:pointerdown={onPointerDown}
|
|
33
|
+
on:pointerup={onPointerUp} />
|
|
34
|
+
|
|
35
|
+
<rect
|
|
36
|
+
class={`a9s-handle ${$$props.class || ''}`.trim()}
|
|
37
|
+
x={x - handleSize / 2}
|
|
38
|
+
y={y - handleSize / 2}
|
|
39
|
+
width={handleSize}
|
|
40
|
+
height={handleSize}
|
|
41
|
+
on:pointerdown
|
|
42
|
+
on:pointerdown={onPointerDown}
|
|
43
|
+
on:pointerup={onPointerUp} />
|
|
44
|
+
</g>
|
|
45
|
+
{:else}
|
|
46
|
+
<rect
|
|
47
|
+
class={`a9s-handle ${$$props.class || ''}`.trim()}
|
|
48
|
+
x={x - handleSize / 2}
|
|
49
|
+
y={y - handleSize / 2}
|
|
50
|
+
width={handleSize}
|
|
51
|
+
height={handleSize}
|
|
52
|
+
on:pointerdown />
|
|
53
|
+
{/if}
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.a9s-touch-halo {
|
|
57
|
+
fill: transparent;
|
|
58
|
+
stroke-width: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.a9s-touch-halo.touched {
|
|
62
|
+
fill: rgba(255, 255, 255, 0.25);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
</style>
|
|
@@ -4,8 +4,8 @@ import { PolygonEditor } from './polygon';
|
|
|
4
4
|
import { RectangleEditor } from './rectangle';
|
|
5
5
|
|
|
6
6
|
const REGISTERED = new Map<ShapeType, typeof SvelteComponent>([
|
|
7
|
-
[ShapeType.RECTANGLE, RectangleEditor],
|
|
8
|
-
[ShapeType.POLYGON, PolygonEditor]
|
|
7
|
+
[ShapeType.RECTANGLE, RectangleEditor as typeof SvelteComponent],
|
|
8
|
+
[ShapeType.POLYGON, PolygonEditor as typeof SvelteComponent]
|
|
9
9
|
]);
|
|
10
10
|
|
|
11
11
|
export const getEditor = (shape: Shape) => REGISTERED.get(shape.type);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './polygon';
|
|
2
2
|
export * from './rectangle';
|
|
3
3
|
export * from './editorsRegistry';
|
|
4
|
-
export * from './Handle';
|
|
5
4
|
|
|
6
5
|
export { default as Editor } from './Editor.svelte';
|
|
7
|
-
export { default as EditorMount } from './EditorMount.svelte';
|
|
6
|
+
export { default as EditorMount } from './EditorMount.svelte';
|
|
7
|
+
export { default as Handle } from './Handle.svelte';
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { boundsFromPoints } from '../../../model';
|
|
3
|
-
import type { Polygon } from '../../../model';
|
|
3
|
+
import type { Polygon, PolygonGeometry, Shape } from '../../../model';
|
|
4
4
|
import type { Transform } from '../../Transform';
|
|
5
5
|
import { Editor, Handle } from '..';
|
|
6
6
|
|
|
7
7
|
/** Props */
|
|
8
8
|
export let shape: Polygon;
|
|
9
|
-
export let computedStyle: string
|
|
9
|
+
export let computedStyle: string | undefined;
|
|
10
10
|
export let transform: Transform;
|
|
11
11
|
export let viewportScale: number = 1;
|
|
12
12
|
|
|
13
13
|
$: geom = shape.geometry;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const editor = (polygon: Polygon, handle: Handle, delta: [number, number]) => {
|
|
15
|
+
const editor = (polygon: Shape, handle: string, delta: [number, number]) => {
|
|
18
16
|
let points: [number, number][];
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const geom = (polygon.geometry) as PolygonGeometry;
|
|
19
|
+
|
|
20
|
+
if (handle === 'SHAPE') {
|
|
21
|
+
points = geom.points.map(([x, y]) => [x + delta[0], y + delta[1]]);
|
|
22
22
|
} else {
|
|
23
|
-
points =
|
|
24
|
-
handle ===
|
|
23
|
+
points = geom.points.map(([x, y], idx) =>
|
|
24
|
+
handle === `HANDLE-${idx}` ? [x + delta[0], y + delta[1]] : [x, y]
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
<polygon
|
|
47
47
|
class="a9s-outer"
|
|
48
48
|
style={computedStyle ? 'display:none;' : undefined}
|
|
49
|
-
on:pointerdown={grab(
|
|
49
|
+
on:pointerdown={grab('SHAPE')}
|
|
50
50
|
points={geom.points.map(xy => xy.join(',')).join(' ')} />
|
|
51
51
|
|
|
52
52
|
<polygon
|
|
53
53
|
class="a9s-inner a9s-shape-handle"
|
|
54
54
|
style={computedStyle}
|
|
55
|
-
on:pointerdown={grab(
|
|
55
|
+
on:pointerdown={grab('SHAPE')}
|
|
56
56
|
points={geom.points.map(xy => xy.join(',')).join(' ')} />
|
|
57
57
|
|
|
58
58
|
{#each geom.points as point, idx}
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
<Handle
|
|
60
|
+
on:pointerdown={grab(`HANDLE-${idx}`)}
|
|
61
|
+
x={point[0]} y={point[1]}
|
|
62
|
+
scale={viewportScale} />
|
|
63
63
|
{/each}
|
|
64
64
|
</Editor>
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Handle from '../Handle.svelte';
|
|
3
|
+
import type { Rectangle, Shape } from '../../../model';
|
|
3
4
|
import type { Transform } from '../../Transform';
|
|
4
|
-
import { Editor
|
|
5
|
+
import { Editor } from '..';
|
|
5
6
|
|
|
6
7
|
/** Props */
|
|
7
8
|
export let shape: Rectangle;
|
|
8
|
-
export let computedStyle: string
|
|
9
|
+
export let computedStyle: string | undefined;
|
|
9
10
|
export let transform: Transform;
|
|
10
11
|
export let viewportScale: number = 1;
|
|
11
12
|
|
|
12
13
|
$: geom = shape.geometry;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const editor = (rectangle: Rectangle, handle: Handle, delta: [number, number]) => {
|
|
15
|
+
const editor = (rectangle: Shape, handle: string, delta: [number, number]) => {
|
|
17
16
|
const initialBounds = rectangle.geometry.bounds;
|
|
18
17
|
|
|
19
18
|
let [x0, y0] = [initialBounds.minX, initialBounds.minY];
|
|
@@ -21,39 +20,39 @@
|
|
|
21
20
|
|
|
22
21
|
const [dx, dy] = delta;
|
|
23
22
|
|
|
24
|
-
if (handle ===
|
|
23
|
+
if (handle === 'SHAPE') {
|
|
25
24
|
x0 += dx;
|
|
26
25
|
x1 += dx;
|
|
27
26
|
y0 += dy;
|
|
28
27
|
y1 += dy;
|
|
29
28
|
} else {
|
|
30
29
|
switch (handle) {
|
|
31
|
-
case
|
|
32
|
-
case
|
|
33
|
-
case
|
|
30
|
+
case 'TOP':
|
|
31
|
+
case 'TOP_LEFT':
|
|
32
|
+
case 'TOP_RIGHT': {
|
|
34
33
|
y0 += dy;
|
|
35
34
|
break;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
case
|
|
39
|
-
case
|
|
40
|
-
case
|
|
37
|
+
case 'BOTTOM':
|
|
38
|
+
case 'BOTTOM_LEFT':
|
|
39
|
+
case 'BOTTOM_RIGHT': {
|
|
41
40
|
y1 += dy;
|
|
42
41
|
break;
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
switch (handle) {
|
|
47
|
-
case
|
|
48
|
-
case
|
|
49
|
-
case
|
|
46
|
+
case 'LEFT':
|
|
47
|
+
case 'TOP_LEFT':
|
|
48
|
+
case 'BOTTOM_LEFT': {
|
|
50
49
|
x0 += dx;
|
|
51
50
|
break;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
case
|
|
55
|
-
case
|
|
56
|
-
case
|
|
53
|
+
case 'RIGHT':
|
|
54
|
+
case 'TOP_RIGHT':
|
|
55
|
+
case 'BOTTOM_RIGHT': {
|
|
57
56
|
x1 += dx;
|
|
58
57
|
break;
|
|
59
58
|
}
|
|
@@ -92,52 +91,56 @@
|
|
|
92
91
|
<rect
|
|
93
92
|
class="a9s-outer"
|
|
94
93
|
style={computedStyle ? 'display:none;' : undefined}
|
|
95
|
-
on:pointerdown={grab(
|
|
94
|
+
on:pointerdown={grab('SHAPE')}
|
|
96
95
|
x={geom.x} y={geom.y} width={geom.w} height={geom.h} />
|
|
97
96
|
|
|
98
97
|
<rect
|
|
99
98
|
class="a9s-inner a9s-shape-handle"
|
|
100
99
|
style={computedStyle}
|
|
101
|
-
on:pointerdown={grab(
|
|
100
|
+
on:pointerdown={grab('SHAPE')}
|
|
102
101
|
x={geom.x} y={geom.y} width={geom.w} height={geom.h} />
|
|
103
102
|
|
|
104
103
|
<rect
|
|
105
104
|
class="a9s-edge-handle a9s-edge-handle-top"
|
|
106
|
-
on:pointerdown={grab(
|
|
105
|
+
on:pointerdown={grab('TOP')}
|
|
107
106
|
x={geom.x} y={geom.y} height={1} width={geom.w} />
|
|
108
107
|
|
|
109
108
|
<rect
|
|
110
109
|
class="a9s-edge-handle a9s-edge-handle-right"
|
|
111
|
-
on:pointerdown={grab(
|
|
110
|
+
on:pointerdown={grab('RIGHT')}
|
|
112
111
|
x={geom.x + geom.w} y={geom.y} height={geom.h} width={1}/>
|
|
113
112
|
|
|
114
113
|
<rect
|
|
115
114
|
class="a9s-edge-handle a9s-edge-handle-bottom"
|
|
116
|
-
on:pointerdown={grab(
|
|
115
|
+
on:pointerdown={grab('BOTTOM')}
|
|
117
116
|
x={geom.x} y={geom.y + geom.h} height={1} width={geom.w} />
|
|
118
117
|
|
|
119
118
|
<rect
|
|
120
119
|
class="a9s-edge-handle a9s-edge-handle-left"
|
|
121
|
-
on:pointerdown={grab(
|
|
120
|
+
on:pointerdown={grab('LEFT')}
|
|
122
121
|
x={geom.x} y={geom.y} height={geom.h} width={1} />
|
|
123
122
|
|
|
124
|
-
<
|
|
125
|
-
class="a9s-corner-handle
|
|
126
|
-
on:pointerdown={grab(
|
|
127
|
-
x={geom.x
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
123
|
+
<Handle
|
|
124
|
+
class="a9s-corner-handle-topleft"
|
|
125
|
+
on:pointerdown={grab('TOP_LEFT')}
|
|
126
|
+
x={geom.x} y={geom.y}
|
|
127
|
+
scale={viewportScale} />
|
|
128
|
+
|
|
129
|
+
<Handle
|
|
130
|
+
class="a9s-corner-handle-topright"
|
|
131
|
+
on:pointerdown={grab('TOP_RIGHT')}
|
|
132
|
+
x={geom.x + geom.w} y={geom.y}
|
|
133
|
+
scale={viewportScale} />
|
|
133
134
|
|
|
134
|
-
<
|
|
135
|
-
class="a9s-corner-handle
|
|
136
|
-
on:pointerdown={grab(
|
|
137
|
-
x={geom.x + geom.w
|
|
135
|
+
<Handle
|
|
136
|
+
class="a9s-corner-handle-bottomright"
|
|
137
|
+
on:pointerdown={grab('BOTTOM_RIGHT')}
|
|
138
|
+
x={geom.x + geom.w} y={geom.y + geom.h}
|
|
139
|
+
scale={viewportScale} />
|
|
138
140
|
|
|
139
|
-
<
|
|
140
|
-
class="a9s-corner-handle
|
|
141
|
-
on:pointerdown={grab(
|
|
142
|
-
x={geom.x
|
|
141
|
+
<Handle
|
|
142
|
+
class="a9s-corner-handle-bottomleft"
|
|
143
|
+
on:pointerdown={grab('BOTTOM_LEFT')}
|
|
144
|
+
x={geom.x} y={geom.y + geom.h}
|
|
145
|
+
scale={viewportScale} />
|
|
143
146
|
</Editor>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import type {
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DrawingStyleExpression } from '@annotorious/core';
|
|
3
3
|
import type { Geometry, EllipseGeometry, ImageAnnotation } from '../../model';
|
|
4
4
|
import { computeStyle } from '../utils/styling';
|
|
5
5
|
|
|
6
6
|
/** Props */
|
|
7
7
|
export let annotation: ImageAnnotation;
|
|
8
8
|
export let geom: Geometry;
|
|
9
|
-
export let style:
|
|
9
|
+
export let style: DrawingStyleExpression<ImageAnnotation> | undefined;
|
|
10
10
|
|
|
11
11
|
$: computedStyle = computeStyle(annotation, style);
|
|
12
12
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import type {
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DrawingStyleExpression } from '@annotorious/core';
|
|
3
3
|
import type { Geometry, ImageAnnotation, PolygonGeometry } from '../../model';
|
|
4
4
|
import { computeStyle } from '../utils/styling';
|
|
5
5
|
|
|
6
6
|
/** Props **/
|
|
7
7
|
export let annotation: ImageAnnotation;
|
|
8
8
|
export let geom: Geometry;
|
|
9
|
-
export let style:
|
|
9
|
+
export let style: DrawingStyleExpression<ImageAnnotation> | undefined;
|
|
10
10
|
|
|
11
11
|
$: computedStyle = computeStyle(annotation, style);
|
|
12
12
|
|