kviewer 0.3.0 → 0.3.2
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/module.d.mts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +13 -0
- package/dist/runtime/annotation/engine/config.d.ts +1 -0
- package/dist/runtime/annotation/engine/config.js +4 -0
- package/dist/runtime/annotation/engine/cursor-preview.d.ts +14 -1
- package/dist/runtime/annotation/engine/cursor-preview.js +32 -6
- package/dist/runtime/annotation/engine/editor/editor.js +10 -12
- package/dist/runtime/annotation/engine/editor/selector.js +3 -1
- package/dist/runtime/annotation/engine/tools/arrow.js +24 -14
- package/dist/runtime/annotation/engine/tools/circle.js +24 -13
- package/dist/runtime/annotation/engine/tools/cloud.js +27 -18
- package/dist/runtime/annotation/engine/tools/free-highlight.js +24 -15
- package/dist/runtime/annotation/engine/tools/freehand.js +21 -12
- package/dist/runtime/annotation/engine/tools/highlight.d.ts +2 -0
- package/dist/runtime/annotation/engine/tools/highlight.js +20 -10
- package/dist/runtime/annotation/engine/tools/note.js +3 -1
- package/dist/runtime/annotation/engine/tools/rectangle.js +19 -8
- package/dist/runtime/annotation/engine/tools/signature.js +31 -5
- package/dist/runtime/annotation/engine/tools/stamp.d.ts +1 -0
- package/dist/runtime/annotation/engine/tools/stamp.js +43 -15
- package/dist/runtime/annotation/engine/utils.d.ts +1 -4
- package/dist/runtime/annotation/engine/utils.js +3 -11
- package/dist/runtime/annotation/pdf-export/download.js +1 -1
- package/dist/runtime/annotation/pdf-export/export.js +1 -1
- package/dist/runtime/annotation/pdf-export/parse_polyline.js +5 -1
- package/dist/runtime/annotation/pdf-export/parse_stamp.js +4 -4
- package/dist/runtime/annotation/pdf-export/unicode-font.js +1 -4
- package/dist/runtime/annotation/pdf-import/decode_stamp.js +3 -2
- package/dist/runtime/annotation/pdf-import/extract_stamp_appearance.js +1 -1
- package/dist/runtime/annotation/pdf-import/utils.js +1 -1
- package/dist/runtime/annotation/utils/placement_size.d.ts +27 -0
- package/dist/runtime/annotation/utils/placement_size.js +26 -0
- package/dist/runtime/components/FormFieldLayer.d.vue.ts +1 -1
- package/dist/runtime/components/FormFieldLayer.vue.d.ts +1 -1
- package/dist/runtime/components/PdfPage.vue +3 -3
- package/dist/runtime/components/Viewer.vue +3 -1
- package/dist/runtime/components/ViewerTabs.vue +1 -1
- package/dist/runtime/components/panels/SignaturePicker.vue +8 -2
- package/dist/runtime/composables/useSearchIndex.js +1 -1
- package/dist/runtime/embed/bridge-host.d.ts +1 -1
- package/dist/runtime/embed/bridge-host.js +3 -3
- package/dist/runtime/imports.d.ts +19 -0
- package/dist/types.d.mts +1 -1
- package/package.json +2 -2
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
export { ActiveTool, AddFormFieldPayload, CheckboxStyle, ExportPdfOptions, FormFieldDefinition, FormFieldOrigin, FormFieldType, FormFieldValue, KVIEWER_EMBED_PROTOCOL_VERSION, KViewerApi, KViewerEmbedBridgeOptions, KViewerEmbedClient, KViewerEmbedClientOptions, KViewerEmbedEventName, KViewerEmbedEventPayloads, KViewerEmbedMethodName, SignatureData, SignatureHandlers, ViewMode, ViewerBottomToolId, ViewerLayoutToolId, ViewerMenuButtonItem, ViewerMenuCheckboxItem, ViewerMenuItem, ViewerMenuSeparatorItem, ViewerState, ViewerToolEntry, ViewerToolId, ViewerToolSlot, ViewerTopToolId, useKViewerEmbedBridge } from '../dist/runtime/public-types.js';
|
|
2
|
+
export { ActiveTool, AddFormFieldPayload, CheckboxStyle, ExportPdfOptions, FormFieldDefinition, FormFieldOrigin, FormFieldType, FormFieldValue, KVIEWER_EMBED_PROTOCOL_VERSION, KViewerApi, KViewerEmbedBridgeOptions, KViewerEmbedClient, KViewerEmbedClientOptions, KViewerEmbedEventName, KViewerEmbedEventPayloads, KViewerEmbedMethodName, PlacedFieldDefaults, SignatureData, SignatureFieldStatus, SignatureHandlers, ViewMode, ViewerBottomToolId, ViewerLayoutToolId, ViewerMenuButtonItem, ViewerMenuCheckboxItem, ViewerMenuItem, ViewerMenuSeparatorItem, ViewerState, ViewerToolEntry, ViewerToolId, ViewerToolSlot, ViewerTopToolId, useKViewerEmbedBridge } from '../dist/runtime/public-types.js';
|
|
3
3
|
|
|
4
4
|
interface ModuleOptions {
|
|
5
5
|
/**
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -56,6 +56,10 @@ const module$1 = defineNuxtModule({
|
|
|
56
56
|
locale: options.locale ?? "en"
|
|
57
57
|
};
|
|
58
58
|
nuxt.options.css.push("pdfjs-dist/web/pdf_viewer.css");
|
|
59
|
+
const cssnano = nuxt.options.postcss?.plugins?.cssnano;
|
|
60
|
+
if (cssnano && typeof cssnano === "object" && !cssnano.preset) {
|
|
61
|
+
cssnano.preset = ["default", { svgo: false }];
|
|
62
|
+
}
|
|
59
63
|
nuxt.options.css.push(resolve("./runtime/assets/kviewer.css"));
|
|
60
64
|
addPlugin(resolve("./runtime/plugin"));
|
|
61
65
|
addComponentsDir({
|
|
@@ -72,6 +76,15 @@ const module$1 = defineNuxtModule({
|
|
|
72
76
|
const require_ = createRequire(import.meta.url);
|
|
73
77
|
const pdfjsDir = dirname(require_.resolve("pdfjs-dist/package.json"));
|
|
74
78
|
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
79
|
+
nitroConfig.externals ||= {};
|
|
80
|
+
nitroConfig.externals.inline ||= [];
|
|
81
|
+
if (Array.isArray(nitroConfig.externals.inline)) {
|
|
82
|
+
for (const dependency of ["unhead", "consola"]) {
|
|
83
|
+
if (!nitroConfig.externals.inline.includes(dependency)) {
|
|
84
|
+
nitroConfig.externals.inline.push(dependency);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
75
88
|
nitroConfig.publicAssets ||= [];
|
|
76
89
|
nitroConfig.publicAssets.push(
|
|
77
90
|
{
|
|
@@ -74,6 +74,10 @@ export const defaultOptions = {
|
|
|
74
74
|
STROKE_WIDTH: 2,
|
|
75
75
|
OPACITY: 1,
|
|
76
76
|
MAX_CURSOR_SIZE: 96,
|
|
77
|
+
// Bound for stamps/signatures placed without explicit dimensions. Shared
|
|
78
|
+
// by the placement path and the cursor preview so the ghost cannot drift
|
|
79
|
+
// from what actually lands on the page.
|
|
80
|
+
MAX_PLACEMENT_SIZE: 120,
|
|
77
81
|
MAX_UPLOAD_IMAGE_SIZE: 800,
|
|
78
82
|
LOAD_PDF_ANNOTATION: true,
|
|
79
83
|
DB_CLICK_DELETE: false
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface ImageSize {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Bumped whenever the preview is torn down or replaced. Callers that size the
|
|
7
|
+
* preview asynchronously capture it first and bail if it moved, so a slow
|
|
8
|
+
* measurement cannot resurrect a ghost for a tool the user already left.
|
|
9
|
+
*/
|
|
10
|
+
export declare function cursorPreviewToken(): number;
|
|
11
|
+
/** Synchronous hit for an already-measured image, so repeat picks don't flash. */
|
|
12
|
+
export declare function peekImageSize(imageUrl: string): ImageSize | null;
|
|
13
|
+
export declare function measureImage(imageUrl: string): Promise<ImageSize | null>;
|
|
14
|
+
export declare function showCursorPreview(imageUrl: string, width?: number, height?: number): void;
|
|
2
15
|
export declare function hideCursorPreview(): void;
|
|
@@ -4,6 +4,32 @@ const PADDING = 6;
|
|
|
4
4
|
const CROSSHAIR_SIZE = 12;
|
|
5
5
|
let previewEl = null;
|
|
6
6
|
let mouseMoveHandler = null;
|
|
7
|
+
let previewToken = 0;
|
|
8
|
+
const naturalSizeCache = /* @__PURE__ */ new Map();
|
|
9
|
+
export function cursorPreviewToken() {
|
|
10
|
+
return previewToken;
|
|
11
|
+
}
|
|
12
|
+
export function peekImageSize(imageUrl) {
|
|
13
|
+
return naturalSizeCache.get(imageUrl) ?? null;
|
|
14
|
+
}
|
|
15
|
+
export function measureImage(imageUrl) {
|
|
16
|
+
const cached = naturalSizeCache.get(imageUrl);
|
|
17
|
+
if (cached) return Promise.resolve(cached);
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
const img = new Image();
|
|
20
|
+
img.addEventListener("load", () => {
|
|
21
|
+
const size = { width: img.naturalWidth, height: img.naturalHeight };
|
|
22
|
+
if (!size.width || !size.height) {
|
|
23
|
+
resolve(null);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
naturalSizeCache.set(imageUrl, size);
|
|
27
|
+
resolve(size);
|
|
28
|
+
});
|
|
29
|
+
img.addEventListener("error", () => resolve(null));
|
|
30
|
+
img.src = imageUrl;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
7
33
|
function isOverPage(e) {
|
|
8
34
|
const target = e.target;
|
|
9
35
|
if (!target) return false;
|
|
@@ -21,16 +47,15 @@ function onMouseMove(e) {
|
|
|
21
47
|
document.body.style.cursor = "";
|
|
22
48
|
}
|
|
23
49
|
}
|
|
24
|
-
export function showCursorPreview(imageUrl,
|
|
50
|
+
export function showCursorPreview(imageUrl, width = 80, height = width) {
|
|
25
51
|
hideCursorPreview();
|
|
26
|
-
const outerSize = size + PADDING * 2;
|
|
27
52
|
previewEl = document.createElement("div");
|
|
28
53
|
Object.assign(previewEl.style, {
|
|
29
54
|
position: "fixed",
|
|
30
55
|
zIndex: "9999",
|
|
31
56
|
pointerEvents: "none",
|
|
32
|
-
width: `${
|
|
33
|
-
height: `${
|
|
57
|
+
width: `${width + PADDING * 2}px`,
|
|
58
|
+
height: `${height + PADDING * 2}px`,
|
|
34
59
|
transform: "translate(-50%, -50%)",
|
|
35
60
|
border: `2px solid ${PRIMARY_COLOR}`,
|
|
36
61
|
borderRadius: "3px",
|
|
@@ -41,8 +66,8 @@ export function showCursorPreview(imageUrl, size = 80) {
|
|
|
41
66
|
const img = document.createElement("img");
|
|
42
67
|
img.src = imageUrl;
|
|
43
68
|
Object.assign(img.style, {
|
|
44
|
-
width: `${
|
|
45
|
-
height: `${
|
|
69
|
+
width: `${width}px`,
|
|
70
|
+
height: `${height}px`,
|
|
46
71
|
objectFit: "contain",
|
|
47
72
|
display: "block",
|
|
48
73
|
pointerEvents: "none"
|
|
@@ -76,6 +101,7 @@ export function showCursorPreview(imageUrl, size = 80) {
|
|
|
76
101
|
document.addEventListener("mousemove", mouseMoveHandler);
|
|
77
102
|
}
|
|
78
103
|
export function hideCursorPreview() {
|
|
104
|
+
previewToken++;
|
|
79
105
|
if (previewEl) {
|
|
80
106
|
previewEl.remove();
|
|
81
107
|
previewEl = null;
|
|
@@ -57,18 +57,14 @@ export class Editor {
|
|
|
57
57
|
id,
|
|
58
58
|
pageNumber,
|
|
59
59
|
konvaString: konvaGroup.toJSON(),
|
|
60
|
-
// Do NOT use konvaGroup.getClientRect()
|
|
61
|
-
// stage
|
|
62
|
-
//
|
|
60
|
+
// Do NOT use konvaGroup.getClientRect() without relativeTo here — it is
|
|
61
|
+
// in absolute stage coordinates, which bake in the stage's zoom scale
|
|
62
|
+
// AND the windowed stage position (setStageWindow shifts stage.position
|
|
63
|
+
// at high zoom). relativeTo undoes both, yielding page-space
|
|
64
|
+
// coordinates regardless of the zoom state at placement time.
|
|
63
65
|
konvaClientRect: (() => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
x: raw.x / scale,
|
|
68
|
-
y: raw.y / scale,
|
|
69
|
-
width: raw.width / scale,
|
|
70
|
-
height: raw.height / scale
|
|
71
|
-
};
|
|
66
|
+
const stage = konvaGroup.getStage();
|
|
67
|
+
return stage ? konvaGroup.getClientRect({ relativeTo: stage }) : konvaGroup.getClientRect();
|
|
72
68
|
})(),
|
|
73
69
|
title: this.userName,
|
|
74
70
|
type: annotation.type,
|
|
@@ -144,7 +140,9 @@ export class Editor {
|
|
|
144
140
|
this.konvaStage.off("click mousedown mousemove mouseup touchstart touchmove touchend");
|
|
145
141
|
}
|
|
146
142
|
getBgLayer(konvaStage) {
|
|
147
|
-
|
|
143
|
+
const layer = konvaStage ? konvaStage.getLayers()[0] : this.konvaStage.getLayers()[0];
|
|
144
|
+
if (!layer) throw new Error("Annotation stage has no background layer");
|
|
145
|
+
return layer;
|
|
148
146
|
}
|
|
149
147
|
delShapeGroup(id) {
|
|
150
148
|
this.shapeGroupStore.delete(id);
|
|
@@ -99,7 +99,9 @@ export class Selector {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
getBackgroundLayer(konvaStage) {
|
|
102
|
-
|
|
102
|
+
const layer = konvaStage.getLayers()[0];
|
|
103
|
+
if (!layer) throw new Error("Annotation stage has no background layer");
|
|
104
|
+
return layer;
|
|
103
105
|
}
|
|
104
106
|
getPageShapeGroups(konvaStage) {
|
|
105
107
|
return this.getBackgroundLayer(konvaStage).getChildren(
|
|
@@ -13,17 +13,21 @@ export class EditorArrow extends Editor {
|
|
|
13
13
|
}
|
|
14
14
|
mouseDownHandler(e) {
|
|
15
15
|
if (e.currentTarget !== this.konvaStage) return;
|
|
16
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
17
|
+
const annotation = this.currentAnnotation;
|
|
18
|
+
const style = annotation?.style;
|
|
19
|
+
if (!pos || !annotation || !style) return;
|
|
16
20
|
this.arrow = null;
|
|
17
21
|
this.isPainting = true;
|
|
18
|
-
|
|
19
|
-
this.
|
|
20
|
-
|
|
22
|
+
const shapeGroup = this.createShapeGroup();
|
|
23
|
+
this.currentShapeGroup = shapeGroup;
|
|
24
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
21
25
|
this.startPoint = { x: pos.x, y: pos.y };
|
|
22
26
|
this.arrow = new Konva.Arrow({
|
|
23
27
|
points: [pos.x, pos.y, pos.x, pos.y],
|
|
24
|
-
stroke:
|
|
25
|
-
strokeWidth:
|
|
26
|
-
fill:
|
|
28
|
+
stroke: style.color,
|
|
29
|
+
strokeWidth: style.strokeWidth,
|
|
30
|
+
fill: style.color,
|
|
27
31
|
pointerLength: 10,
|
|
28
32
|
pointerWidth: 10,
|
|
29
33
|
hitStrokeWidth: 20,
|
|
@@ -31,15 +35,16 @@ export class EditorArrow extends Editor {
|
|
|
31
35
|
lineCap: "round",
|
|
32
36
|
lineJoin: "round",
|
|
33
37
|
visible: false,
|
|
34
|
-
opacity:
|
|
38
|
+
opacity: style.opacity
|
|
35
39
|
});
|
|
36
|
-
|
|
40
|
+
shapeGroup.konvaGroup.add(this.arrow);
|
|
37
41
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
38
42
|
}
|
|
39
43
|
mouseMoveHandler(e) {
|
|
40
44
|
if (!this.isPainting) return;
|
|
41
45
|
e.evt.preventDefault();
|
|
42
46
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
47
|
+
if (!pos) return;
|
|
43
48
|
const points = [this.startPoint.x, this.startPoint.y, pos.x, pos.y];
|
|
44
49
|
this.arrow?.show();
|
|
45
50
|
this.arrow?.setAttrs({ points });
|
|
@@ -47,20 +52,24 @@ export class EditorArrow extends Editor {
|
|
|
47
52
|
mouseUpHandler() {
|
|
48
53
|
if (!this.isPainting) return;
|
|
49
54
|
this.isPainting = false;
|
|
50
|
-
const
|
|
51
|
-
|
|
55
|
+
const arrow = this.arrow;
|
|
56
|
+
const group = arrow?.getParent();
|
|
57
|
+
if (!arrow || !group) return;
|
|
58
|
+
if (!arrow.isVisible() && group.getType() === "Group") {
|
|
52
59
|
this.delShapeGroup(group.id());
|
|
53
60
|
return;
|
|
54
61
|
}
|
|
55
62
|
if (this.isTooShort()) {
|
|
56
|
-
|
|
63
|
+
arrow.destroy();
|
|
57
64
|
this.delShapeGroup(group.id());
|
|
58
65
|
this.arrow = null;
|
|
59
66
|
return;
|
|
60
67
|
}
|
|
68
|
+
const style = this.currentAnnotation?.style;
|
|
69
|
+
if (!style) return;
|
|
61
70
|
this.setShapeGroupDone({
|
|
62
71
|
id: group.id(),
|
|
63
|
-
color:
|
|
72
|
+
color: style.color,
|
|
64
73
|
contentsObj: {
|
|
65
74
|
text: ""
|
|
66
75
|
}
|
|
@@ -76,8 +85,9 @@ export class EditorArrow extends Editor {
|
|
|
76
85
|
if (!this.arrow) return true;
|
|
77
86
|
const points = this.arrow.points();
|
|
78
87
|
if (points.length !== 4) return true;
|
|
79
|
-
const
|
|
80
|
-
const
|
|
88
|
+
const [x1, y1, x2, y2] = points;
|
|
89
|
+
const dx = x2 - x1;
|
|
90
|
+
const dy = y2 - y1;
|
|
81
91
|
return Math.hypot(dx, dy) < Editor.MinSize;
|
|
82
92
|
}
|
|
83
93
|
/**
|
|
@@ -23,11 +23,15 @@ export class EditorCircle extends Editor {
|
|
|
23
23
|
if (e.currentTarget !== this.konvaStage) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
27
|
+
const annotation = this.currentAnnotation;
|
|
28
|
+
const style = annotation?.style;
|
|
29
|
+
if (!pos || !annotation || !style) return;
|
|
26
30
|
this.ellipse = null;
|
|
27
31
|
this.isPainting = true;
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
|
|
32
|
+
const shapeGroup = this.createShapeGroup();
|
|
33
|
+
this.currentShapeGroup = shapeGroup;
|
|
34
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
31
35
|
this.vertex = { x: pos.x, y: pos.y };
|
|
32
36
|
this.ellipse = new Konva.Ellipse({
|
|
33
37
|
radiusX: 0,
|
|
@@ -36,14 +40,14 @@ export class EditorCircle extends Editor {
|
|
|
36
40
|
y: pos.y,
|
|
37
41
|
visible: false,
|
|
38
42
|
// Start hidden
|
|
39
|
-
stroke:
|
|
43
|
+
stroke: style.color,
|
|
40
44
|
// Set the ellipse stroke color
|
|
41
|
-
strokeWidth:
|
|
45
|
+
strokeWidth: style.strokeWidth,
|
|
42
46
|
// Set the ellipse stroke width
|
|
43
|
-
opacity:
|
|
47
|
+
opacity: style.opacity
|
|
44
48
|
// Set the ellipse opacity
|
|
45
49
|
});
|
|
46
|
-
|
|
50
|
+
shapeGroup.konvaGroup.add(this.ellipse);
|
|
47
51
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
48
52
|
}
|
|
49
53
|
/**
|
|
@@ -55,8 +59,10 @@ export class EditorCircle extends Editor {
|
|
|
55
59
|
return;
|
|
56
60
|
}
|
|
57
61
|
e.evt.preventDefault();
|
|
58
|
-
this.ellipse.show();
|
|
59
62
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
63
|
+
const ellipse = this.ellipse;
|
|
64
|
+
if (!pos || !ellipse) return;
|
|
65
|
+
ellipse.show();
|
|
60
66
|
const radiusX = Math.abs(pos.x - this.vertex.x) / 2;
|
|
61
67
|
const radiusY = Math.abs(pos.y - this.vertex.y) / 2;
|
|
62
68
|
const areaAttr = {
|
|
@@ -65,7 +71,7 @@ export class EditorCircle extends Editor {
|
|
|
65
71
|
radiusX,
|
|
66
72
|
radiusY
|
|
67
73
|
};
|
|
68
|
-
|
|
74
|
+
ellipse.setAttrs(areaAttr);
|
|
69
75
|
}
|
|
70
76
|
/**
|
|
71
77
|
* Handles mouse or touch pointer-up events and finishes drawing the ellipse.
|
|
@@ -75,20 +81,24 @@ export class EditorCircle extends Editor {
|
|
|
75
81
|
return;
|
|
76
82
|
}
|
|
77
83
|
this.isPainting = false;
|
|
78
|
-
const
|
|
79
|
-
|
|
84
|
+
const ellipse = this.ellipse;
|
|
85
|
+
const group = ellipse?.getParent();
|
|
86
|
+
if (!ellipse || !group) return;
|
|
87
|
+
if (!ellipse.isVisible() && group.getType() === "Group") {
|
|
80
88
|
this.delShapeGroup(group.id());
|
|
81
89
|
return;
|
|
82
90
|
}
|
|
83
91
|
if (this.isTooSmall()) {
|
|
84
|
-
|
|
92
|
+
ellipse.destroy();
|
|
85
93
|
this.delShapeGroup(group.id());
|
|
86
94
|
this.ellipse = null;
|
|
87
95
|
return;
|
|
88
96
|
}
|
|
97
|
+
const style = this.currentAnnotation?.style;
|
|
98
|
+
if (!style) return;
|
|
89
99
|
this.setShapeGroupDone({
|
|
90
100
|
id: group.id(),
|
|
91
|
-
color:
|
|
101
|
+
color: style.color,
|
|
92
102
|
contentsObj: {
|
|
93
103
|
text: ""
|
|
94
104
|
}
|
|
@@ -109,6 +119,7 @@ export class EditorCircle extends Editor {
|
|
|
109
119
|
* @returns True if the ellipse width or height is smaller than the minimum size, otherwise false.
|
|
110
120
|
*/
|
|
111
121
|
isTooSmall() {
|
|
122
|
+
if (!this.ellipse) return true;
|
|
112
123
|
const { width, height } = this.ellipse.size();
|
|
113
124
|
return Math.max(width, height) < Editor.MinSize;
|
|
114
125
|
}
|
|
@@ -35,23 +35,27 @@ export class EditorCloud extends Editor {
|
|
|
35
35
|
}
|
|
36
36
|
mouseDownHandler(_e) {
|
|
37
37
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
38
|
+
const annotation = this.currentAnnotation;
|
|
39
|
+
const style = annotation?.style;
|
|
40
|
+
if (!pos || !annotation || !style) return;
|
|
38
41
|
this.points.push(pos);
|
|
39
42
|
if (!this.isPainting) {
|
|
40
43
|
this.isPainting = true;
|
|
41
|
-
|
|
42
|
-
this.
|
|
44
|
+
const shapeGroup = this.createShapeGroup();
|
|
45
|
+
this.currentShapeGroup = shapeGroup;
|
|
46
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
43
47
|
this.cloudPath = new Konva.Path({
|
|
44
48
|
data: "",
|
|
45
|
-
stroke:
|
|
46
|
-
strokeWidth:
|
|
49
|
+
stroke: style.color,
|
|
50
|
+
strokeWidth: style.strokeWidth,
|
|
47
51
|
fillEnabled: false,
|
|
48
52
|
lineJoin: "round",
|
|
49
53
|
lineCap: "round",
|
|
50
54
|
hitStrokeWidth: 20,
|
|
51
55
|
// Set the hit detection width
|
|
52
|
-
opacity:
|
|
56
|
+
opacity: style.opacity
|
|
53
57
|
});
|
|
54
|
-
|
|
58
|
+
shapeGroup.konvaGroup.add(this.cloudPath);
|
|
55
59
|
this.drawStartRect(pos);
|
|
56
60
|
}
|
|
57
61
|
this.updateCloudPreview();
|
|
@@ -59,6 +63,7 @@ export class EditorCloud extends Editor {
|
|
|
59
63
|
mouseMoveHandler(_e) {
|
|
60
64
|
if (!this.isPainting || !this.cloudPath) return;
|
|
61
65
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
66
|
+
if (!pos) return;
|
|
62
67
|
this.updateCloudPreview(pos);
|
|
63
68
|
}
|
|
64
69
|
mouseUpHandler(_e) {
|
|
@@ -73,9 +78,12 @@ export class EditorCloud extends Editor {
|
|
|
73
78
|
const closedPoints = [...this.points, this.points[0]];
|
|
74
79
|
const pathData = this.generateCloudPathData(closedPoints);
|
|
75
80
|
this.cloudPath.data(pathData);
|
|
81
|
+
const shapeGroup = this.currentShapeGroup;
|
|
82
|
+
const style = this.currentAnnotation?.style;
|
|
83
|
+
if (!shapeGroup || !style) return;
|
|
76
84
|
this.setShapeGroupDone({
|
|
77
|
-
id:
|
|
78
|
-
color:
|
|
85
|
+
id: shapeGroup.konvaGroup.id(),
|
|
86
|
+
color: style.color,
|
|
79
87
|
contentsObj: { text: "" }
|
|
80
88
|
});
|
|
81
89
|
this.cloudPath = null;
|
|
@@ -179,7 +187,7 @@ export class EditorCloud extends Editor {
|
|
|
179
187
|
height: this.startRectSize,
|
|
180
188
|
stroke: "#000",
|
|
181
189
|
strokeWidth: 2,
|
|
182
|
-
|
|
190
|
+
fillEnabled: false,
|
|
183
191
|
cornerRadius: 2,
|
|
184
192
|
hitStrokeWidth: 10,
|
|
185
193
|
// Increase the hit detection area
|
|
@@ -187,26 +195,27 @@ export class EditorCloud extends Editor {
|
|
|
187
195
|
dash: [4, 2],
|
|
188
196
|
name: "startRect"
|
|
189
197
|
});
|
|
190
|
-
this.
|
|
191
|
-
this.
|
|
192
|
-
|
|
198
|
+
const startRect = this.startRect;
|
|
199
|
+
this.getBgLayer().add(startRect);
|
|
200
|
+
startRect.moveToTop();
|
|
201
|
+
startRect.on(
|
|
193
202
|
"mouseup",
|
|
194
203
|
(_e) => {
|
|
195
204
|
this.handleDoubleClick();
|
|
196
205
|
}
|
|
197
206
|
);
|
|
198
|
-
|
|
207
|
+
startRect.on(
|
|
199
208
|
"mousemove",
|
|
200
209
|
(_e) => {
|
|
201
|
-
|
|
202
|
-
|
|
210
|
+
startRect.stroke("#1677ff");
|
|
211
|
+
startRect.getLayer()?.batchDraw();
|
|
203
212
|
}
|
|
204
213
|
);
|
|
205
|
-
|
|
214
|
+
startRect.on(
|
|
206
215
|
"mouseout",
|
|
207
216
|
(_e) => {
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
startRect.stroke("#000");
|
|
218
|
+
startRect.getLayer()?.batchDraw();
|
|
210
219
|
}
|
|
211
220
|
);
|
|
212
221
|
}
|
|
@@ -16,16 +16,20 @@ export class EditorFreeHighlight extends Editor {
|
|
|
16
16
|
if (e.currentTarget !== this.konvaStage) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
20
|
+
const annotation = this.currentAnnotation;
|
|
21
|
+
const style = annotation?.style;
|
|
22
|
+
if (!pos || !annotation || !style) return;
|
|
19
23
|
this.line = null;
|
|
20
24
|
this.isPainting = true;
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
|
|
25
|
+
const shapeGroup = this.createShapeGroup();
|
|
26
|
+
this.currentShapeGroup = shapeGroup;
|
|
27
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
24
28
|
this.line = new Konva.Line({
|
|
25
|
-
stroke:
|
|
26
|
-
strokeWidth:
|
|
27
|
-
opacity:
|
|
28
|
-
hitStrokeWidth:
|
|
29
|
+
stroke: style.color,
|
|
30
|
+
strokeWidth: style.strokeWidth,
|
|
31
|
+
opacity: style.opacity,
|
|
32
|
+
hitStrokeWidth: style.strokeWidth,
|
|
29
33
|
lineCap: "round",
|
|
30
34
|
lineJoin: "round",
|
|
31
35
|
visible: false,
|
|
@@ -33,7 +37,7 @@ export class EditorFreeHighlight extends Editor {
|
|
|
33
37
|
points: [pos.x, pos.y]
|
|
34
38
|
// Initialize the starting point
|
|
35
39
|
});
|
|
36
|
-
|
|
40
|
+
shapeGroup.konvaGroup.add(this.line);
|
|
37
41
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
@@ -45,10 +49,12 @@ export class EditorFreeHighlight extends Editor {
|
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
47
51
|
e.evt.preventDefault();
|
|
48
|
-
this.line.show();
|
|
49
52
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
50
|
-
const
|
|
51
|
-
|
|
53
|
+
const line = this.line;
|
|
54
|
+
if (!pos || !line) return;
|
|
55
|
+
line.show();
|
|
56
|
+
const newPoints = line.points().concat([pos.x, pos.y]);
|
|
57
|
+
line.points(newPoints);
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
60
|
* Handles mouse or touch pointer-up events and finishes drawing the freeform curve.
|
|
@@ -58,8 +64,9 @@ export class EditorFreeHighlight extends Editor {
|
|
|
58
64
|
return;
|
|
59
65
|
}
|
|
60
66
|
this.isPainting = false;
|
|
61
|
-
const
|
|
62
|
-
|
|
67
|
+
const line = this.line;
|
|
68
|
+
const group = line?.getParent();
|
|
69
|
+
if (group && line && !line.isVisible() && group.getType() === "Group") {
|
|
63
70
|
this.delShapeGroup(group.id());
|
|
64
71
|
return;
|
|
65
72
|
}
|
|
@@ -71,13 +78,14 @@ export class EditorFreeHighlight extends Editor {
|
|
|
71
78
|
this.line = null;
|
|
72
79
|
return;
|
|
73
80
|
}
|
|
74
|
-
|
|
81
|
+
const style = this.currentAnnotation?.style;
|
|
82
|
+
if (this.line && group && style) {
|
|
75
83
|
const originalPoints = this.line.points();
|
|
76
84
|
const correctedPoints = this.correctLineIfStraight(originalPoints);
|
|
77
85
|
this.line.points(correctedPoints);
|
|
78
86
|
this.setShapeGroupDone({
|
|
79
87
|
id: group.id(),
|
|
80
|
-
color:
|
|
88
|
+
color: style.color,
|
|
81
89
|
contentsObj: {
|
|
82
90
|
text: ""
|
|
83
91
|
}
|
|
@@ -100,6 +108,7 @@ export class EditorFreeHighlight extends Editor {
|
|
|
100
108
|
* @returns The corrected points
|
|
101
109
|
*/
|
|
102
110
|
correctLineIfStraight(points) {
|
|
111
|
+
if (points.length < 4) return points;
|
|
103
112
|
const THRESHOLD_ANGLE_DEGREES = 2;
|
|
104
113
|
const startX = points[0];
|
|
105
114
|
const startY = points[1];
|
|
@@ -20,6 +20,10 @@ export class EditorFreeHand extends Editor {
|
|
|
20
20
|
if (e.currentTarget !== this.konvaStage) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
24
|
+
const annotation = this.currentAnnotation;
|
|
25
|
+
const style = annotation?.style;
|
|
26
|
+
if (!pos || !annotation || !style) return;
|
|
23
27
|
Editor.TimerClear(this.pageNumber);
|
|
24
28
|
this.line = null;
|
|
25
29
|
this.isPainting = true;
|
|
@@ -27,13 +31,12 @@ export class EditorFreeHand extends Editor {
|
|
|
27
31
|
this.currentShapeGroup = this.createShapeGroup();
|
|
28
32
|
this.getBgLayer().add(this.currentShapeGroup.konvaGroup);
|
|
29
33
|
}
|
|
30
|
-
const pos = this.konvaStage.getRelativePointerPosition();
|
|
31
34
|
this.line = new Konva.Line({
|
|
32
|
-
stroke:
|
|
35
|
+
stroke: style.color,
|
|
33
36
|
// Set the line color
|
|
34
|
-
strokeWidth:
|
|
37
|
+
strokeWidth: style.strokeWidth,
|
|
35
38
|
// Set the line width
|
|
36
|
-
opacity:
|
|
39
|
+
opacity: style.opacity,
|
|
37
40
|
// Set the line opacity
|
|
38
41
|
lineCap: "round",
|
|
39
42
|
// Set rounded line caps
|
|
@@ -59,10 +62,12 @@ export class EditorFreeHand extends Editor {
|
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
64
|
e.evt.preventDefault();
|
|
62
|
-
this.line.show();
|
|
63
65
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
+
const line = this.line;
|
|
67
|
+
if (!pos || !line) return;
|
|
68
|
+
line.show();
|
|
69
|
+
const newPoints = line.points().concat([pos.x, pos.y]);
|
|
70
|
+
line.points(newPoints);
|
|
66
71
|
}
|
|
67
72
|
/**
|
|
68
73
|
* Handles mouse or touch pointer-up events and finishes drawing the freeform curve.
|
|
@@ -72,13 +77,17 @@ export class EditorFreeHand extends Editor {
|
|
|
72
77
|
return;
|
|
73
78
|
}
|
|
74
79
|
this.isPainting = false;
|
|
75
|
-
const
|
|
80
|
+
const line = this.line;
|
|
81
|
+
const group = line?.getParent();
|
|
82
|
+
const style = this.currentAnnotation?.style;
|
|
83
|
+
if (!line || !group || !style) return;
|
|
84
|
+
const color = style.color;
|
|
76
85
|
if (this.isTooSmall()) {
|
|
77
|
-
|
|
86
|
+
line.destroy();
|
|
78
87
|
Editor.TimerStart(this.pageNumber, () => {
|
|
79
88
|
this.setShapeGroupDone({
|
|
80
89
|
id: group.id(),
|
|
81
|
-
color
|
|
90
|
+
color,
|
|
82
91
|
contentsObj: {
|
|
83
92
|
text: ""
|
|
84
93
|
}
|
|
@@ -90,7 +99,7 @@ export class EditorFreeHand extends Editor {
|
|
|
90
99
|
Editor.TimerStart(this.pageNumber, () => {
|
|
91
100
|
this.setShapeGroupDone({
|
|
92
101
|
id: group.id(),
|
|
93
|
-
color
|
|
102
|
+
color,
|
|
94
103
|
contentsObj: {
|
|
95
104
|
text: ""
|
|
96
105
|
}
|
|
@@ -113,7 +122,7 @@ export class EditorFreeHand extends Editor {
|
|
|
113
122
|
* @returns True if the line point count is less than 5, otherwise false
|
|
114
123
|
*/
|
|
115
124
|
isTooSmall() {
|
|
116
|
-
return this.line.points().length < Editor.MinSize;
|
|
125
|
+
return !this.line || this.line.points().length < Editor.MinSize;
|
|
117
126
|
}
|
|
118
127
|
/**
|
|
119
128
|
* @description Update annotation styles
|
|
@@ -5,6 +5,8 @@ import { Editor, type IEditorOptions } from '../editor/editor.js';
|
|
|
5
5
|
* EditorHighLight is a highlight editor class that extends Editor.
|
|
6
6
|
*/
|
|
7
7
|
export declare class EditorHighLight extends Editor {
|
|
8
|
+
private get activeAnnotation();
|
|
9
|
+
private get activeStyle();
|
|
8
10
|
/**
|
|
9
11
|
* Creates an EditorHighLight instance.
|
|
10
12
|
* @param EditorOptions Options used to initialize the editor
|