@annotorious/annotorious 3.0.0-rc.1 → 3.0.0-rc.11
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 +3 -1
- package/dist/Annotorious.d.ts.map +1 -1
- package/dist/AnnotoriousOpts.d.ts +2 -0
- package/dist/AnnotoriousOpts.d.ts.map +1 -1
- package/dist/annotation/Transform.d.ts.map +1 -1
- package/dist/annotorious.es.js +1909 -1864
- 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 +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/keyboardCommands.d.ts +5 -0
- package/dist/keyboardCommands.d.ts.map +1 -0
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts.map +1 -1
- package/dist/themes/smart/setTheme.d.ts +3 -1
- package/dist/themes/smart/setTheme.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/Annotorious.ts +42 -33
- package/src/AnnotoriousOpts.ts +6 -1
- package/src/annotation/SVGAnnotationLayer.svelte +5 -3
- package/src/annotation/Transform.ts +5 -3
- package/src/annotation/editors/EditorMount.svelte +1 -1
- package/src/annotation/shapes/Rectangle.svelte +1 -1
- package/src/annotation/tools/polygon/RubberbandPolygon.svelte +23 -22
- package/src/annotation/tools/rectangle/RubberbandRectangle.svelte +1 -6
- package/src/index.ts +26 -8
- package/src/keyboardCommands.ts +46 -0
- package/src/model/w3c/W3CImageFormatAdapter.ts +6 -3
- package/src/themes/smart/setTheme.ts +8 -4
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,6 @@ export * from './themes';
|
|
|
5
5
|
export * from './annotation/tools';
|
|
6
6
|
export * from './Annotorious';
|
|
7
7
|
export * from './AnnotoriousOpts';
|
|
8
|
-
export * from '
|
|
9
|
-
export
|
|
10
|
-
export * from '@annotorious/core/src/utils';
|
|
11
|
-
export type { HoverState, Selection, SelectionState, Store, StoreObserver } from '@annotorious/core/src/state';
|
|
8
|
+
export * from './keyboardCommands';
|
|
9
|
+
export type { Annotation, AnnotationBody, AnnotationTarget, Annotator, AnnotatorState, Appearance, AppearanceProvider, Color, DrawingStyle, Filter, FormatAdapter, HoverState, LifecycleEvents, ParseResult, PresentUser, Purpose, Selection, SelectionState, Store, StoreChangeEvent, StoreObserver, User, W3CAnnotation, W3CAnnotationBody, W3CAnnotationTarget, W3CSelector } from '@annotorious/core';
|
|
12
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,YAAY,EACZ,MAAM,EACN,aAAa,EACb,UAAU,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,OAAO,EACP,SAAS,EACT,cAAc,EACd,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,IAAI,EACJ,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACZ,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboardCommands.d.ts","sourceRoot":"","sources":["../src/keyboardCommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI/D,eAAO,MAAM,oBAAoB,8DAEnB,OAAO;;CAuCpB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"W3CImageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../src/model/w3c/W3CImageFormatAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAMlE,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAElF,eAAO,MAAM,cAAc,WACjB,MAAM,YACL,OAAO,0BAUjB,CAAA;AAED,eAAO,MAAM,uBAAuB,eACtB,aAAa,YAChB,OAAO,KACf,YAAY,eAAe,
|
|
1
|
+
{"version":3,"file":"W3CImageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../src/model/w3c/W3CImageFormatAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAMlE,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAElF,eAAO,MAAM,cAAc,WACjB,MAAM,YACL,OAAO,0BAUjB,CAAA;AAED,eAAO,MAAM,uBAAuB,eACtB,aAAa,YAChB,OAAO,KACf,YAAY,eAAe,CAgC7B,CAAA;AAED,eAAO,MAAM,2BAA2B,eAC1B,eAAe,UACnB,MAAM,KACb,aAmBF,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Theme } from '../../AnnotoriousOpts';
|
|
1
2
|
export declare const sampleBrightness: (imageOrCanvas: HTMLElement) => number;
|
|
2
|
-
export declare const
|
|
3
|
+
export declare const detectTheme: (imageOrCanvas: HTMLElement) => "dark" | "light";
|
|
4
|
+
export declare const setTheme: (imageOrCanvas: HTMLElement, container: HTMLElement, theme: Theme) => void;
|
|
3
5
|
//# sourceMappingURL=setTheme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setTheme.d.ts","sourceRoot":"","sources":["../../../src/themes/smart/setTheme.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,kBAAmB,WAAW,WAmC1D,CAAA;AAED,eAAO,MAAM,QAAQ,kBAAmB,WAAW,aAAa,WAAW,
|
|
1
|
+
{"version":3,"file":"setTheme.d.ts","sourceRoot":"","sources":["../../../src/themes/smart/setTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,eAAO,MAAM,gBAAgB,kBAAmB,WAAW,WAmC1D,CAAA;AAED,eAAO,MAAM,WAAW,kBAAmB,WAAW,qBAOrD,CAAA;AAED,eAAO,MAAM,QAAQ,kBAAmB,WAAW,aAAa,WAAW,SAAS,KAAK,SACI,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@annotorious/annotorious",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.11",
|
|
4
4
|
"description": "Add image annotation functionality to any web page with a few lines of JavaScript",
|
|
5
5
|
"author": "Rainer Simon",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -33,9 +33,7 @@
|
|
|
33
33
|
"require": "./dist/annotorious.js"
|
|
34
34
|
},
|
|
35
35
|
"./annotorious.css": "./dist/annotorious.css",
|
|
36
|
-
"./src": "./src/index.ts"
|
|
37
|
-
"./src/annotation": "./src/annotation/index.ts",
|
|
38
|
-
"./src/model": "./src/model/index.ts"
|
|
36
|
+
"./src": "./src/index.ts"
|
|
39
37
|
},
|
|
40
38
|
"devDependencies": {
|
|
41
39
|
"@sveltejs/vite-plugin-svelte": "^2.4.6",
|
|
@@ -48,6 +46,9 @@
|
|
|
48
46
|
"vite-plugin-dts": "^3.6.0",
|
|
49
47
|
"vitest": "^0.34.6"
|
|
50
48
|
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@annotorious/core": "*"
|
|
51
|
+
},
|
|
51
52
|
"dependencies": {
|
|
52
53
|
"rbush": "^3.0.1",
|
|
53
54
|
"uuid": "^9.0.1"
|
package/src/Annotorious.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { SvelteComponent } from 'svelte';
|
|
2
|
-
import type { Annotator, DrawingStyle, User } from '@annotorious/core';
|
|
3
|
-
import { createAnonymousGuest, createBaseAnnotator, createLifecyleObserver } from '@annotorious/core';
|
|
2
|
+
import type { Annotator, DrawingStyle, Filter, User } from '@annotorious/core';
|
|
3
|
+
import { createAnonymousGuest, createBaseAnnotator, createLifecyleObserver, createUndoStack } from '@annotorious/core';
|
|
4
4
|
import { registerEditor } from './annotation/editors';
|
|
5
5
|
import { getTool, registerTool, listDrawingTools, type DrawingTool } from './annotation/tools';
|
|
6
6
|
import { SVGAnnotationLayer } from './annotation';
|
|
7
7
|
import type { DrawingToolOpts, SVGAnnotationLayerPointerEvent } from './annotation';
|
|
8
8
|
import type { ImageAnnotation, ShapeType } from './model';
|
|
9
9
|
import { createSvelteImageAnnotatorState } from './state';
|
|
10
|
-
import { setTheme } from './themes';
|
|
11
|
-
import { fillDefaults } from './AnnotoriousOpts';
|
|
10
|
+
import { setTheme as _setTheme } from './themes';
|
|
11
|
+
import { fillDefaults, type Theme } from './AnnotoriousOpts';
|
|
12
12
|
import type { AnnotoriousOpts } from './AnnotoriousOpts';
|
|
13
|
+
import { initKeyboardCommands } from './keyboardCommands';
|
|
13
14
|
|
|
14
15
|
import './Annotorious.css';
|
|
15
16
|
import './themes/dark/index.css';
|
|
@@ -23,10 +24,12 @@ export interface ImageAnnotator<E extends unknown = ImageAnnotation> extends Ann
|
|
|
23
24
|
|
|
24
25
|
registerShapeEditor(shapeType: ShapeType, editor: typeof SvelteComponent): void;
|
|
25
26
|
|
|
26
|
-
setDrawingTool(
|
|
27
|
+
setDrawingTool(name: DrawingTool): void;
|
|
27
28
|
|
|
28
29
|
setDrawingEnabled(enabled: boolean): void;
|
|
29
30
|
|
|
31
|
+
setTheme(theme: Theme): void;
|
|
32
|
+
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
@@ -44,14 +47,13 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
44
47
|
|
|
45
48
|
const state = createSvelteImageAnnotatorState(opts);
|
|
46
49
|
|
|
47
|
-
const {
|
|
50
|
+
const { selection, store } = state;
|
|
48
51
|
|
|
49
|
-
const
|
|
50
|
-
store, selection, hover, undefined, opts.adapter, opts.autoSave);
|
|
52
|
+
const undoStack = createUndoStack(store);
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const lifecycle = createLifecyleObserver<ImageAnnotation, E>(
|
|
55
|
+
state, undoStack, opts.adapter, opts.autoSave
|
|
56
|
+
);
|
|
55
57
|
|
|
56
58
|
// We'll wrap the image in a container DIV.
|
|
57
59
|
const container = document.createElement('DIV');
|
|
@@ -64,7 +66,11 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
64
66
|
img.parentNode.insertBefore(container, img);
|
|
65
67
|
container.appendChild(img);
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
const keyboardCommands = initKeyboardCommands(undoStack);
|
|
70
|
+
|
|
71
|
+
let currentUser: User = createAnonymousGuest();
|
|
72
|
+
|
|
73
|
+
_setTheme(img, container, opts.theme);
|
|
68
74
|
|
|
69
75
|
const annotationLayer = new SVGAnnotationLayer({
|
|
70
76
|
target: container,
|
|
@@ -73,7 +79,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
73
79
|
image: img,
|
|
74
80
|
preferredDrawingMode: opts.drawingMode,
|
|
75
81
|
state,
|
|
76
|
-
style,
|
|
82
|
+
style: opts.style,
|
|
77
83
|
user: currentUser
|
|
78
84
|
}
|
|
79
85
|
});
|
|
@@ -91,12 +97,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
91
97
|
/******++++++*************/
|
|
92
98
|
|
|
93
99
|
// Most of the external API functions are covered in the base annotator
|
|
94
|
-
const base = createBaseAnnotator<ImageAnnotation, E>(
|
|
95
|
-
|
|
96
|
-
const setStyle = (drawingStyle: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) | undefined) => {
|
|
97
|
-
style = drawingStyle;
|
|
98
|
-
annotationLayer.$set({ style });
|
|
99
|
-
}
|
|
100
|
+
const base = createBaseAnnotator<ImageAnnotation, E>(state, undoStack, opts.adapter);
|
|
100
101
|
|
|
101
102
|
const destroy = () => {
|
|
102
103
|
// Destroy Svelte annotation layer
|
|
@@ -105,6 +106,10 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
105
106
|
// Unwrap the image
|
|
106
107
|
container.parentNode.insertBefore(img, container);
|
|
107
108
|
container.parentNode.removeChild(container);
|
|
109
|
+
|
|
110
|
+
// Other cleanup actions
|
|
111
|
+
keyboardCommands.destroy();
|
|
112
|
+
undoStack.destroy();
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
const getUser = () => currentUser;
|
|
@@ -115,23 +120,27 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
115
120
|
const registerShapeEditor = (shapeType: ShapeType, editor: typeof SvelteComponent) =>
|
|
116
121
|
registerEditor(shapeType, editor);
|
|
117
122
|
|
|
118
|
-
const setDrawingTool = (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
const setDrawingTool = (name: DrawingTool) => {
|
|
124
|
+
// Validate that the tool exists
|
|
125
|
+
const toolSpec = getTool(name);
|
|
126
|
+
if (!toolSpec)
|
|
127
|
+
throw `No drawing tool named ${name}`;
|
|
128
|
+
|
|
129
|
+
annotationLayer.$set({ toolName: name })
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
const setDrawingEnabled = (enabled: boolean) =>
|
|
125
133
|
annotationLayer.$set({ drawingEnabled: enabled });
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
selection.setSelected(arg);
|
|
130
|
-
} else {
|
|
131
|
-
selection.clear();
|
|
132
|
-
}
|
|
134
|
+
|
|
135
|
+
const setFilter = (filter: Filter) => {
|
|
136
|
+
console.warn('Filter not implemented yet');
|
|
133
137
|
}
|
|
134
138
|
|
|
139
|
+
const setStyle = (style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) | undefined) =>
|
|
140
|
+
annotationLayer.$set({ style });
|
|
141
|
+
|
|
142
|
+
const setTheme = (theme: Theme) => _setTheme(img, container, theme);
|
|
143
|
+
|
|
135
144
|
const setUser = (user: User) => {
|
|
136
145
|
currentUser = user;
|
|
137
146
|
annotationLayer.$set({ user });
|
|
@@ -139,8 +148,6 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
139
148
|
|
|
140
149
|
return {
|
|
141
150
|
...base,
|
|
142
|
-
get style() { return style },
|
|
143
|
-
set style(s: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) | undefined) { setStyle(s) },
|
|
144
151
|
destroy,
|
|
145
152
|
getUser,
|
|
146
153
|
listDrawingTools,
|
|
@@ -150,7 +157,9 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
|
|
|
150
157
|
registerShapeEditor,
|
|
151
158
|
setDrawingEnabled,
|
|
152
159
|
setDrawingTool,
|
|
153
|
-
|
|
160
|
+
setFilter,
|
|
161
|
+
setStyle,
|
|
162
|
+
setTheme,
|
|
154
163
|
setUser,
|
|
155
164
|
state
|
|
156
165
|
}
|
package/src/AnnotoriousOpts.ts
CHANGED
|
@@ -18,10 +18,14 @@ export interface AnnotoriousOpts<I extends Annotation = ImageAnnotation, E exten
|
|
|
18
18
|
|
|
19
19
|
style?: DrawingStyle | ((annotation: I) => DrawingStyle);
|
|
20
20
|
|
|
21
|
+
theme?: Theme;
|
|
22
|
+
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export type DrawingMode = 'click' | 'drag';
|
|
24
26
|
|
|
27
|
+
export type Theme = 'dark' | 'light' | 'auto';
|
|
28
|
+
|
|
25
29
|
export const fillDefaults = <I extends ImageAnnotation = ImageAnnotation, E extends unknown = ImageAnnotation> (
|
|
26
30
|
opts: AnnotoriousOpts<I, E>
|
|
27
31
|
): AnnotoriousOpts<I, E> => {
|
|
@@ -30,7 +34,8 @@ export const fillDefaults = <I extends ImageAnnotation = ImageAnnotation, E exte
|
|
|
30
34
|
...opts,
|
|
31
35
|
drawingEnabled: opts.drawingEnabled === undefined ? true : opts.drawingEnabled,
|
|
32
36
|
drawingMode: opts.drawingMode || 'drag',
|
|
33
|
-
pointerSelectAction: opts.pointerSelectAction || PointerSelectAction.EDIT
|
|
37
|
+
pointerSelectAction: opts.pointerSelectAction || PointerSelectAction.EDIT,
|
|
38
|
+
theme: opts.theme || 'light'
|
|
34
39
|
};
|
|
35
40
|
|
|
36
41
|
};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { ImageAnnotation, Shape} from '../model';
|
|
7
7
|
import { 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
12
|
import { addEventListeners } from './SVGAnnotationLayerPointerEvent';
|
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
export let preferredDrawingMode: DrawingMode;
|
|
20
20
|
export let state: SvelteImageAnnotatorState;
|
|
21
21
|
export let style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) = undefined;
|
|
22
|
-
export let
|
|
22
|
+
export let toolName: string = listDrawingTools().length > 0 ? listDrawingTools()[0] : undefined;
|
|
23
23
|
export let user: User;
|
|
24
24
|
|
|
25
|
+
$: ({ tool, opts } = getTool(toolName));
|
|
26
|
+
|
|
25
27
|
$: drawingMode = opts?.drawingMode || preferredDrawingMode;
|
|
26
28
|
|
|
27
29
|
/** Drawing tool layer **/
|
|
@@ -154,7 +156,7 @@
|
|
|
154
156
|
{/key}
|
|
155
157
|
{/each}
|
|
156
158
|
{:else if (tool && drawingEnabled)}
|
|
157
|
-
{#key
|
|
159
|
+
{#key toolName}
|
|
158
160
|
<ToolMount
|
|
159
161
|
target={drawingEl}
|
|
160
162
|
tool={tool}
|
|
@@ -13,11 +13,13 @@ export const IdentityTransform: Transform = {
|
|
|
13
13
|
export const createSVGTransform = (svg: SVGSVGElement): Transform => ({
|
|
14
14
|
|
|
15
15
|
elementToImage: (offsetX: number, offsetY: number) => {
|
|
16
|
+
const bbox = svg.getBoundingClientRect();
|
|
17
|
+
|
|
16
18
|
const pt = svg.createSVGPoint();
|
|
17
|
-
pt.x = offsetX;
|
|
18
|
-
pt.y = offsetY;
|
|
19
|
+
pt.x = offsetX + bbox.x;
|
|
20
|
+
pt.y = offsetY + bbox.y;
|
|
19
21
|
|
|
20
|
-
const { x, y } = pt.matrixTransform(svg.
|
|
22
|
+
const { x, y } = pt.matrixTransform(svg.getScreenCTM().inverse());
|
|
21
23
|
return [x, y];
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
|
|
20
20
|
$: computedStyle = computeStyle(annotation, style);
|
|
21
21
|
|
|
22
|
+
$: if (annotation) editorComponent?.$set({ shape: annotation.target.selector });
|
|
22
23
|
$: if (editorComponent) editorComponent.$set({ transform });
|
|
23
|
-
|
|
24
24
|
$: if (editorComponent) editorComponent.$set({ viewportScale });
|
|
25
25
|
|
|
26
26
|
onMount(() => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script type="ts">
|
|
2
2
|
import { onMount, createEventDispatcher } from 'svelte';
|
|
3
3
|
import type { DrawingMode } from '../../../AnnotoriousOpts';
|
|
4
|
-
import { boundsFromPoints, ShapeType, type Polygon } from '../../../model';
|
|
4
|
+
import { boundsFromPoints, computeArea, ShapeType, type Polygon } from '../../../model';
|
|
5
5
|
import { distance } from '../../utils';
|
|
6
6
|
import type { Transform } from '../..';
|
|
7
7
|
|
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
export let transform: Transform;
|
|
14
14
|
export let viewportScale = 1;
|
|
15
15
|
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
let lastPointerDown: number;
|
|
16
|
+
let lastPointerDown: { timeStamp: number, offsetX: number, offsetY: number };
|
|
19
17
|
|
|
20
18
|
let points: [number, number][] = [];
|
|
21
19
|
|
|
@@ -28,7 +26,9 @@
|
|
|
28
26
|
$: handleSize = 10 / viewportScale;
|
|
29
27
|
|
|
30
28
|
const onPointerDown = (evt: PointerEvent) => {
|
|
31
|
-
|
|
29
|
+
// Note that the event itself is ephemeral!
|
|
30
|
+
const { timeStamp, offsetX, offsetY } = evt;
|
|
31
|
+
lastPointerDown = { timeStamp, offsetX, offsetY };
|
|
32
32
|
|
|
33
33
|
if (drawingMode === 'drag') {
|
|
34
34
|
if (points.length === 0) {
|
|
@@ -52,14 +52,15 @@
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const onPointerUp = (evt: PointerEvent) => {
|
|
55
|
-
const timeDifference = performance.now() - lastPointerDown;
|
|
56
|
-
|
|
57
55
|
if (drawingMode === 'click') {
|
|
58
|
-
|
|
59
|
-
if (timeDifference > 300)
|
|
60
|
-
return;
|
|
56
|
+
const timeDifference = evt.timeStamp - lastPointerDown.timeStamp;
|
|
61
57
|
|
|
62
|
-
|
|
58
|
+
const d = distance(
|
|
59
|
+
[lastPointerDown.offsetX, lastPointerDown.offsetY],
|
|
60
|
+
[evt.offsetX, evt.offsetY]);
|
|
61
|
+
|
|
62
|
+
if (timeDifference > 300 || d > 15) // Not a single click - ignore
|
|
63
|
+
return;
|
|
63
64
|
|
|
64
65
|
if (isClosable) {
|
|
65
66
|
stopDrawing();
|
|
@@ -98,22 +99,25 @@
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
const onDblClick = () => {
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
// Require min 3 points (incl. cursor) and minimum
|
|
103
|
+
// polygon area
|
|
103
104
|
const p = [...points, cursor];
|
|
104
105
|
|
|
105
106
|
const shape: Polygon = {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
107
|
+
type: ShapeType.POLYGON,
|
|
108
|
+
geometry: {
|
|
109
|
+
bounds: boundsFromPoints(p),
|
|
110
|
+
points: p
|
|
111
111
|
}
|
|
112
|
+
}
|
|
112
113
|
|
|
114
|
+
const area = computeArea(shape);
|
|
115
|
+
if (area > 4) {
|
|
113
116
|
points = [];
|
|
114
117
|
cursor = null;
|
|
115
118
|
|
|
116
119
|
dispatch('create', shape);
|
|
120
|
+
}
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
const stopDrawing = () => {
|
|
@@ -139,10 +143,7 @@
|
|
|
139
143
|
});
|
|
140
144
|
</script>
|
|
141
145
|
|
|
142
|
-
<g
|
|
143
|
-
bind:this={container}
|
|
144
|
-
class="a9s-annotation a9s-rubberband">
|
|
145
|
-
|
|
146
|
+
<g class="a9s-annotation a9s-rubberband">
|
|
146
147
|
{#if cursor}
|
|
147
148
|
{@const coords = (isClosable ? points : [...points, cursor]).map(xy => xy.join(',')).join(' ')}
|
|
148
149
|
<polygon
|
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
export let addEventListener: (type: string, fn: EventListener, capture?: boolean) => void;
|
|
11
11
|
export let drawingMode: DrawingMode;
|
|
12
12
|
export let transform: Transform;
|
|
13
|
-
|
|
14
|
-
let container: SVGGElement;
|
|
15
13
|
|
|
16
14
|
let lastPointerDown: number;
|
|
17
15
|
|
|
@@ -109,10 +107,7 @@
|
|
|
109
107
|
});
|
|
110
108
|
</script>
|
|
111
109
|
|
|
112
|
-
<g
|
|
113
|
-
bind:this={container}
|
|
114
|
-
class="a9s-annotation a9s-rubberband">
|
|
115
|
-
|
|
110
|
+
<g class="a9s-annotation a9s-rubberband">
|
|
116
111
|
{#if origin}
|
|
117
112
|
<rect
|
|
118
113
|
class="a9s-outer"
|
package/src/index.ts
CHANGED
|
@@ -5,16 +5,34 @@ export * from './themes';
|
|
|
5
5
|
export * from './annotation/tools';
|
|
6
6
|
export * from './Annotorious';
|
|
7
7
|
export * from './AnnotoriousOpts';
|
|
8
|
+
export * from './keyboardCommands';
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
// Essential re-exports from @annotorious/core
|
|
11
|
+
export type {
|
|
12
|
+
Annotation,
|
|
13
|
+
AnnotationBody,
|
|
14
|
+
AnnotationTarget,
|
|
15
|
+
Annotator,
|
|
16
|
+
AnnotatorState,
|
|
17
|
+
Appearance,
|
|
18
|
+
AppearanceProvider,
|
|
19
|
+
Color,
|
|
20
|
+
DrawingStyle,
|
|
21
|
+
Filter,
|
|
22
|
+
FormatAdapter,
|
|
15
23
|
HoverState,
|
|
24
|
+
LifecycleEvents,
|
|
25
|
+
ParseResult,
|
|
26
|
+
PresentUser,
|
|
27
|
+
Purpose,
|
|
16
28
|
Selection,
|
|
17
29
|
SelectionState,
|
|
18
30
|
Store,
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
StoreChangeEvent,
|
|
32
|
+
StoreObserver,
|
|
33
|
+
User,
|
|
34
|
+
W3CAnnotation,
|
|
35
|
+
W3CAnnotationBody,
|
|
36
|
+
W3CAnnotationTarget,
|
|
37
|
+
W3CSelector
|
|
38
|
+
} from '@annotorious/core';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Annotation, UndoStack } from '@annotorious/core';
|
|
2
|
+
|
|
3
|
+
const isMac = navigator.userAgent.indexOf('Mac OS X') !== -1;
|
|
4
|
+
|
|
5
|
+
export const initKeyboardCommands = <T extends Annotation>(
|
|
6
|
+
undoStack: UndoStack<T>,
|
|
7
|
+
container?: Element
|
|
8
|
+
) => {
|
|
9
|
+
|
|
10
|
+
const el = container || document;
|
|
11
|
+
|
|
12
|
+
const onWinKeyDown = (event: KeyboardEvent) => {
|
|
13
|
+
if (event.key === 'Z' && event.ctrlKey) {
|
|
14
|
+
undoStack.undo();
|
|
15
|
+
} else if (event.key === 'Y' && event.ctrlKey) {
|
|
16
|
+
undoStack.redo()
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const onMacKeyDown = (event: KeyboardEvent) => {
|
|
21
|
+
if (event.key === 'z' && event.metaKey) {
|
|
22
|
+
if (event.shiftKey) {
|
|
23
|
+
undoStack.redo()
|
|
24
|
+
} else {
|
|
25
|
+
undoStack.undo();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const destroy = () => {
|
|
31
|
+
if (isMac) {
|
|
32
|
+
el.removeEventListener('keydown', onMacKeyDown);
|
|
33
|
+
} else {
|
|
34
|
+
el.removeEventListener('keydown', onWinKeyDown);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (isMac)
|
|
39
|
+
el.addEventListener('keydown', onMacKeyDown);
|
|
40
|
+
else
|
|
41
|
+
el.addEventListener('keydown', onWinKeyDown);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
destroy
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -30,7 +30,9 @@ export const parseW3CImageAnnotation = (
|
|
|
30
30
|
): ParseResult<ImageAnnotation> => {
|
|
31
31
|
const annotationId = annotation.id || uuidv4();
|
|
32
32
|
|
|
33
|
-
const
|
|
33
|
+
const { body, ...rest } = annotation;
|
|
34
|
+
|
|
35
|
+
const bodies = parseW3CBodies(body, annotationId);
|
|
34
36
|
|
|
35
37
|
const target = Array.isArray(annotation.target) ? annotation.target[0] : annotation.target;
|
|
36
38
|
|
|
@@ -44,16 +46,17 @@ export const parseW3CImageAnnotation = (
|
|
|
44
46
|
|
|
45
47
|
return selector ? {
|
|
46
48
|
parsed: {
|
|
47
|
-
...
|
|
49
|
+
...rest,
|
|
48
50
|
id: annotationId,
|
|
49
51
|
bodies,
|
|
50
52
|
target: {
|
|
53
|
+
...rest.target,
|
|
51
54
|
annotation: annotationId,
|
|
52
55
|
selector
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
} : {
|
|
56
|
-
error: Error(`Unknown selector type: ${
|
|
59
|
+
error: Error(`Unknown selector type: ${w3cSelector.type}`)
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Theme } from '../../AnnotoriousOpts';
|
|
2
|
+
|
|
1
3
|
export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
|
|
2
4
|
|
|
3
5
|
let canvas: HTMLCanvasElement;
|
|
@@ -35,12 +37,14 @@ export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
|
|
|
35
37
|
return totalBrightness / 81;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
export const
|
|
40
|
+
export const detectTheme = (imageOrCanvas: HTMLElement) => {
|
|
39
41
|
const brightness = sampleBrightness(imageOrCanvas);
|
|
40
|
-
|
|
41
42
|
const theme = brightness > 0.6 ? 'dark' : 'light'
|
|
42
43
|
|
|
43
44
|
console.log(`[Annotorious] Image brightness: ${brightness.toFixed(1)}. Setting ${theme} theme.`);
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
}
|
|
46
|
+
return theme;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const setTheme = (imageOrCanvas: HTMLElement, container: HTMLElement, theme: Theme) =>
|
|
50
|
+
container.setAttribute('data-theme', theme === 'auto' ? detectTheme(imageOrCanvas) : theme);
|