@annotorious/annotorious 3.0.0-rc.9 → 3.0.1
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 +9 -10
- package/dist/AnnotoriousOpts.d.ts +5 -7
- package/dist/annotation/SVGAnnotationLayer.svelte.d.ts +1 -1
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts +6 -6
- package/dist/annotation/Transform.d.ts +0 -1
- package/dist/annotation/editors/Editor.svelte.d.ts +1 -1
- package/dist/annotation/editors/EditorMount.svelte.d.ts +1 -1
- package/dist/annotation/editors/Handle.svelte.d.ts +1 -0
- package/dist/annotation/editors/editorsRegistry.d.ts +3 -4
- package/dist/annotation/editors/index.d.ts +1 -2
- package/dist/annotation/editors/polygon/PolygonEditor.svelte.d.ts +1 -1
- package/dist/annotation/editors/polygon/index.d.ts +0 -1
- package/dist/annotation/editors/rectangle/RectangleEditor.svelte.d.ts +1 -1
- package/dist/annotation/editors/rectangle/index.d.ts +0 -1
- package/dist/annotation/index.d.ts +0 -1
- package/dist/annotation/shapes/Ellipse.svelte.d.ts +1 -1
- package/dist/annotation/shapes/Polygon.svelte.d.ts +1 -1
- package/dist/annotation/shapes/Rectangle.svelte.d.ts +1 -1
- package/dist/annotation/shapes/index.d.ts +0 -1
- package/dist/annotation/tools/DrawingToolConfig.d.ts +1 -2
- package/dist/annotation/tools/ToolMount.svelte.d.ts +1 -1
- package/dist/annotation/tools/drawingToolsRegistry.d.ts +4 -5
- package/dist/annotation/tools/index.d.ts +0 -1
- package/dist/annotation/tools/polygon/RubberbandPolygon.svelte.d.ts +1 -1
- package/dist/annotation/tools/polygon/index.d.ts +0 -1
- package/dist/annotation/tools/rectangle/RubberbandRectangle.svelte.d.ts +1 -1
- package/dist/annotation/tools/rectangle/index.d.ts +0 -1
- package/dist/annotation/utils/index.d.ts +0 -1
- package/dist/annotation/utils/math.d.ts +0 -1
- package/dist/annotation/utils/responsive.d.ts +1 -2
- package/dist/annotation/utils/styling.d.ts +3 -4
- package/dist/annotation/utils/touch.d.ts +0 -1
- package/dist/annotorious.css +1 -1
- package/dist/annotorious.es.js +2538 -2061
- 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 -2
- package/dist/keyboardCommands.d.ts +2 -2
- package/dist/model/core/ImageAnnotation.d.ts +4 -3
- package/dist/model/core/Shape.d.ts +1 -2
- package/dist/model/core/ellipse/Ellipse.d.ts +1 -2
- package/dist/model/core/ellipse/ellipseUtils.d.ts +0 -1
- package/dist/model/core/ellipse/index.d.ts +0 -1
- package/dist/model/core/index.d.ts +0 -1
- package/dist/model/core/polygon/Polygon.d.ts +1 -2
- package/dist/model/core/polygon/index.d.ts +0 -1
- package/dist/model/core/polygon/polygonUtils.d.ts +0 -1
- package/dist/model/core/rectangle/Rectangle.d.ts +1 -2
- package/dist/model/core/rectangle/index.d.ts +0 -1
- package/dist/model/core/rectangle/rectangleUtils.d.ts +2 -3
- package/dist/model/core/shapeUtils.d.ts +2 -6
- package/dist/model/index.d.ts +0 -1
- package/dist/model/w3c/W3CImageAnnotation.d.ts +10 -0
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts +11 -7
- package/dist/model/w3c/fragment/FragmentSelector.d.ts +2 -4
- package/dist/model/w3c/fragment/index.d.ts +0 -1
- package/dist/model/w3c/index.d.ts +1 -1
- package/dist/model/w3c/svg/SVG.d.ts +0 -1
- package/dist/model/w3c/svg/SVGSelector.d.ts +2 -4
- package/dist/model/w3c/svg/index.d.ts +0 -1
- package/dist/state/ImageAnnotationStore.d.ts +6 -7
- package/dist/state/ImageAnnotatorState.d.ts +8 -9
- package/dist/state/index.d.ts +0 -1
- package/dist/state/spatialTree.d.ts +7 -7
- package/dist/themes/index.d.ts +0 -1
- package/dist/themes/smart/index.d.ts +0 -1
- package/dist/themes/smart/setTheme.d.ts +1 -2
- package/package.json +16 -17
- package/src/Annotorious.css +13 -5
- package/src/Annotorious.ts +42 -26
- package/src/AnnotoriousOpts.ts +13 -17
- package/src/annotation/SVGAnnotationLayer.svelte +77 -42
- package/src/annotation/SVGAnnotationLayerPointerEvent.ts +8 -9
- 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 +4 -4
- package/src/annotation/shapes/Polygon.svelte +4 -4
- package/src/annotation/shapes/Rectangle.svelte +4 -4
- package/src/annotation/tools/ToolMount.svelte +3 -3
- package/src/annotation/tools/drawingToolsRegistry.ts +2 -1
- package/src/annotation/tools/polygon/RubberbandPolygon.svelte +36 -11
- package/src/annotation/tools/rectangle/RubberbandRectangle.svelte +27 -11
- package/src/annotation/utils/responsive.ts +1 -1
- package/src/annotation/utils/styling.ts +18 -9
- package/src/annotation/utils/touch.ts +9 -1
- package/src/index.ts +1 -3
- package/src/keyboardCommands.ts +13 -5
- package/src/model/core/ImageAnnotation.ts +12 -1
- package/src/model/w3c/W3CImageAnnotation.ts +17 -0
- package/src/model/w3c/W3CImageFormatAdapter.ts +79 -32
- 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/ImageAnnotationStore.ts +5 -5
- package/src/state/ImageAnnotatorState.ts +19 -19
- package/src/state/spatialTree.ts +23 -11
- package/src/themes/dark/index.css +3 -3
- package/src/themes/light/index.css +2 -2
- package/src/themes/smart/setTheme.ts +2 -2
- package/dist/Annotorious.d.ts.map +0 -1
- package/dist/AnnotoriousOpts.d.ts.map +0 -1
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts.map +0 -1
- package/dist/annotation/Transform.d.ts.map +0 -1
- package/dist/annotation/editors/Handle.d.ts +0 -14
- package/dist/annotation/editors/Handle.d.ts.map +0 -1
- package/dist/annotation/editors/editorsRegistry.d.ts.map +0 -1
- package/dist/annotation/editors/index.d.ts.map +0 -1
- package/dist/annotation/editors/polygon/index.d.ts.map +0 -1
- package/dist/annotation/editors/rectangle/index.d.ts.map +0 -1
- package/dist/annotation/index.d.ts.map +0 -1
- package/dist/annotation/shapes/index.d.ts.map +0 -1
- package/dist/annotation/tools/DrawingToolConfig.d.ts.map +0 -1
- package/dist/annotation/tools/drawingToolsRegistry.d.ts.map +0 -1
- package/dist/annotation/tools/index.d.ts.map +0 -1
- package/dist/annotation/tools/polygon/index.d.ts.map +0 -1
- package/dist/annotation/tools/rectangle/index.d.ts.map +0 -1
- package/dist/annotation/utils/index.d.ts.map +0 -1
- package/dist/annotation/utils/math.d.ts.map +0 -1
- package/dist/annotation/utils/responsive.d.ts.map +0 -1
- package/dist/annotation/utils/styling.d.ts.map +0 -1
- package/dist/annotation/utils/touch.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/keyboardCommands.d.ts.map +0 -1
- package/dist/model/core/ImageAnnotation.d.ts.map +0 -1
- package/dist/model/core/Shape.d.ts.map +0 -1
- package/dist/model/core/ellipse/Ellipse.d.ts.map +0 -1
- package/dist/model/core/ellipse/ellipseUtils.d.ts.map +0 -1
- package/dist/model/core/ellipse/index.d.ts.map +0 -1
- package/dist/model/core/index.d.ts.map +0 -1
- package/dist/model/core/polygon/Polygon.d.ts.map +0 -1
- package/dist/model/core/polygon/index.d.ts.map +0 -1
- package/dist/model/core/polygon/polygonUtils.d.ts.map +0 -1
- package/dist/model/core/rectangle/Rectangle.d.ts.map +0 -1
- package/dist/model/core/rectangle/index.d.ts.map +0 -1
- package/dist/model/core/rectangle/rectangleUtils.d.ts.map +0 -1
- package/dist/model/core/shapeUtils.d.ts.map +0 -1
- package/dist/model/index.d.ts.map +0 -1
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts.map +0 -1
- package/dist/model/w3c/fragment/FragmentSelector.d.ts.map +0 -1
- package/dist/model/w3c/fragment/index.d.ts.map +0 -1
- package/dist/model/w3c/index.d.ts.map +0 -1
- package/dist/model/w3c/svg/SVG.d.ts.map +0 -1
- package/dist/model/w3c/svg/SVGSelector.d.ts.map +0 -1
- package/dist/model/w3c/svg/index.d.ts.map +0 -1
- package/dist/state/ImageAnnotationStore.d.ts.map +0 -1
- package/dist/state/ImageAnnotatorState.d.ts.map +0 -1
- package/dist/state/index.d.ts.map +0 -1
- package/dist/state/spatialTree.d.ts.map +0 -1
- package/dist/themes/index.d.ts.map +0 -1
- package/dist/themes/smart/index.d.ts.map +0 -1
- package/dist/themes/smart/setTheme.d.ts.map +0 -1
- package/src/annotation/editors/Handle.ts +0 -21
|
@@ -1,19 +1,19 @@
|
|
|
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
|
|
|
13
13
|
const { cx, cy, rx, ry } = geom as EllipseGeometry;
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<g data-id={annotation.id}>
|
|
16
|
+
<g class="a9s-annotation" data-id={annotation.id}>
|
|
17
17
|
<ellipse
|
|
18
18
|
class="a9s-outer"
|
|
19
19
|
style={computedStyle ? 'display:none;' : undefined}
|
|
@@ -1,19 +1,19 @@
|
|
|
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
|
|
|
13
13
|
const { points } = geom as PolygonGeometry;
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<g data-id={annotation.id}>
|
|
16
|
+
<g class="a9s-annotation" data-id={annotation.id}>
|
|
17
17
|
<polygon
|
|
18
18
|
class="a9s-outer"
|
|
19
19
|
style={computedStyle ? 'display:none;' : undefined}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import type {
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DrawingStyleExpression } from '@annotorious/core';
|
|
3
3
|
import type { Geometry, ImageAnnotation, RectangleGeometry } 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
|
|
|
13
13
|
$: ({ x, y, w, h } = geom as RectangleGeometry);
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<g data-id={annotation.id}>
|
|
16
|
+
<g class="a9s-annotation" data-id={annotation.id}>
|
|
17
17
|
<rect
|
|
18
18
|
class="a9s-outer"
|
|
19
19
|
style={computedStyle ? 'display:none;' : undefined}
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
|
|
24
24
|
const cleanup: Function[] = [];
|
|
25
25
|
|
|
26
|
-
const addEventListener = (name:
|
|
27
|
-
svg
|
|
28
|
-
cleanup.push(() => svg
|
|
26
|
+
const addEventListener = (name: keyof SVGSVGElementEventMap, handler: EventListenerOrEventListenerObject, capture?: boolean) => {
|
|
27
|
+
svg?.addEventListener(name, handler, capture);
|
|
28
|
+
cleanup.push(() => svg?.removeEventListener(name, handler, capture));
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
toolComponent = new tool({
|
|
@@ -9,10 +9,11 @@ export type DrawingToolOpts = {
|
|
|
9
9
|
|
|
10
10
|
drawingMode?: DrawingMode;
|
|
11
11
|
|
|
12
|
-
[key: string]:
|
|
12
|
+
[key: string]: any;
|
|
13
13
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
// @ts-ignore
|
|
16
17
|
const REGISTERED = new Map<DrawingTool, { tool: typeof SvelteComponent, opts?: DrawingToolOpts }>([
|
|
17
18
|
['rectangle', { tool: RubberbandRectangle }],
|
|
18
19
|
['polygon', { tool: RubberbandPolygon }]
|
|
@@ -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,15 +17,24 @@
|
|
|
17
17
|
|
|
18
18
|
let points: [number, number][] = [];
|
|
19
19
|
|
|
20
|
-
let cursor: [number, number]
|
|
20
|
+
let cursor: [number, number] | undefined;
|
|
21
|
+
|
|
22
|
+
// Keep track of the user keeping the finger
|
|
23
|
+
// in place. Long pauses will be interpreted like a
|
|
24
|
+
// double click and close the shape.
|
|
25
|
+
let touchPauseTimer: number | undefined;
|
|
21
26
|
|
|
22
27
|
let isClosable: boolean = false;
|
|
23
28
|
|
|
24
29
|
const CLOSE_DISTANCE = 20;
|
|
25
30
|
|
|
31
|
+
const TOUCH_PAUSE_LIMIT = 1500;
|
|
32
|
+
|
|
26
33
|
$: handleSize = 10 / viewportScale;
|
|
27
34
|
|
|
28
|
-
const onPointerDown = (
|
|
35
|
+
const onPointerDown = (event: Event) => {
|
|
36
|
+
const evt = event as PointerEvent;
|
|
37
|
+
|
|
29
38
|
// Note that the event itself is ephemeral!
|
|
30
39
|
const { timeStamp, offsetX, offsetY } = evt;
|
|
31
40
|
lastPointerDown = { timeStamp, offsetX, offsetY };
|
|
@@ -40,7 +49,11 @@
|
|
|
40
49
|
}
|
|
41
50
|
}
|
|
42
51
|
|
|
43
|
-
const onPointerMove = (
|
|
52
|
+
const onPointerMove = (event: Event) => {
|
|
53
|
+
const evt = event as PointerEvent;
|
|
54
|
+
|
|
55
|
+
if (touchPauseTimer) clearTimeout(touchPauseTimer);
|
|
56
|
+
|
|
44
57
|
if (points.length > 0) {
|
|
45
58
|
cursor = transform.elementToImage(evt.offsetX, evt.offsetY);
|
|
46
59
|
|
|
@@ -48,10 +61,20 @@
|
|
|
48
61
|
const d = distance(cursor, points[0]) * viewportScale;
|
|
49
62
|
isClosable = d < CLOSE_DISTANCE;
|
|
50
63
|
}
|
|
64
|
+
|
|
65
|
+
if (evt.pointerType === 'touch') {
|
|
66
|
+
touchPauseTimer = setTimeout(() => {
|
|
67
|
+
onDblClick();
|
|
68
|
+
}, TOUCH_PAUSE_LIMIT);
|
|
69
|
+
}
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
72
|
|
|
54
|
-
const onPointerUp = (
|
|
73
|
+
const onPointerUp = (event: Event) => {
|
|
74
|
+
const evt = event as PointerEvent;
|
|
75
|
+
|
|
76
|
+
if (touchPauseTimer) clearTimeout(touchPauseTimer);
|
|
77
|
+
|
|
55
78
|
if (drawingMode === 'click') {
|
|
56
79
|
const timeDifference = evt.timeStamp - lastPointerDown.timeStamp;
|
|
57
80
|
|
|
@@ -71,17 +94,17 @@
|
|
|
71
94
|
|
|
72
95
|
cursor = point;
|
|
73
96
|
} else {
|
|
74
|
-
points.push(cursor);
|
|
97
|
+
points.push(cursor!);
|
|
75
98
|
}
|
|
76
99
|
} else {
|
|
77
100
|
// Require minimum drag of 4px
|
|
78
101
|
if (points.length === 1) {
|
|
79
|
-
const dist = distance(points[0], cursor);
|
|
102
|
+
const dist = distance(points[0], cursor!);
|
|
80
103
|
|
|
81
104
|
if (dist <= 4) {
|
|
82
105
|
// Cancel
|
|
83
106
|
points = [];
|
|
84
|
-
cursor =
|
|
107
|
+
cursor = undefined;
|
|
85
108
|
|
|
86
109
|
return;
|
|
87
110
|
}
|
|
@@ -93,12 +116,14 @@
|
|
|
93
116
|
if (isClosable) {
|
|
94
117
|
stopDrawing();
|
|
95
118
|
} else {
|
|
96
|
-
points.push(cursor);
|
|
119
|
+
points.push(cursor!);
|
|
97
120
|
}
|
|
98
121
|
}
|
|
99
122
|
}
|
|
100
123
|
|
|
101
124
|
const onDblClick = () => {
|
|
125
|
+
if (!cursor) return;
|
|
126
|
+
|
|
102
127
|
// Require min 3 points (incl. cursor) and minimum
|
|
103
128
|
// polygon area
|
|
104
129
|
const p = [...points, cursor];
|
|
@@ -114,7 +139,7 @@
|
|
|
114
139
|
const area = computeArea(shape);
|
|
115
140
|
if (area > 4) {
|
|
116
141
|
points = [];
|
|
117
|
-
cursor =
|
|
142
|
+
cursor = undefined;
|
|
118
143
|
|
|
119
144
|
dispatch('create', shape);
|
|
120
145
|
}
|
|
@@ -130,7 +155,7 @@
|
|
|
130
155
|
}
|
|
131
156
|
|
|
132
157
|
points = [];
|
|
133
|
-
cursor =
|
|
158
|
+
cursor = undefined;
|
|
134
159
|
|
|
135
160
|
dispatch('create', shape);
|
|
136
161
|
}
|
|
@@ -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') {
|
|
@@ -52,7 +58,17 @@
|
|
|
52
58
|
if (timeDifference > 300)
|
|
53
59
|
return;
|
|
54
60
|
|
|
55
|
-
|
|
61
|
+
// This statement caused a weird bug on OSD: when starting
|
|
62
|
+
// to draw with a quick drag (<300ms), OSD got stuck in mouseNav
|
|
63
|
+
// mode. The image still moved with the mouse cursor, even though
|
|
64
|
+
// button was no longer pressed.
|
|
65
|
+
// I'm commenting out this statement as a fix. But there must have
|
|
66
|
+
// been a reason I put it here in the first place. Keep an eye ou
|
|
67
|
+
// for regressions.
|
|
68
|
+
//
|
|
69
|
+
// And if you are ever tempted to un-comment the statement: beware!
|
|
70
|
+
|
|
71
|
+
// evt.stopPropagation();
|
|
56
72
|
|
|
57
73
|
if (origin) {
|
|
58
74
|
stopDrawing();
|
|
@@ -71,8 +87,8 @@
|
|
|
71
87
|
evt.stopPropagation();
|
|
72
88
|
stopDrawing();
|
|
73
89
|
} else {
|
|
74
|
-
origin =
|
|
75
|
-
anchor =
|
|
90
|
+
origin = undefined;
|
|
91
|
+
anchor = undefined;
|
|
76
92
|
}
|
|
77
93
|
}
|
|
78
94
|
}
|
|
@@ -96,8 +112,8 @@
|
|
|
96
112
|
dispatch('create', shape);
|
|
97
113
|
}
|
|
98
114
|
|
|
99
|
-
origin =
|
|
100
|
-
anchor =
|
|
115
|
+
origin = undefined;
|
|
116
|
+
anchor = undefined;
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
onMount(() => {
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DrawingStyleExpression } from '@annotorious/core';
|
|
2
2
|
import type { ImageAnnotation } from '../../model';
|
|
3
3
|
|
|
4
|
-
export const computeStyle = (
|
|
4
|
+
export const computeStyle = (
|
|
5
|
+
annotation: ImageAnnotation,
|
|
6
|
+
style?: DrawingStyleExpression<ImageAnnotation>
|
|
7
|
+
) => {
|
|
5
8
|
const computed = typeof style === 'function' ? style(annotation) : style;
|
|
6
9
|
|
|
7
10
|
if (computed) {
|
|
8
|
-
const { fill, fillOpacity } = computed;
|
|
11
|
+
const { fill, fillOpacity, stroke, strokeWidth, strokeOpacity } = computed;
|
|
9
12
|
|
|
10
13
|
let css = '';
|
|
11
|
-
|
|
12
|
-
if (fill)
|
|
13
|
-
css += `fill:${fill}
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
if (fill) {
|
|
16
|
+
css += `fill:${fill};`;
|
|
17
|
+
css += `fill-opacity:${fillOpacity || '0.25'};`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (stroke) {
|
|
21
|
+
css += `stroke:${stroke};`;
|
|
22
|
+
css += `stroke-width:${strokeWidth || '1'};`;
|
|
23
|
+
css += `stroke-opacity:${strokeOpacity || '1'};`;
|
|
24
|
+
}
|
|
16
25
|
|
|
17
26
|
return css;
|
|
18
27
|
}
|
|
19
|
-
}
|
|
28
|
+
};
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
export const isTouch =
|
|
1
|
+
export const isTouch = (() => {
|
|
2
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined')
|
|
3
|
+
return false;
|
|
4
|
+
|
|
5
|
+
return 'ontouchstart' in window ||
|
|
6
|
+
navigator.maxTouchPoints > 0 ||
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
navigator.msMaxTouchPoints > 0;
|
|
9
|
+
})();
|
package/src/index.ts
CHANGED
|
@@ -24,7 +24,6 @@ export type {
|
|
|
24
24
|
LifecycleEvents,
|
|
25
25
|
ParseResult,
|
|
26
26
|
PresentUser,
|
|
27
|
-
Purpose,
|
|
28
27
|
Selection,
|
|
29
28
|
SelectionState,
|
|
30
29
|
Store,
|
|
@@ -33,6 +32,5 @@ export type {
|
|
|
33
32
|
User,
|
|
34
33
|
W3CAnnotation,
|
|
35
34
|
W3CAnnotationBody,
|
|
36
|
-
W3CAnnotationTarget
|
|
37
|
-
W3CSelector
|
|
35
|
+
W3CAnnotationTarget
|
|
38
36
|
} from '@annotorious/core';
|
package/src/keyboardCommands.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Annotation, UndoStack } from '@annotorious/core';
|
|
2
2
|
|
|
3
|
-
const isMac =
|
|
3
|
+
export const isMac = (() => {
|
|
4
|
+
if (typeof navigator === 'undefined') return false;
|
|
5
|
+
|
|
6
|
+
return navigator.userAgent.indexOf('Mac OS X') !== -1;
|
|
7
|
+
})();
|
|
4
8
|
|
|
5
9
|
export const initKeyboardCommands = <T extends Annotation>(
|
|
6
10
|
undoStack: UndoStack<T>,
|
|
@@ -9,15 +13,19 @@ export const initKeyboardCommands = <T extends Annotation>(
|
|
|
9
13
|
|
|
10
14
|
const el = container || document;
|
|
11
15
|
|
|
12
|
-
const onWinKeyDown = (
|
|
13
|
-
|
|
16
|
+
const onWinKeyDown = (evt: Event) => {
|
|
17
|
+
const event = evt as KeyboardEvent;
|
|
18
|
+
|
|
19
|
+
if (event.key === 'z' && event.ctrlKey) {
|
|
14
20
|
undoStack.undo();
|
|
15
|
-
} else if (event.key === '
|
|
21
|
+
} else if (event.key === 'y' && event.ctrlKey) {
|
|
16
22
|
undoStack.redo()
|
|
17
23
|
}
|
|
18
24
|
};
|
|
19
25
|
|
|
20
|
-
const onMacKeyDown = (
|
|
26
|
+
const onMacKeyDown = (evt: Event) => {
|
|
27
|
+
const event = evt as KeyboardEvent;
|
|
28
|
+
|
|
21
29
|
if (event.key === 'z' && event.metaKey) {
|
|
22
30
|
if (event.shiftKey) {
|
|
23
31
|
undoStack.redo()
|
|
@@ -11,4 +11,15 @@ export interface ImageAnnotationTarget extends AnnotationTarget {
|
|
|
11
11
|
|
|
12
12
|
selector: Shape
|
|
13
13
|
|
|
14
|
-
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const isImageAnnotation = <T extends Annotation>(
|
|
17
|
+
a: T | ImageAnnotation
|
|
18
|
+
): a is ImageAnnotation =>
|
|
19
|
+
isImageAnnotationTarget(a.target);
|
|
20
|
+
|
|
21
|
+
export const isImageAnnotationTarget = <T extends AnnotationTarget>(
|
|
22
|
+
t: T | ImageAnnotationTarget
|
|
23
|
+
): t is ImageAnnotationTarget =>
|
|
24
|
+
t?.annotation !== undefined &&
|
|
25
|
+
(t as ImageAnnotationTarget)?.selector?.geometry?.bounds !== undefined;
|
|
@@ -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,86 +1,133 @@
|
|
|
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>;
|
|
13
|
+
|
|
14
|
+
export interface W3CImageFormatAdapterOpts {
|
|
15
|
+
|
|
16
|
+
strict: boolean;
|
|
17
|
+
|
|
18
|
+
invertY: boolean;
|
|
19
|
+
|
|
20
|
+
}
|
|
12
21
|
|
|
13
22
|
export const W3CImageFormat = (
|
|
14
23
|
source: string,
|
|
15
|
-
|
|
24
|
+
opts: W3CImageFormatAdapterOpts = { strict: true, invertY: false }
|
|
16
25
|
): W3CImageFormatAdapter => {
|
|
17
26
|
|
|
18
27
|
const parse = (serialized: W3CAnnotation) =>
|
|
19
|
-
parseW3CImageAnnotation(serialized,
|
|
28
|
+
parseW3CImageAnnotation(serialized, opts);
|
|
20
29
|
|
|
21
30
|
const serialize = (annotation: ImageAnnotation) =>
|
|
22
|
-
serializeW3CImageAnnotation(annotation, source);
|
|
31
|
+
serializeW3CImageAnnotation(annotation, source, opts);
|
|
23
32
|
|
|
24
33
|
return { parse, serialize }
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export const parseW3CImageAnnotation = (
|
|
28
37
|
annotation: W3CAnnotation,
|
|
29
|
-
|
|
38
|
+
opts: W3CImageFormatAdapterOpts = { strict: true, invertY: false }
|
|
30
39
|
): ParseResult<ImageAnnotation> => {
|
|
31
40
|
const annotationId = annotation.id || uuidv4();
|
|
32
41
|
|
|
33
|
-
const {
|
|
42
|
+
const {
|
|
43
|
+
creator,
|
|
44
|
+
created,
|
|
45
|
+
modified,
|
|
46
|
+
body,
|
|
47
|
+
...rest
|
|
48
|
+
} = annotation;
|
|
34
49
|
|
|
35
|
-
const bodies = parseW3CBodies(body, annotationId);
|
|
50
|
+
const bodies = parseW3CBodies(body || [], annotationId);
|
|
36
51
|
|
|
37
|
-
const
|
|
52
|
+
const w3cTarget = Array.isArray(annotation.target)
|
|
53
|
+
? annotation.target[0] : annotation.target;
|
|
38
54
|
|
|
39
|
-
const w3cSelector = Array.isArray(
|
|
55
|
+
const w3cSelector = Array.isArray(w3cTarget.selector)
|
|
56
|
+
? w3cTarget.selector[0] : w3cTarget.selector;
|
|
40
57
|
|
|
41
58
|
const selector =
|
|
42
|
-
w3cSelector
|
|
43
|
-
parseFragmentSelector(w3cSelector as FragmentSelector, invertY) :
|
|
44
|
-
w3cSelector
|
|
59
|
+
w3cSelector?.type === 'FragmentSelector' ?
|
|
60
|
+
parseFragmentSelector(w3cSelector as FragmentSelector, opts.invertY) :
|
|
61
|
+
w3cSelector?.type === 'SvgSelector' ?
|
|
45
62
|
parseSVGSelector(w3cSelector as SVGSelector) : undefined;
|
|
46
63
|
|
|
47
|
-
return selector ? {
|
|
64
|
+
return (selector || !opts.strict) ? {
|
|
48
65
|
parsed: {
|
|
49
66
|
...rest,
|
|
50
67
|
id: annotationId,
|
|
51
68
|
bodies,
|
|
52
69
|
target: {
|
|
53
|
-
|
|
70
|
+
created: created ? new Date(created) : undefined,
|
|
71
|
+
creator: parseW3CUser(creator),
|
|
72
|
+
updated: modified ? new Date(modified) : undefined,
|
|
73
|
+
...(Array.isArray(rest.target) ? rest.target[0] : rest.target),
|
|
54
74
|
annotation: annotationId,
|
|
55
|
-
selector
|
|
75
|
+
selector: selector || w3cSelector
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
} : {
|
|
59
|
-
error: Error(`
|
|
79
|
+
error: Error(`Invalid selector: ${JSON.stringify(w3cSelector)}`)
|
|
60
80
|
};
|
|
61
|
-
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
export const serializeW3CImageAnnotation = (
|
|
65
84
|
annotation: ImageAnnotation,
|
|
66
|
-
source: string
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
source: string,
|
|
86
|
+
opts: W3CImageFormatAdapterOpts = { strict: true, invertY: false }
|
|
87
|
+
): W3CImageAnnotation => {
|
|
88
|
+
const {
|
|
89
|
+
selector,
|
|
90
|
+
creator,
|
|
91
|
+
created,
|
|
92
|
+
updated,
|
|
93
|
+
updatedBy, // Excluded from serialization
|
|
94
|
+
...rest
|
|
95
|
+
} = annotation.target;
|
|
96
|
+
|
|
97
|
+
let w3cSelector: FragmentSelector | SVGSelector | unknown;
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
w3cSelector = selector.type == ShapeType.RECTANGLE ?
|
|
101
|
+
serializeFragmentSelector(selector.geometry as RectangleGeometry) :
|
|
102
|
+
serializeSVGSelector(selector);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (opts.strict)
|
|
105
|
+
throw error;
|
|
106
|
+
else
|
|
107
|
+
w3cSelector = selector;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const serialized = {
|
|
76
111
|
...annotation,
|
|
77
112
|
'@context': 'http://www.w3.org/ns/anno.jsonld',
|
|
78
113
|
id: annotation.id,
|
|
79
114
|
type: 'Annotation',
|
|
80
115
|
body: serializeW3CBodies(annotation.bodies),
|
|
116
|
+
created: created?.toISOString(),
|
|
117
|
+
creator,
|
|
118
|
+
modified: updated?.toISOString(),
|
|
81
119
|
target: {
|
|
120
|
+
...rest,
|
|
82
121
|
source,
|
|
83
|
-
selector
|
|
122
|
+
selector: w3cSelector
|
|
84
123
|
}
|
|
85
|
-
};
|
|
86
|
-
|
|
124
|
+
} as W3CImageAnnotation;
|
|
125
|
+
|
|
126
|
+
// Remove core properties that should not appear in the W3C annotation
|
|
127
|
+
delete serialized.bodies;
|
|
128
|
+
|
|
129
|
+
if ('annotation' in serialized.target)
|
|
130
|
+
delete serialized.target.annotation;
|
|
131
|
+
|
|
132
|
+
return serialized;
|
|
133
|
+
}
|
|
@@ -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
|
|