js-draw 1.9.1 → 1.10.0
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/Editor.css +48 -1
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.d.ts +41 -0
- package/dist/cjs/Editor.js +9 -0
- package/dist/cjs/Pointer.js +1 -1
- package/dist/cjs/commands/Erase.d.ts +22 -2
- package/dist/cjs/commands/Erase.js +22 -2
- package/dist/cjs/commands/uniteCommands.d.ts +36 -0
- package/dist/cjs/commands/uniteCommands.js +36 -0
- package/dist/cjs/components/ImageComponent.d.ts +12 -0
- package/dist/cjs/components/ImageComponent.js +16 -9
- package/dist/cjs/components/Stroke.d.ts +16 -2
- package/dist/cjs/components/Stroke.js +17 -1
- package/dist/cjs/components/builders/ArrowBuilder.js +3 -3
- package/dist/cjs/components/builders/CircleBuilder.js +3 -3
- package/dist/cjs/components/builders/FreehandLineBuilder.js +3 -3
- package/dist/cjs/components/builders/LineBuilder.js +3 -3
- package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.js +3 -3
- package/dist/cjs/components/builders/RectangleBuilder.js +5 -6
- package/dist/cjs/components/builders/autocorrect/makeShapeFitAutocorrect.d.ts +3 -0
- package/dist/cjs/components/builders/autocorrect/makeShapeFitAutocorrect.js +168 -0
- package/dist/cjs/components/builders/autocorrect/makeSnapToGridAutocorrect.d.ts +3 -0
- package/dist/cjs/components/builders/autocorrect/makeSnapToGridAutocorrect.js +46 -0
- package/dist/cjs/components/builders/types.d.ts +1 -0
- package/dist/cjs/image/EditorImage.d.ts +32 -1
- package/dist/cjs/image/EditorImage.js +32 -1
- package/dist/cjs/rendering/RenderablePathSpec.d.ts +5 -1
- package/dist/cjs/rendering/RenderablePathSpec.js +4 -0
- package/dist/cjs/toolbar/IconProvider.d.ts +2 -0
- package/dist/cjs/toolbar/IconProvider.js +17 -0
- package/dist/cjs/toolbar/localization.d.ts +3 -0
- package/dist/cjs/toolbar/localization.js +4 -1
- package/dist/cjs/toolbar/widgets/InsertImageWidget.d.ts +2 -1
- package/dist/cjs/toolbar/widgets/InsertImageWidget.js +102 -22
- package/dist/cjs/toolbar/widgets/PenToolWidget.d.ts +1 -2
- package/dist/cjs/toolbar/widgets/PenToolWidget.js +50 -20
- package/dist/cjs/tools/Pen.d.ts +9 -0
- package/dist/cjs/tools/Pen.js +77 -3
- package/dist/cjs/tools/TextTool.js +5 -1
- package/dist/cjs/tools/util/StationaryPenDetector.d.ts +22 -0
- package/dist/cjs/tools/util/StationaryPenDetector.js +95 -0
- package/dist/cjs/util/ReactiveValue.d.ts +2 -0
- package/dist/cjs/util/ReactiveValue.js +2 -0
- package/dist/cjs/util/lib.d.ts +1 -0
- package/dist/cjs/util/lib.js +4 -1
- package/dist/cjs/util/waitForImageLoaded.d.ts +2 -0
- package/dist/cjs/util/waitForImageLoaded.js +12 -0
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +41 -0
- package/dist/mjs/Editor.mjs +9 -0
- package/dist/mjs/Pointer.mjs +1 -1
- package/dist/mjs/commands/Erase.d.ts +22 -2
- package/dist/mjs/commands/Erase.mjs +22 -2
- package/dist/mjs/commands/uniteCommands.d.ts +36 -0
- package/dist/mjs/commands/uniteCommands.mjs +36 -0
- package/dist/mjs/components/ImageComponent.d.ts +12 -0
- package/dist/mjs/components/ImageComponent.mjs +16 -9
- package/dist/mjs/components/Stroke.d.ts +16 -2
- package/dist/mjs/components/Stroke.mjs +17 -1
- package/dist/mjs/components/builders/ArrowBuilder.mjs +3 -2
- package/dist/mjs/components/builders/CircleBuilder.mjs +3 -2
- package/dist/mjs/components/builders/FreehandLineBuilder.mjs +3 -2
- package/dist/mjs/components/builders/LineBuilder.mjs +3 -2
- package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.mjs +3 -2
- package/dist/mjs/components/builders/RectangleBuilder.mjs +5 -4
- package/dist/mjs/components/builders/autocorrect/makeShapeFitAutocorrect.d.ts +3 -0
- package/dist/mjs/components/builders/autocorrect/makeShapeFitAutocorrect.mjs +166 -0
- package/dist/mjs/components/builders/autocorrect/makeSnapToGridAutocorrect.d.ts +3 -0
- package/dist/mjs/components/builders/autocorrect/makeSnapToGridAutocorrect.mjs +44 -0
- package/dist/mjs/components/builders/types.d.ts +1 -0
- package/dist/mjs/image/EditorImage.d.ts +32 -1
- package/dist/mjs/image/EditorImage.mjs +32 -1
- package/dist/mjs/rendering/RenderablePathSpec.d.ts +5 -1
- package/dist/mjs/rendering/RenderablePathSpec.mjs +4 -0
- package/dist/mjs/toolbar/IconProvider.d.ts +2 -0
- package/dist/mjs/toolbar/IconProvider.mjs +17 -0
- package/dist/mjs/toolbar/localization.d.ts +3 -0
- package/dist/mjs/toolbar/localization.mjs +4 -1
- package/dist/mjs/toolbar/widgets/InsertImageWidget.d.ts +2 -1
- package/dist/mjs/toolbar/widgets/InsertImageWidget.mjs +102 -22
- package/dist/mjs/toolbar/widgets/PenToolWidget.d.ts +1 -2
- package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +50 -20
- package/dist/mjs/tools/Pen.d.ts +9 -0
- package/dist/mjs/tools/Pen.mjs +77 -3
- package/dist/mjs/tools/TextTool.mjs +5 -1
- package/dist/mjs/tools/util/StationaryPenDetector.d.ts +22 -0
- package/dist/mjs/tools/util/StationaryPenDetector.mjs +92 -0
- package/dist/mjs/util/ReactiveValue.d.ts +2 -0
- package/dist/mjs/util/ReactiveValue.mjs +2 -0
- package/dist/mjs/util/lib.d.ts +1 -0
- package/dist/mjs/util/lib.mjs +1 -0
- package/dist/mjs/util/waitForImageLoaded.d.ts +2 -0
- package/dist/mjs/util/waitForImageLoaded.mjs +10 -0
- package/dist/mjs/version.mjs +1 -1
- package/package.json +3 -3
- package/src/Editor.scss +7 -0
- package/src/toolbar/AbstractToolbar.scss +20 -0
- package/src/toolbar/toolbar.scss +1 -1
- package/src/toolbar/widgets/InsertImageWidget.scss +6 -1
- package/src/toolbar/widgets/PenToolWidget.scss +33 -0
- package/src/tools/SelectionTool/SelectionTool.scss +6 -0
- package/src/toolbar/widgets/PenToolWidget.css +0 -2
package/dist/cjs/util/lib.js
CHANGED
@@ -3,6 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.adjustEditorThemeForContrast = void 0;
|
6
|
+
exports.MutableReactiveValue = exports.ReactiveValue = exports.adjustEditorThemeForContrast = void 0;
|
7
7
|
var adjustEditorThemeForContrast_1 = require("./adjustEditorThemeForContrast");
|
8
8
|
Object.defineProperty(exports, "adjustEditorThemeForContrast", { enumerable: true, get: function () { return __importDefault(adjustEditorThemeForContrast_1).default; } });
|
9
|
+
var ReactiveValue_1 = require("./ReactiveValue");
|
10
|
+
Object.defineProperty(exports, "ReactiveValue", { enumerable: true, get: function () { return ReactiveValue_1.ReactiveValue; } });
|
11
|
+
Object.defineProperty(exports, "MutableReactiveValue", { enumerable: true, get: function () { return ReactiveValue_1.MutableReactiveValue; } });
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const waitForImageLoad = async (image) => {
|
4
|
+
if (!image.complete) {
|
5
|
+
await new Promise((resolve, reject) => {
|
6
|
+
image.onload = event => resolve(event);
|
7
|
+
image.onerror = event => reject(event);
|
8
|
+
image.onabort = event => reject(event);
|
9
|
+
});
|
10
|
+
}
|
11
|
+
};
|
12
|
+
exports.default = waitForImageLoad;
|
package/dist/cjs/version.js
CHANGED
package/dist/mjs/Editor.d.ts
CHANGED
@@ -156,6 +156,38 @@ export declare class Editor {
|
|
156
156
|
readonly toolController: ToolController;
|
157
157
|
/**
|
158
158
|
* Global event dispatcher/subscriber.
|
159
|
+
*
|
160
|
+
* @example
|
161
|
+
*
|
162
|
+
* ```ts,runnable
|
163
|
+
* import { Editor, EditorEventType, SerializableCommand } from 'js-draw';
|
164
|
+
*
|
165
|
+
* // Create a minimal editor
|
166
|
+
* const editor = new Editor(document.body);
|
167
|
+
* editor.addToolbar();
|
168
|
+
*
|
169
|
+
* // Create a place to show text output
|
170
|
+
* const log = document.createElement('textarea');
|
171
|
+
* document.body.appendChild(log);
|
172
|
+
* log.style.width = '100%';
|
173
|
+
* log.style.height = '200px';
|
174
|
+
*
|
175
|
+
* // Listen for CommandDone events (there's also a CommandUndone)
|
176
|
+
* editor.notifier.on(EditorEventType.CommandDone, event => {
|
177
|
+
* // Type narrowing for TypeScript -- event will always be of kind CommandDone,
|
178
|
+
* // but TypeScript doesn't know this.
|
179
|
+
* if (event.kind !== EditorEventType.CommandDone) return;
|
180
|
+
*
|
181
|
+
* log.value = `Command done ${event.command.description(editor, editor.localization)}\n`;
|
182
|
+
*
|
183
|
+
* if (event.command instanceof SerializableCommand) {
|
184
|
+
* log.value += `serializes to: ${JSON.stringify(event.command.serialize())}`;
|
185
|
+
* }
|
186
|
+
* });
|
187
|
+
*
|
188
|
+
* // Dispatch an initial command to trigger the event listener for the first time
|
189
|
+
* editor.dispatch(editor.image.setAutoresizeEnabled(true));
|
190
|
+
* ```
|
159
191
|
*/
|
160
192
|
readonly notifier: EditorNotifier;
|
161
193
|
private loadingWarning;
|
@@ -395,6 +427,12 @@ export declare class Editor {
|
|
395
427
|
* @see {@link sendPenEvent} {@link sendTouchEvent}
|
396
428
|
*/
|
397
429
|
sendPenEvent(eventType: InputEvtType.PointerDownEvt | InputEvtType.PointerMoveEvt | InputEvtType.PointerUpEvt, point: Point2, allPointers?: Pointer[]): void;
|
430
|
+
/**
|
431
|
+
* Adds all components in `components` such that they are in the center of the screen.
|
432
|
+
* This is a convenience method that creates **and applies** a single command.
|
433
|
+
*
|
434
|
+
* If `selectComponents` is true (the default), the components are selected.
|
435
|
+
*/
|
398
436
|
addAndCenterComponents(components: AbstractComponent[], selectComponents?: boolean): Promise<void>;
|
399
437
|
/**
|
400
438
|
* Get a data URL (e.g. as produced by `HTMLCanvasElement::toDataURL`).
|
@@ -403,6 +441,9 @@ export declare class Editor {
|
|
403
441
|
*
|
404
442
|
* The export resolution is the same as the size of the drawing canvas, unless `outputSize`
|
405
443
|
* is given.
|
444
|
+
*
|
445
|
+
* **Example**:
|
446
|
+
* [[include:doc-pages/inline-examples/adding-an-image-and-data-urls.md]]
|
406
447
|
*/
|
407
448
|
toDataURL(format?: 'image/png' | 'image/jpeg' | 'image/webp', outputSize?: Vec2): string;
|
408
449
|
/**
|
package/dist/mjs/Editor.mjs
CHANGED
@@ -886,6 +886,12 @@ export class Editor {
|
|
886
886
|
allPointers) {
|
887
887
|
sendPenEvent(this, eventType, point, allPointers);
|
888
888
|
}
|
889
|
+
/**
|
890
|
+
* Adds all components in `components` such that they are in the center of the screen.
|
891
|
+
* This is a convenience method that creates **and applies** a single command.
|
892
|
+
*
|
893
|
+
* If `selectComponents` is true (the default), the components are selected.
|
894
|
+
*/
|
889
895
|
async addAndCenterComponents(components, selectComponents = true) {
|
890
896
|
let bbox = null;
|
891
897
|
for (const component of components) {
|
@@ -932,6 +938,9 @@ export class Editor {
|
|
932
938
|
*
|
933
939
|
* The export resolution is the same as the size of the drawing canvas, unless `outputSize`
|
934
940
|
* is given.
|
941
|
+
*
|
942
|
+
* **Example**:
|
943
|
+
* [[include:doc-pages/inline-examples/adding-an-image-and-data-urls.md]]
|
935
944
|
*/
|
936
945
|
toDataURL(format = 'image/png', outputSize) {
|
937
946
|
const canvas = document.createElement('canvas');
|
package/dist/mjs/Pointer.mjs
CHANGED
@@ -112,7 +112,7 @@ export default class Pointer {
|
|
112
112
|
// Intended for unit tests.
|
113
113
|
static ofCanvasPoint(canvasPos, isDown, viewport, id = 0, device = PointerDevice.Pen, isPrimary = true, pressure = null) {
|
114
114
|
const screenPos = viewport.canvasToScreen(canvasPos);
|
115
|
-
const timeStamp =
|
115
|
+
const timeStamp = performance.now();
|
116
116
|
return new Pointer(screenPos, canvasPos, pressure, isPrimary, isDown, device, id, timeStamp);
|
117
117
|
}
|
118
118
|
}
|
@@ -5,8 +5,28 @@ import SerializableCommand from './SerializableCommand';
|
|
5
5
|
/**
|
6
6
|
* Removes the given {@link AbstractComponent}s from the image.
|
7
7
|
*
|
8
|
-
*
|
9
|
-
* ```ts
|
8
|
+
* **Example**:
|
9
|
+
* ```ts,runnable
|
10
|
+
* import { Editor, Erase, uniteCommands, Color4, Path, Stroke, Rect2, pathToRenderable } from 'js-draw';
|
11
|
+
*
|
12
|
+
* const editor = new Editor(document.body);
|
13
|
+
* editor.addToolbar();
|
14
|
+
*
|
15
|
+
* // Add a large number of strokes
|
16
|
+
* const commands = [];
|
17
|
+
* for (let x = -20; x < 20; x++) {
|
18
|
+
* for (let y = 0; y < 60; y++) {
|
19
|
+
* const stroke = new Stroke([
|
20
|
+
* pathToRenderable(
|
21
|
+
* Path.fromString(`m${x * 5},${y * 5}l1,1`),
|
22
|
+
* { fill: Color4.transparent, stroke: {width: 2, color: Color4.ofRGB(x / 10, y / 10, 0.5)}} )
|
23
|
+
* ]);
|
24
|
+
* commands.push(editor.image.addElement(stroke));
|
25
|
+
* }
|
26
|
+
* }
|
27
|
+
* await editor.dispatch(uniteCommands(commands, 100));
|
28
|
+
*
|
29
|
+
* ---visible---
|
10
30
|
* // Given some editor...
|
11
31
|
*
|
12
32
|
* // Find all elements intersecting the rectangle with top left (-10,-30) and
|
@@ -5,8 +5,28 @@ import SerializableCommand from './SerializableCommand.mjs';
|
|
5
5
|
/**
|
6
6
|
* Removes the given {@link AbstractComponent}s from the image.
|
7
7
|
*
|
8
|
-
*
|
9
|
-
* ```ts
|
8
|
+
* **Example**:
|
9
|
+
* ```ts,runnable
|
10
|
+
* import { Editor, Erase, uniteCommands, Color4, Path, Stroke, Rect2, pathToRenderable } from 'js-draw';
|
11
|
+
*
|
12
|
+
* const editor = new Editor(document.body);
|
13
|
+
* editor.addToolbar();
|
14
|
+
*
|
15
|
+
* // Add a large number of strokes
|
16
|
+
* const commands = [];
|
17
|
+
* for (let x = -20; x < 20; x++) {
|
18
|
+
* for (let y = 0; y < 60; y++) {
|
19
|
+
* const stroke = new Stroke([
|
20
|
+
* pathToRenderable(
|
21
|
+
* Path.fromString(`m${x * 5},${y * 5}l1,1`),
|
22
|
+
* { fill: Color4.transparent, stroke: {width: 2, color: Color4.ofRGB(x / 10, y / 10, 0.5)}} )
|
23
|
+
* ]);
|
24
|
+
* commands.push(editor.image.addElement(stroke));
|
25
|
+
* }
|
26
|
+
* }
|
27
|
+
* await editor.dispatch(uniteCommands(commands, 100));
|
28
|
+
*
|
29
|
+
* ---visible---
|
10
30
|
* // Given some editor...
|
11
31
|
*
|
12
32
|
* // Find all elements intersecting the rectangle with top left (-10,-30) and
|
@@ -1,4 +1,40 @@
|
|
1
1
|
import Command from './Command';
|
2
2
|
import SerializableCommand from './SerializableCommand';
|
3
|
+
/**
|
4
|
+
* Creates a single command from `commands`. This is useful when undoing should undo *all* commands
|
5
|
+
* in `commands` at once, rather than one at a time.
|
6
|
+
*
|
7
|
+
* @example
|
8
|
+
*
|
9
|
+
* ```ts,runnable
|
10
|
+
* import { Editor, pathToRenderable, Stroke, uniteCommands } from 'js-draw';
|
11
|
+
* import { Path, Color4 } from '@js-draw/math';
|
12
|
+
*
|
13
|
+
* const editor = new Editor(document.body);
|
14
|
+
* editor.addToolbar();
|
15
|
+
*
|
16
|
+
* // Create strokes!
|
17
|
+
* const strokes = [];
|
18
|
+
* for (let i = 0; i < 10; i++) {
|
19
|
+
* const renderablePath = pathToRenderable(
|
20
|
+
* Path.fromString(`M0,${i * 10} L100,100 L300,30 z`),
|
21
|
+
* { fill: Color4.transparent, stroke: { color: Color4.red, width: 1, } }
|
22
|
+
* );
|
23
|
+
* strokes.push(new Stroke([ renderablePath ]));
|
24
|
+
* }
|
25
|
+
*
|
26
|
+
* // Convert to commands
|
27
|
+
* const addStrokesCommands = strokes.map(stroke => editor.image.addElement(stroke));
|
28
|
+
*
|
29
|
+
* // Apply all as a single undoable command (try applying each in a loop instead!)
|
30
|
+
* await editor.dispatch(uniteCommands(addStrokesCommands));
|
31
|
+
*
|
32
|
+
* // The second parameter to uniteCommands is for very large numbers of commands, when
|
33
|
+
* // applying them shouldn't be done all at once (which would block the UI).
|
34
|
+
*
|
35
|
+
* // The second parameter to uniteCommands is for very large numbers of commands, when
|
36
|
+
* // applying them shouldn't be done all at once (which would block the UI).
|
37
|
+
* ```
|
38
|
+
*/
|
3
39
|
declare const uniteCommands: <T extends Command>(commands: T[], applyChunkSize?: number) => T extends SerializableCommand ? SerializableCommand : Command;
|
4
40
|
export default uniteCommands;
|
@@ -84,6 +84,42 @@ class SerializableUnion extends SerializableCommand {
|
|
84
84
|
return this.nonserializableCommand.description(editor, localizationTable);
|
85
85
|
}
|
86
86
|
}
|
87
|
+
/**
|
88
|
+
* Creates a single command from `commands`. This is useful when undoing should undo *all* commands
|
89
|
+
* in `commands` at once, rather than one at a time.
|
90
|
+
*
|
91
|
+
* @example
|
92
|
+
*
|
93
|
+
* ```ts,runnable
|
94
|
+
* import { Editor, pathToRenderable, Stroke, uniteCommands } from 'js-draw';
|
95
|
+
* import { Path, Color4 } from '@js-draw/math';
|
96
|
+
*
|
97
|
+
* const editor = new Editor(document.body);
|
98
|
+
* editor.addToolbar();
|
99
|
+
*
|
100
|
+
* // Create strokes!
|
101
|
+
* const strokes = [];
|
102
|
+
* for (let i = 0; i < 10; i++) {
|
103
|
+
* const renderablePath = pathToRenderable(
|
104
|
+
* Path.fromString(`M0,${i * 10} L100,100 L300,30 z`),
|
105
|
+
* { fill: Color4.transparent, stroke: { color: Color4.red, width: 1, } }
|
106
|
+
* );
|
107
|
+
* strokes.push(new Stroke([ renderablePath ]));
|
108
|
+
* }
|
109
|
+
*
|
110
|
+
* // Convert to commands
|
111
|
+
* const addStrokesCommands = strokes.map(stroke => editor.image.addElement(stroke));
|
112
|
+
*
|
113
|
+
* // Apply all as a single undoable command (try applying each in a loop instead!)
|
114
|
+
* await editor.dispatch(uniteCommands(addStrokesCommands));
|
115
|
+
*
|
116
|
+
* // The second parameter to uniteCommands is for very large numbers of commands, when
|
117
|
+
* // applying them shouldn't be done all at once (which would block the UI).
|
118
|
+
*
|
119
|
+
* // The second parameter to uniteCommands is for very large numbers of commands, when
|
120
|
+
* // applying them shouldn't be done all at once (which would block the UI).
|
121
|
+
* ```
|
122
|
+
*/
|
87
123
|
const uniteCommands = (commands, applyChunkSize) => {
|
88
124
|
let allSerializable = true;
|
89
125
|
for (const command of commands) {
|
@@ -2,12 +2,24 @@ import { Mat33Array, Rect2, Mat33, LineSegment2 } from '@js-draw/math';
|
|
2
2
|
import AbstractRenderer, { RenderableImage } from '../rendering/renderers/AbstractRenderer';
|
3
3
|
import AbstractComponent from './AbstractComponent';
|
4
4
|
import { ImageComponentLocalization } from './localization';
|
5
|
+
/**
|
6
|
+
* Represents a raster image.
|
7
|
+
*
|
8
|
+
* **Example: Adding images**:
|
9
|
+
* [[include:doc-pages/inline-examples/adding-an-image-and-data-urls.md]]
|
10
|
+
*/
|
5
11
|
export default class ImageComponent extends AbstractComponent {
|
6
12
|
protected contentBBox: Rect2;
|
7
13
|
private image;
|
8
14
|
constructor(image: RenderableImage);
|
9
15
|
private getImageRect;
|
10
16
|
private recomputeBBox;
|
17
|
+
/**
|
18
|
+
* Load from an image. Waits for the image to load if incomplete.
|
19
|
+
*
|
20
|
+
* The image, `elem`, must not [taint](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image#security_and_tainted_canvases)
|
21
|
+
* an HTMLCanvasElement when rendered.
|
22
|
+
*/
|
11
23
|
static fromImage(elem: HTMLImageElement, transform: Mat33): Promise<ImageComponent>;
|
12
24
|
render(canvas: AbstractRenderer, _visibleRect?: Rect2): void;
|
13
25
|
getProportionalRenderingTime(): number;
|
@@ -1,7 +1,13 @@
|
|
1
1
|
import { Rect2, Mat33 } from '@js-draw/math';
|
2
2
|
import { assertIsNumber, assertIsNumberArray } from '../util/assertions.mjs';
|
3
3
|
import AbstractComponent from './AbstractComponent.mjs';
|
4
|
-
|
4
|
+
import waitForImageLoaded from '../util/waitForImageLoaded.mjs';
|
5
|
+
/**
|
6
|
+
* Represents a raster image.
|
7
|
+
*
|
8
|
+
* **Example: Adding images**:
|
9
|
+
* [[include:doc-pages/inline-examples/adding-an-image-and-data-urls.md]]
|
10
|
+
*/
|
5
11
|
export default class ImageComponent extends AbstractComponent {
|
6
12
|
constructor(image) {
|
7
13
|
super('image-component');
|
@@ -24,15 +30,14 @@ export default class ImageComponent extends AbstractComponent {
|
|
24
30
|
this.contentBBox = this.getImageRect();
|
25
31
|
this.contentBBox = this.contentBBox.transformedBoundingBox(this.image.transform);
|
26
32
|
}
|
27
|
-
|
33
|
+
/**
|
34
|
+
* Load from an image. Waits for the image to load if incomplete.
|
35
|
+
*
|
36
|
+
* The image, `elem`, must not [taint](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image#security_and_tainted_canvases)
|
37
|
+
* an HTMLCanvasElement when rendered.
|
38
|
+
*/
|
28
39
|
static async fromImage(elem, transform) {
|
29
|
-
|
30
|
-
await new Promise((resolve, reject) => {
|
31
|
-
elem.onload = resolve;
|
32
|
-
elem.onerror = reject;
|
33
|
-
elem.onabort = reject;
|
34
|
-
});
|
35
|
-
}
|
40
|
+
await waitForImageLoaded(elem);
|
36
41
|
let width, height;
|
37
42
|
if (typeof elem.width === 'number' && typeof elem.height === 'number'
|
38
43
|
&& elem.width !== 0 && elem.height !== 0) {
|
@@ -74,6 +79,7 @@ export default class ImageComponent extends AbstractComponent {
|
|
74
79
|
canvas.drawImage(this.image);
|
75
80
|
canvas.endObject(this.getLoadSaveData());
|
76
81
|
}
|
82
|
+
// A *very* rough estimate of how long it takes to render this component
|
77
83
|
getProportionalRenderingTime() {
|
78
84
|
// Estimate: Equivalent to a stroke with 10 segments.
|
79
85
|
return 10;
|
@@ -98,6 +104,7 @@ export default class ImageComponent extends AbstractComponent {
|
|
98
104
|
getAltText() {
|
99
105
|
return this.image.label;
|
100
106
|
}
|
107
|
+
// The base64 image URL of this image.
|
101
108
|
getURL() {
|
102
109
|
return this.image.base64Url;
|
103
110
|
}
|
@@ -5,7 +5,7 @@ import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
|
|
5
5
|
import AbstractComponent from './AbstractComponent';
|
6
6
|
import { ImageComponentLocalization } from './localization';
|
7
7
|
import RestyleableComponent, { ComponentStyle } from './RestylableComponent';
|
8
|
-
import RenderablePathSpec from '../rendering/RenderablePathSpec';
|
8
|
+
import RenderablePathSpec, { RenderablePathSpecWithPath } from '../rendering/RenderablePathSpec';
|
9
9
|
/**
|
10
10
|
* Represents an {@link AbstractComponent} made up of one or more {@link Path}s.
|
11
11
|
*
|
@@ -21,6 +21,9 @@ import RenderablePathSpec from '../rendering/RenderablePathSpec';
|
|
21
21
|
* ```ts
|
22
22
|
* editor.dispatch(stroke.transformBy(Mat33.translation(Vec2.of(10, 0))));
|
23
23
|
* ```
|
24
|
+
*
|
25
|
+
* **Adding**:
|
26
|
+
* [[include:doc-pages/inline-examples/adding-a-stroke.md]]
|
24
27
|
*/
|
25
28
|
export default class Stroke extends AbstractComponent implements RestyleableComponent {
|
26
29
|
private parts;
|
@@ -39,7 +42,7 @@ export default class Stroke extends AbstractComponent implements RestyleableComp
|
|
39
42
|
*
|
40
43
|
* const stroke = new Stroke([
|
41
44
|
* // Fill with red
|
42
|
-
* pathToRenderable({ fill: Color4.red })
|
45
|
+
* pathToRenderable(path, { fill: Color4.red })
|
43
46
|
* ]);
|
44
47
|
* ```
|
45
48
|
*/
|
@@ -57,6 +60,17 @@ export default class Stroke extends AbstractComponent implements RestyleableComp
|
|
57
60
|
private bboxForPart;
|
58
61
|
getExactBBox(): Rect2;
|
59
62
|
protected applyTransformation(affineTransfm: Mat33): void;
|
63
|
+
/**
|
64
|
+
* @returns A list of the parts that make up this path. Many paths only have one part.
|
65
|
+
*
|
66
|
+
* Each part (a {@link RenderablePathSpec}) contains information about the style and geometry
|
67
|
+
* of that part of the stroke. Use the `.path` property to do collision detection and other
|
68
|
+
* operations involving the stroke's geometry.
|
69
|
+
*
|
70
|
+
* Note that many of {@link Path}'s methods (e.g. {@link Path.intersection}) take a
|
71
|
+
* `strokeWidth` parameter that can be gotten from {@link RenderablePathSpec.style} `.stroke.width`.
|
72
|
+
*/
|
73
|
+
getParts(): Readonly<RenderablePathSpecWithPath>[];
|
60
74
|
/**
|
61
75
|
* @returns the {@link Path.union} of all paths that make up this stroke.
|
62
76
|
*/
|
@@ -18,6 +18,9 @@ import { pathFromRenderable, pathToRenderable, simplifyPathToFullScreenOrEmpty
|
|
18
18
|
* ```ts
|
19
19
|
* editor.dispatch(stroke.transformBy(Mat33.translation(Vec2.of(10, 0))));
|
20
20
|
* ```
|
21
|
+
*
|
22
|
+
* **Adding**:
|
23
|
+
* [[include:doc-pages/inline-examples/adding-a-stroke.md]]
|
21
24
|
*/
|
22
25
|
export default class Stroke extends AbstractComponent {
|
23
26
|
/**
|
@@ -32,7 +35,7 @@ export default class Stroke extends AbstractComponent {
|
|
32
35
|
*
|
33
36
|
* const stroke = new Stroke([
|
34
37
|
* // Fill with red
|
35
|
-
* pathToRenderable({ fill: Color4.red })
|
38
|
+
* pathToRenderable(path, { fill: Color4.red })
|
36
39
|
* ]);
|
37
40
|
* ```
|
38
41
|
*/
|
@@ -290,6 +293,19 @@ export default class Stroke extends AbstractComponent {
|
|
290
293
|
};
|
291
294
|
});
|
292
295
|
}
|
296
|
+
/**
|
297
|
+
* @returns A list of the parts that make up this path. Many paths only have one part.
|
298
|
+
*
|
299
|
+
* Each part (a {@link RenderablePathSpec}) contains information about the style and geometry
|
300
|
+
* of that part of the stroke. Use the `.path` property to do collision detection and other
|
301
|
+
* operations involving the stroke's geometry.
|
302
|
+
*
|
303
|
+
* Note that many of {@link Path}'s methods (e.g. {@link Path.intersection}) take a
|
304
|
+
* `strokeWidth` parameter that can be gotten from {@link RenderablePathSpec.style} `.stroke.width`.
|
305
|
+
*/
|
306
|
+
getParts() {
|
307
|
+
return [...this.parts];
|
308
|
+
}
|
293
309
|
/**
|
294
310
|
* @returns the {@link Path.union} of all paths that make up this stroke.
|
295
311
|
*/
|
@@ -1,8 +1,9 @@
|
|
1
1
|
import { Path, PathCommandType } from '@js-draw/math';
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
|
-
|
3
|
+
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
4
|
+
export const makeArrowBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
4
5
|
return new ArrowBuilder(initialPoint, viewport);
|
5
|
-
};
|
6
|
+
});
|
6
7
|
export default class ArrowBuilder {
|
7
8
|
constructor(startPoint, viewport) {
|
8
9
|
this.startPoint = startPoint;
|
@@ -2,9 +2,10 @@ import { Vec2, Path, PathCommandType, Color4 } from '@js-draw/math';
|
|
2
2
|
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import Stroke from '../Stroke.mjs';
|
5
|
-
|
5
|
+
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
6
|
+
export const makeOutlinedCircleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
6
7
|
return new CircleBuilder(initialPoint, viewport);
|
7
|
-
};
|
8
|
+
});
|
8
9
|
class CircleBuilder {
|
9
10
|
constructor(startPoint, viewport) {
|
10
11
|
this.startPoint = startPoint;
|
@@ -2,13 +2,14 @@ import { Vec2, Rect2, Color4, PathCommandType } from '@js-draw/math';
|
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import { StrokeSmoother } from '../util/StrokeSmoother.mjs';
|
5
|
-
|
5
|
+
import makeShapeFitAutocorrect from './autocorrect/makeShapeFitAutocorrect.mjs';
|
6
|
+
export const makeFreehandLineBuilder = makeShapeFitAutocorrect((initialPoint, viewport) => {
|
6
7
|
// Don't smooth if input is more than ± 3 pixels from the true curve, do smooth if
|
7
8
|
// less than ±1 px from the curve.
|
8
9
|
const maxSmoothingDist = viewport.getSizeOfPixelOnCanvas() * 3;
|
9
10
|
const minSmoothingDist = viewport.getSizeOfPixelOnCanvas();
|
10
11
|
return new FreehandLineBuilder(initialPoint, minSmoothingDist, maxSmoothingDist, viewport);
|
11
|
-
};
|
12
|
+
});
|
12
13
|
// Handles stroke smoothing and creates Strokes from user/stylus input.
|
13
14
|
export default class FreehandLineBuilder {
|
14
15
|
constructor(startPoint, minFitAllowed, maxFitAllowed, viewport) {
|
@@ -1,9 +1,10 @@
|
|
1
1
|
import { Path, PathCommandType } from '@js-draw/math';
|
2
2
|
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
3
3
|
import Stroke from '../Stroke.mjs';
|
4
|
-
|
4
|
+
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
5
|
+
export const makeLineBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
5
6
|
return new LineBuilder(initialPoint, viewport);
|
6
|
-
};
|
7
|
+
});
|
7
8
|
export default class LineBuilder {
|
8
9
|
constructor(startPoint, viewport) {
|
9
10
|
this.startPoint = startPoint;
|
@@ -3,13 +3,14 @@ import { Vec2, Rect2, PathCommandType } from '@js-draw/math';
|
|
3
3
|
import Stroke from '../Stroke.mjs';
|
4
4
|
import Viewport from '../../Viewport.mjs';
|
5
5
|
import { StrokeSmoother } from '../util/StrokeSmoother.mjs';
|
6
|
-
|
6
|
+
import makeShapeFitAutocorrect from './autocorrect/makeShapeFitAutocorrect.mjs';
|
7
|
+
export const makePressureSensitiveFreehandLineBuilder = makeShapeFitAutocorrect((initialPoint, viewport) => {
|
7
8
|
// Don't smooth if input is more than ± 3 pixels from the true curve, do smooth if
|
8
9
|
// less than ±1 px from the curve.
|
9
10
|
const maxSmoothingDist = viewport.getSizeOfPixelOnCanvas() * 3;
|
10
11
|
const minSmoothingDist = viewport.getSizeOfPixelOnCanvas();
|
11
12
|
return new PressureSensitiveFreehandLineBuilder(initialPoint, minSmoothingDist, maxSmoothingDist, viewport);
|
12
|
-
};
|
13
|
+
});
|
13
14
|
// Handles stroke smoothing and creates Strokes from user/stylus input.
|
14
15
|
export default class PressureSensitiveFreehandLineBuilder {
|
15
16
|
constructor(startPoint,
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import { Mat33, Rect2, Path } from '@js-draw/math';
|
2
2
|
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
3
3
|
import Stroke from '../Stroke.mjs';
|
4
|
-
|
4
|
+
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
5
|
+
export const makeFilledRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
5
6
|
return new RectangleBuilder(initialPoint, true, viewport);
|
6
|
-
};
|
7
|
-
export const makeOutlinedRectangleBuilder = (initialPoint, viewport) => {
|
7
|
+
});
|
8
|
+
export const makeOutlinedRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
8
9
|
return new RectangleBuilder(initialPoint, false, viewport);
|
9
|
-
};
|
10
|
+
});
|
10
11
|
export default class RectangleBuilder {
|
11
12
|
constructor(startPoint, filled, viewport) {
|
12
13
|
this.startPoint = startPoint;
|