@annotorious/annotorious 3.0.0-rc.15 → 3.0.0-rc.17
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 +1 -1
- package/dist/Annotorious.d.ts.map +1 -1
- package/dist/AnnotoriousOpts.d.ts +2 -3
- package/dist/AnnotoriousOpts.d.ts.map +1 -1
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts.map +1 -1
- package/dist/annotation/editors/editorsRegistry.d.ts +1 -1
- package/dist/annotation/editors/editorsRegistry.d.ts.map +1 -1
- package/dist/annotation/tools/drawingToolsRegistry.d.ts +4 -4
- package/dist/annotation/tools/drawingToolsRegistry.d.ts.map +1 -1
- package/dist/annotation/utils/responsive.d.ts +2 -1
- package/dist/annotation/utils/responsive.d.ts.map +1 -1
- package/dist/annotation/utils/styling.d.ts +1 -1
- package/dist/annotation/utils/styling.d.ts.map +1 -1
- package/dist/annotorious.es.js +1598 -1503
- 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 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/keyboardCommands.d.ts.map +1 -1
- package/dist/model/w3c/W3CImageAnnotation.d.ts +11 -0
- package/dist/model/w3c/W3CImageAnnotation.d.ts.map +1 -0
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts +3 -2
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts.map +1 -1
- package/dist/model/w3c/fragment/FragmentSelector.d.ts +1 -2
- 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 +1 -2
- package/dist/model/w3c/svg/SVGSelector.d.ts.map +1 -1
- package/dist/state/spatialTree.d.ts +1 -1
- package/dist/state/spatialTree.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/Annotorious.ts +14 -8
- package/src/AnnotoriousOpts.ts +7 -7
- package/src/annotation/SVGAnnotationLayer.svelte +18 -14
- package/src/annotation/SVGAnnotationLayerPointerEvent.ts +1 -2
- package/src/annotation/Transform.ts +1 -1
- package/src/annotation/editors/Editor.svelte +5 -5
- package/src/annotation/editors/EditorMount.svelte +1 -1
- package/src/annotation/editors/polygon/PolygonEditor.svelte +8 -6
- package/src/annotation/editors/rectangle/RectangleEditor.svelte +4 -4
- package/src/annotation/shapes/Ellipse.svelte +2 -2
- package/src/annotation/shapes/Polygon.svelte +2 -2
- package/src/annotation/shapes/Rectangle.svelte +2 -2
- package/src/annotation/tools/ToolMount.svelte +3 -3
- package/src/annotation/tools/drawingToolsRegistry.ts +2 -1
- package/src/annotation/tools/polygon/RubberbandPolygon.svelte +18 -12
- package/src/annotation/tools/rectangle/RubberbandRectangle.svelte +16 -10
- package/src/annotation/utils/responsive.ts +1 -1
- package/src/index.ts +1 -2
- package/src/keyboardCommands.ts +6 -2
- package/src/model/w3c/W3CImageAnnotation.ts +17 -0
- package/src/model/w3c/W3CImageFormatAdapter.ts +42 -19
- 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 +3 -3
- package/src/state/spatialTree.ts +3 -2
- package/src/themes/smart/setTheme.ts +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { onMount, createEventDispatcher } from 'svelte';
|
|
3
3
|
import type { DrawingMode } from '../../../AnnotoriousOpts';
|
|
4
4
|
import { boundsFromPoints, computeArea, ShapeType, type Polygon } from '../../../model';
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
let points: [number, number][] = [];
|
|
19
19
|
|
|
20
|
-
let cursor: [number, number]
|
|
20
|
+
let cursor: [number, number] | undefined;
|
|
21
21
|
|
|
22
22
|
let isClosable: boolean = false;
|
|
23
23
|
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
|
|
26
26
|
$: handleSize = 10 / viewportScale;
|
|
27
27
|
|
|
28
|
-
const onPointerDown = (
|
|
28
|
+
const onPointerDown = (event: Event) => {
|
|
29
|
+
const evt = event as PointerEvent;
|
|
30
|
+
|
|
29
31
|
// Note that the event itself is ephemeral!
|
|
30
32
|
const { timeStamp, offsetX, offsetY } = evt;
|
|
31
33
|
lastPointerDown = { timeStamp, offsetX, offsetY };
|
|
@@ -40,7 +42,9 @@
|
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
const onPointerMove = (
|
|
45
|
+
const onPointerMove = (event: Event) => {
|
|
46
|
+
const evt = event as PointerEvent;
|
|
47
|
+
|
|
44
48
|
if (points.length > 0) {
|
|
45
49
|
cursor = transform.elementToImage(evt.offsetX, evt.offsetY);
|
|
46
50
|
|
|
@@ -51,7 +55,9 @@
|
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
const onPointerUp = (
|
|
58
|
+
const onPointerUp = (event: Event) => {
|
|
59
|
+
const evt = event as PointerEvent;
|
|
60
|
+
|
|
55
61
|
if (drawingMode === 'click') {
|
|
56
62
|
const timeDifference = evt.timeStamp - lastPointerDown.timeStamp;
|
|
57
63
|
|
|
@@ -71,17 +77,17 @@
|
|
|
71
77
|
|
|
72
78
|
cursor = point;
|
|
73
79
|
} else {
|
|
74
|
-
points.push(cursor);
|
|
80
|
+
points.push(cursor!);
|
|
75
81
|
}
|
|
76
82
|
} else {
|
|
77
83
|
// Require minimum drag of 4px
|
|
78
84
|
if (points.length === 1) {
|
|
79
|
-
const dist = distance(points[0], cursor);
|
|
85
|
+
const dist = distance(points[0], cursor!);
|
|
80
86
|
|
|
81
87
|
if (dist <= 4) {
|
|
82
88
|
// Cancel
|
|
83
89
|
points = [];
|
|
84
|
-
cursor =
|
|
90
|
+
cursor = undefined;
|
|
85
91
|
|
|
86
92
|
return;
|
|
87
93
|
}
|
|
@@ -93,7 +99,7 @@
|
|
|
93
99
|
if (isClosable) {
|
|
94
100
|
stopDrawing();
|
|
95
101
|
} else {
|
|
96
|
-
points.push(cursor);
|
|
102
|
+
points.push(cursor!);
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
105
|
}
|
|
@@ -101,7 +107,7 @@
|
|
|
101
107
|
const onDblClick = () => {
|
|
102
108
|
// Require min 3 points (incl. cursor) and minimum
|
|
103
109
|
// polygon area
|
|
104
|
-
const p = [...points, cursor];
|
|
110
|
+
const p = [...points, cursor!];
|
|
105
111
|
|
|
106
112
|
const shape: Polygon = {
|
|
107
113
|
type: ShapeType.POLYGON,
|
|
@@ -114,7 +120,7 @@
|
|
|
114
120
|
const area = computeArea(shape);
|
|
115
121
|
if (area > 4) {
|
|
116
122
|
points = [];
|
|
117
|
-
cursor =
|
|
123
|
+
cursor = undefined;
|
|
118
124
|
|
|
119
125
|
dispatch('create', shape);
|
|
120
126
|
}
|
|
@@ -130,7 +136,7 @@
|
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
points = [];
|
|
133
|
-
cursor =
|
|
139
|
+
cursor = undefined;
|
|
134
140
|
|
|
135
141
|
dispatch('create', shape);
|
|
136
142
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { createEventDispatcher, onMount } from 'svelte';
|
|
3
3
|
import type { DrawingMode } from '../../../AnnotoriousOpts';
|
|
4
4
|
import { ShapeType, type Rectangle } from '../../../model';
|
|
@@ -13,13 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
let lastPointerDown: number;
|
|
15
15
|
|
|
16
|
-
let origin: [x: number, y: number];
|
|
16
|
+
let origin: [x: number, y: number] | undefined;
|
|
17
17
|
|
|
18
|
-
let anchor: [number, number];
|
|
18
|
+
let anchor: [number, number] | undefined;
|
|
19
19
|
|
|
20
20
|
let x: number, y: number, w: number, h: number;
|
|
21
21
|
|
|
22
|
-
const onPointerDown = (
|
|
22
|
+
const onPointerDown = (event: Event) => {
|
|
23
|
+
const evt = event as PointerEvent;
|
|
24
|
+
|
|
23
25
|
lastPointerDown = performance.now();
|
|
24
26
|
|
|
25
27
|
if (drawingMode === 'drag') {
|
|
@@ -33,7 +35,9 @@
|
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
const onPointerMove = (
|
|
38
|
+
const onPointerMove = (event: Event) => {
|
|
39
|
+
const evt = event as PointerEvent;
|
|
40
|
+
|
|
37
41
|
if (origin) {
|
|
38
42
|
anchor = transform.elementToImage(evt.offsetX, evt.offsetY);
|
|
39
43
|
|
|
@@ -44,7 +48,9 @@
|
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
const onPointerUp = (
|
|
51
|
+
const onPointerUp = (event: Event) => {
|
|
52
|
+
const evt = event as PointerEvent;
|
|
53
|
+
|
|
48
54
|
const timeDifference = performance.now() - lastPointerDown;
|
|
49
55
|
|
|
50
56
|
if (drawingMode === 'click') {
|
|
@@ -71,8 +77,8 @@
|
|
|
71
77
|
evt.stopPropagation();
|
|
72
78
|
stopDrawing();
|
|
73
79
|
} else {
|
|
74
|
-
origin =
|
|
75
|
-
anchor =
|
|
80
|
+
origin = undefined;
|
|
81
|
+
anchor = undefined;
|
|
76
82
|
}
|
|
77
83
|
}
|
|
78
84
|
}
|
|
@@ -96,8 +102,8 @@
|
|
|
96
102
|
dispatch('create', shape);
|
|
97
103
|
}
|
|
98
104
|
|
|
99
|
-
origin =
|
|
100
|
-
anchor =
|
|
105
|
+
origin = undefined;
|
|
106
|
+
anchor = undefined;
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
onMount(() => {
|
package/src/index.ts
CHANGED
package/src/keyboardCommands.ts
CHANGED
|
@@ -9,7 +9,9 @@ export const initKeyboardCommands = <T extends Annotation>(
|
|
|
9
9
|
|
|
10
10
|
const el = container || document;
|
|
11
11
|
|
|
12
|
-
const onWinKeyDown = (
|
|
12
|
+
const onWinKeyDown = (evt: Event) => {
|
|
13
|
+
const event = evt as KeyboardEvent;
|
|
14
|
+
|
|
13
15
|
if (event.key === 'Z' && event.ctrlKey) {
|
|
14
16
|
undoStack.undo();
|
|
15
17
|
} else if (event.key === 'Y' && event.ctrlKey) {
|
|
@@ -17,7 +19,9 @@ export const initKeyboardCommands = <T extends Annotation>(
|
|
|
17
19
|
}
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
const onMacKeyDown = (
|
|
22
|
+
const onMacKeyDown = (evt: Event) => {
|
|
23
|
+
const event = evt as KeyboardEvent;
|
|
24
|
+
|
|
21
25
|
if (event.key === 'z' && event.metaKey) {
|
|
22
26
|
if (event.shiftKey) {
|
|
23
27
|
undoStack.redo()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { W3CAnnotation, W3CAnnotationTarget } from '@annotorious/core';
|
|
2
|
+
import type { FragmentSelector } from './fragment';
|
|
3
|
+
import type { SVGSelector } from './svg';
|
|
4
|
+
|
|
5
|
+
export interface W3CImageAnnotation extends W3CAnnotation {
|
|
6
|
+
|
|
7
|
+
target: W3CImageAnnotationTarget | W3CImageAnnotationTarget[];
|
|
8
|
+
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface W3CImageAnnotationTarget extends W3CAnnotationTarget {
|
|
12
|
+
|
|
13
|
+
selector: W3CImageSelector | W3CImageSelector[];
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type W3CImageSelector = FragmentSelector | SVGSelector;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
-
import { parseW3CBodies, serializeW3CBodies } from '@annotorious/core';
|
|
2
|
+
import { parseW3CUser, parseW3CBodies, serializeW3CBodies } from '@annotorious/core';
|
|
3
3
|
import type { FormatAdapter, ParseResult, W3CAnnotation } from '@annotorious/core';
|
|
4
4
|
import { ShapeType } from '../core';
|
|
5
5
|
import type { ImageAnnotation, RectangleGeometry } from '../core';
|
|
6
|
-
import type {
|
|
6
|
+
import type {FragmentSelector } from './fragment';
|
|
7
7
|
import { parseFragmentSelector, serializeFragmentSelector } from './fragment';
|
|
8
8
|
import type { SVGSelector } from './svg';
|
|
9
9
|
import { parseSVGSelector, serializeSVGSelector } from './svg';
|
|
10
|
+
import type { W3CImageAnnotation } from './W3CImageAnnotation';
|
|
10
11
|
|
|
11
|
-
export type W3CImageFormatAdapter = FormatAdapter<ImageAnnotation,
|
|
12
|
+
export type W3CImageFormatAdapter = FormatAdapter<ImageAnnotation, W3CImageAnnotation>;
|
|
12
13
|
|
|
13
14
|
export const W3CImageFormat = (
|
|
14
15
|
source: string,
|
|
@@ -30,18 +31,26 @@ export const parseW3CImageAnnotation = (
|
|
|
30
31
|
): ParseResult<ImageAnnotation> => {
|
|
31
32
|
const annotationId = annotation.id || uuidv4();
|
|
32
33
|
|
|
33
|
-
const {
|
|
34
|
+
const {
|
|
35
|
+
creator,
|
|
36
|
+
created,
|
|
37
|
+
modified,
|
|
38
|
+
body,
|
|
39
|
+
...rest
|
|
40
|
+
} = annotation;
|
|
34
41
|
|
|
35
42
|
const bodies = parseW3CBodies(body, annotationId);
|
|
36
43
|
|
|
37
|
-
const
|
|
44
|
+
const w3cTarget = Array.isArray(annotation.target)
|
|
45
|
+
? annotation.target[0] : annotation.target;
|
|
38
46
|
|
|
39
|
-
const w3cSelector = Array.isArray(
|
|
47
|
+
const w3cSelector = Array.isArray(w3cTarget.selector)
|
|
48
|
+
? w3cTarget.selector[0] : w3cTarget.selector;
|
|
40
49
|
|
|
41
50
|
const selector =
|
|
42
|
-
w3cSelector
|
|
51
|
+
w3cSelector?.type === 'FragmentSelector' ?
|
|
43
52
|
parseFragmentSelector(w3cSelector as FragmentSelector, invertY) :
|
|
44
|
-
w3cSelector
|
|
53
|
+
w3cSelector?.type === 'SvgSelector' ?
|
|
45
54
|
parseSVGSelector(w3cSelector as SVGSelector) : undefined;
|
|
46
55
|
|
|
47
56
|
return selector ? {
|
|
@@ -50,13 +59,16 @@ export const parseW3CImageAnnotation = (
|
|
|
50
59
|
id: annotationId,
|
|
51
60
|
bodies,
|
|
52
61
|
target: {
|
|
62
|
+
created: created ? new Date(created) : undefined,
|
|
63
|
+
creator: parseW3CUser(creator),
|
|
64
|
+
updated: modified ? new Date(modified) : undefined,
|
|
53
65
|
...rest.target,
|
|
54
66
|
annotation: annotationId,
|
|
55
67
|
selector
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
70
|
} : {
|
|
59
|
-
error: Error(`
|
|
71
|
+
error: Error(`Invalid selector: ${JSON.stringify(w3cSelector)}`)
|
|
60
72
|
};
|
|
61
73
|
|
|
62
74
|
}
|
|
@@ -64,13 +76,20 @@ export const parseW3CImageAnnotation = (
|
|
|
64
76
|
export const serializeW3CImageAnnotation = (
|
|
65
77
|
annotation: ImageAnnotation,
|
|
66
78
|
source: string
|
|
67
|
-
):
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
): W3CImageAnnotation => {
|
|
80
|
+
const {
|
|
81
|
+
selector,
|
|
82
|
+
creator,
|
|
83
|
+
created,
|
|
84
|
+
updated,
|
|
85
|
+
updatedBy, // Excluded from serialization
|
|
86
|
+
...rest
|
|
87
|
+
} = annotation.target;
|
|
88
|
+
|
|
89
|
+
const w3CSelector =
|
|
90
|
+
selector.type == ShapeType.RECTANGLE ?
|
|
91
|
+
serializeFragmentSelector(selector.geometry as RectangleGeometry) :
|
|
92
|
+
serializeSVGSelector(selector);
|
|
74
93
|
|
|
75
94
|
return {
|
|
76
95
|
...annotation,
|
|
@@ -78,9 +97,13 @@ export const serializeW3CImageAnnotation = (
|
|
|
78
97
|
id: annotation.id,
|
|
79
98
|
type: 'Annotation',
|
|
80
99
|
body: serializeW3CBodies(annotation.bodies),
|
|
100
|
+
created: created?.toISOString(),
|
|
101
|
+
creator,
|
|
102
|
+
modified: updated?.toISOString(),
|
|
81
103
|
target: {
|
|
104
|
+
...rest,
|
|
82
105
|
source,
|
|
83
|
-
selector
|
|
106
|
+
selector: w3CSelector
|
|
84
107
|
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import type { W3CSelector } from '@annotorious/core';
|
|
2
|
-
import { ShapeType } from '../../core';
|
|
3
1
|
import type { Rectangle, RectangleGeometry } from '../../core';
|
|
2
|
+
import { ShapeType } from '../../core';
|
|
4
3
|
|
|
5
|
-
export interface FragmentSelector
|
|
4
|
+
export interface FragmentSelector {
|
|
6
5
|
|
|
7
6
|
type: 'FragmentSelector';
|
|
8
7
|
|
|
9
8
|
conformsTo: 'http://www.w3.org/TR/media-frags/',
|
|
10
9
|
|
|
11
10
|
value: string;
|
|
12
|
-
|
|
11
|
+
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
export const parseFragmentSelector = (
|
|
@@ -46,7 +45,7 @@ export const parseFragmentSelector = (
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
|
-
}
|
|
48
|
+
}
|
|
50
49
|
|
|
51
50
|
export const serializeFragmentSelector = (geometry: RectangleGeometry): FragmentSelector => {
|
|
52
51
|
const { x, y, w, h } = geometry;
|
|
@@ -56,4 +55,4 @@ export const serializeFragmentSelector = (geometry: RectangleGeometry): Fragment
|
|
|
56
55
|
conformsTo: 'http://www.w3.org/TR/media-frags/',
|
|
57
56
|
value: `xywh=pixel:${x},${y},${w},${h}`
|
|
58
57
|
};
|
|
59
|
-
}
|
|
58
|
+
}
|
package/src/model/w3c/index.ts
CHANGED
package/src/model/w3c/svg/SVG.ts
CHANGED
|
@@ -13,8 +13,7 @@ export const sanitize = (doc: Element | Document) => {
|
|
|
13
13
|
// Remove script tags
|
|
14
14
|
const scripts = doc.getElementsByTagName('script');
|
|
15
15
|
|
|
16
|
-
Array.from(scripts).reverse().forEach(el =>
|
|
17
|
-
el.parentNode.removeChild(el));
|
|
16
|
+
Array.from(scripts).reverse().forEach(el => el.parentNode!.removeChild(el));
|
|
18
17
|
|
|
19
18
|
Array.from(doc.querySelectorAll('*')).forEach(cleanEl);
|
|
20
19
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type { W3CSelector } from '@annotorious/core';
|
|
2
|
-
import { boundsFromPoints, ShapeType } from '../../core';
|
|
3
1
|
import type { Ellipse, EllipseGeometry, Polygon, PolygonGeometry, Shape } from '../../core';
|
|
4
|
-
import {
|
|
2
|
+
import { boundsFromPoints, ShapeType } from '../../core';
|
|
3
|
+
import { insertSVGNamespace, sanitize, SVG_NAMESPACE } from './SVG';
|
|
5
4
|
|
|
6
|
-
export interface SVGSelector
|
|
5
|
+
export interface SVGSelector {
|
|
7
6
|
|
|
8
7
|
type: 'SvgSelector';
|
|
9
8
|
|
|
10
9
|
value: string;
|
|
11
|
-
|
|
10
|
+
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
const parseSVGXML = (value: string): Element => {
|
|
@@ -29,9 +28,6 @@ const parseSVGXML = (value: string): Element => {
|
|
|
29
28
|
|
|
30
29
|
const parseSVGPolygon = (value: string): Polygon => {
|
|
31
30
|
const [a, b, str] = value.match(/(<polygon points=["|'])([^("|')]*)/) || [];
|
|
32
|
-
|
|
33
|
-
if (!str) return;
|
|
34
|
-
|
|
35
31
|
const points = str.split(' ').map((p) => p.split(',').map(parseFloat));
|
|
36
32
|
|
|
37
33
|
return {
|
|
@@ -46,10 +42,10 @@ const parseSVGPolygon = (value: string): Polygon => {
|
|
|
46
42
|
const parseSVGEllipse = (value: string): Ellipse => {
|
|
47
43
|
const doc = parseSVGXML(value);
|
|
48
44
|
|
|
49
|
-
const cx = parseFloat(doc.getAttribute('cx'));
|
|
50
|
-
const cy = parseFloat(doc.getAttribute('cy'));
|
|
51
|
-
const rx = parseFloat(doc.getAttribute('rx'));
|
|
52
|
-
const ry = parseFloat(doc.getAttribute('ry'));
|
|
45
|
+
const cx = parseFloat(doc.getAttribute('cx')!);
|
|
46
|
+
const cy = parseFloat(doc.getAttribute('cy')!);
|
|
47
|
+
const rx = parseFloat(doc.getAttribute('rx')!);
|
|
48
|
+
const ry = parseFloat(doc.getAttribute('ry')!);
|
|
53
49
|
|
|
54
50
|
const bounds = {
|
|
55
51
|
minX: cx - rx,
|
|
@@ -77,10 +73,12 @@ export const parseSVGSelector = <T extends Shape>(valueOrSelector: SVGSelector |
|
|
|
77
73
|
return parseSVGPolygon(value) as unknown as T;
|
|
78
74
|
else if (value.includes('<ellipse '))
|
|
79
75
|
return parseSVGEllipse(value) as unknown as T;
|
|
76
|
+
else
|
|
77
|
+
throw 'Unsupported SVG shape: ' + value;
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
export const serializeSVGSelector = (shape: Shape): SVGSelector => {
|
|
83
|
-
let value: string;
|
|
81
|
+
let value: string | undefined;
|
|
84
82
|
|
|
85
83
|
if (shape.type === ShapeType.POLYGON) {
|
|
86
84
|
const geom = shape.geometry as PolygonGeometry;
|
|
@@ -44,11 +44,11 @@ export const createImageAnnotatorState = <E extends unknown>(
|
|
|
44
44
|
const viewport = createViewportState();
|
|
45
45
|
|
|
46
46
|
store.observe(({ changes }) => {
|
|
47
|
-
tree.set(changes.created.map(a => a.target as ImageAnnotationTarget), false);
|
|
47
|
+
tree.set((changes.created || []).map(a => a.target as ImageAnnotationTarget), false);
|
|
48
48
|
|
|
49
|
-
changes.deleted.forEach(a => tree.remove(a.target as ImageAnnotationTarget));
|
|
49
|
+
(changes.deleted || []).forEach(a => tree.remove(a.target as ImageAnnotationTarget));
|
|
50
50
|
|
|
51
|
-
changes.updated.forEach(({ oldValue, newValue }) =>
|
|
51
|
+
(changes.updated || []).forEach(({ oldValue, newValue }) =>
|
|
52
52
|
tree.update(oldValue.target, newValue.target));
|
|
53
53
|
});
|
|
54
54
|
|
package/src/state/spatialTree.ts
CHANGED
|
@@ -40,7 +40,8 @@ export const createSpatialTree = () => {
|
|
|
40
40
|
|
|
41
41
|
const remove = (target: ImageAnnotationTarget) => {
|
|
42
42
|
const item = index.get(target.annotation);
|
|
43
|
-
|
|
43
|
+
if (item)
|
|
44
|
+
tree.remove(item);
|
|
44
45
|
index.delete(target.annotation);
|
|
45
46
|
};
|
|
46
47
|
|
|
@@ -62,7 +63,7 @@ export const createSpatialTree = () => {
|
|
|
62
63
|
tree.load(indexedTargets);
|
|
63
64
|
};
|
|
64
65
|
|
|
65
|
-
const getAt = (x: number, y: number): ImageAnnotationTarget |
|
|
66
|
+
const getAt = (x: number, y: number): ImageAnnotationTarget | undefined => {
|
|
66
67
|
const idxHits = tree.search({
|
|
67
68
|
minX: x,
|
|
68
69
|
minY: y,
|
|
@@ -8,7 +8,7 @@ export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
|
|
|
8
8
|
|
|
9
9
|
if (imageOrCanvas.nodeName === 'CANVAS') {
|
|
10
10
|
canvas = imageOrCanvas as HTMLCanvasElement;
|
|
11
|
-
context = canvas.getContext('2d', { willReadFrequently: true })
|
|
11
|
+
context = canvas.getContext('2d', { willReadFrequently: true })!;
|
|
12
12
|
} else {
|
|
13
13
|
const img = imageOrCanvas as HTMLImageElement;
|
|
14
14
|
// Copy image to in-memory canvas for processing
|
|
@@ -16,7 +16,7 @@ export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
|
|
|
16
16
|
canvas.width = img.width;
|
|
17
17
|
canvas.height = img.height;
|
|
18
18
|
|
|
19
|
-
context = canvas.getContext('2d', { willReadFrequently: true })
|
|
19
|
+
context = canvas.getContext('2d', { willReadFrequently: true })!;
|
|
20
20
|
context.drawImage(img, 0, 0, img.width, img.height);
|
|
21
21
|
}
|
|
22
22
|
|