js-draw 1.17.0 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +70 -10
- package/dist/bundle.js +2 -2
- package/dist/cjs/Editor.d.ts +18 -20
- package/dist/cjs/Editor.js +5 -2
- package/dist/cjs/components/AbstractComponent.d.ts +17 -5
- package/dist/cjs/components/AbstractComponent.js +15 -15
- package/dist/cjs/components/Stroke.d.ts +4 -1
- package/dist/cjs/components/Stroke.js +158 -2
- package/dist/cjs/components/builders/PolylineBuilder.d.ts +1 -1
- package/dist/cjs/components/builders/PolylineBuilder.js +9 -2
- package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.d.ts +1 -1
- package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.js +44 -51
- package/dist/cjs/image/EditorImage.js +1 -1
- package/dist/cjs/localizations/de.js +1 -1
- package/dist/cjs/localizations/es.js +1 -1
- package/dist/cjs/testing/createEditor.d.ts +2 -2
- package/dist/cjs/testing/createEditor.js +2 -2
- package/dist/cjs/toolbar/IconProvider.d.ts +3 -1
- package/dist/cjs/toolbar/IconProvider.js +15 -3
- package/dist/cjs/toolbar/localization.d.ts +6 -1
- package/dist/cjs/toolbar/localization.js +7 -2
- package/dist/cjs/toolbar/widgets/EraserToolWidget.d.ts +6 -1
- package/dist/cjs/toolbar/widgets/EraserToolWidget.js +45 -5
- package/dist/cjs/toolbar/widgets/PenToolWidget.js +10 -3
- package/dist/cjs/toolbar/widgets/PenToolWidget.test.d.ts +1 -0
- package/dist/cjs/toolbar/widgets/keybindings.js +1 -1
- package/dist/cjs/tools/Eraser.d.ts +24 -4
- package/dist/cjs/tools/Eraser.js +107 -20
- package/dist/cjs/tools/PasteHandler.js +0 -1
- package/dist/cjs/tools/lib.d.ts +1 -4
- package/dist/cjs/tools/lib.js +2 -4
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +18 -20
- package/dist/mjs/Editor.mjs +5 -2
- package/dist/mjs/components/AbstractComponent.d.ts +17 -5
- package/dist/mjs/components/AbstractComponent.mjs +15 -15
- package/dist/mjs/components/Stroke.d.ts +4 -1
- package/dist/mjs/components/Stroke.mjs +159 -3
- package/dist/mjs/components/builders/PolylineBuilder.d.ts +1 -1
- package/dist/mjs/components/builders/PolylineBuilder.mjs +10 -3
- package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.d.ts +1 -1
- package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.mjs +45 -52
- package/dist/mjs/image/EditorImage.mjs +1 -1
- package/dist/mjs/localizations/de.mjs +1 -1
- package/dist/mjs/localizations/es.mjs +1 -1
- package/dist/mjs/testing/createEditor.d.ts +2 -2
- package/dist/mjs/testing/createEditor.mjs +2 -2
- package/dist/mjs/toolbar/IconProvider.d.ts +3 -1
- package/dist/mjs/toolbar/IconProvider.mjs +15 -3
- package/dist/mjs/toolbar/localization.d.ts +6 -1
- package/dist/mjs/toolbar/localization.mjs +7 -2
- package/dist/mjs/toolbar/widgets/EraserToolWidget.d.ts +6 -1
- package/dist/mjs/toolbar/widgets/EraserToolWidget.mjs +47 -6
- package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +10 -3
- package/dist/mjs/toolbar/widgets/PenToolWidget.test.d.ts +1 -0
- package/dist/mjs/toolbar/widgets/keybindings.mjs +1 -1
- package/dist/mjs/tools/Eraser.d.ts +24 -4
- package/dist/mjs/tools/Eraser.mjs +107 -21
- package/dist/mjs/tools/PasteHandler.mjs +0 -1
- package/dist/mjs/tools/lib.d.ts +1 -4
- package/dist/mjs/tools/lib.mjs +1 -4
- package/dist/mjs/version.mjs +1 -1
- package/package.json +3 -3
@@ -1,19 +1,28 @@
|
|
1
1
|
import { EditorEventType } from '../types.mjs';
|
2
2
|
import BaseTool from './BaseTool.mjs';
|
3
|
-
import { Vec2, LineSegment2, Color4, Rect2 } from '@js-draw/math';
|
3
|
+
import { Vec2, LineSegment2, Color4, Rect2, Path } from '@js-draw/math';
|
4
4
|
import Erase from '../commands/Erase.mjs';
|
5
5
|
import { PointerDevice } from '../Pointer.mjs';
|
6
6
|
import { decreaseSizeKeyboardShortcutId, increaseSizeKeyboardShortcutId } from './keybindings.mjs';
|
7
7
|
import { ReactiveValue } from '../util/ReactiveValue.mjs';
|
8
|
+
import EditorImage from '../image/EditorImage.mjs';
|
9
|
+
import uniteCommands from '../commands/uniteCommands.mjs';
|
10
|
+
import { pathToRenderable } from '../rendering/RenderablePathSpec.mjs';
|
11
|
+
export var EraserMode;
|
12
|
+
(function (EraserMode) {
|
13
|
+
EraserMode["PartialStroke"] = "partial-stroke";
|
14
|
+
EraserMode["FullStroke"] = "full-stroke";
|
15
|
+
})(EraserMode || (EraserMode = {}));
|
8
16
|
export default class Eraser extends BaseTool {
|
9
|
-
constructor(editor, description) {
|
17
|
+
constructor(editor, description, options) {
|
10
18
|
super(editor.notifier, description);
|
11
19
|
this.editor = editor;
|
12
20
|
this.lastPoint = null;
|
13
21
|
this.isFirstEraseEvt = true;
|
14
|
-
this.thickness = 10;
|
15
22
|
// Commands that each remove one element
|
16
|
-
this.
|
23
|
+
this.eraseCommands = [];
|
24
|
+
this.addCommands = [];
|
25
|
+
this.thickness = options?.thickness ?? 10;
|
17
26
|
this.thicknessValue = ReactiveValue.fromInitialValue(this.thickness);
|
18
27
|
this.thicknessValue.onUpdate(value => {
|
19
28
|
this.thickness = value;
|
@@ -22,6 +31,13 @@ export default class Eraser extends BaseTool {
|
|
22
31
|
tool: this,
|
23
32
|
});
|
24
33
|
});
|
34
|
+
this.modeValue = ReactiveValue.fromInitialValue(options?.mode ?? EraserMode.FullStroke);
|
35
|
+
this.modeValue.onUpdate(_value => {
|
36
|
+
this.editor.notifier.dispatch(EditorEventType.ToolUpdated, {
|
37
|
+
kind: EditorEventType.ToolUpdated,
|
38
|
+
tool: this,
|
39
|
+
});
|
40
|
+
});
|
25
41
|
}
|
26
42
|
clearPreview() {
|
27
43
|
this.editor.clearWetInk();
|
@@ -34,16 +50,24 @@ export default class Eraser extends BaseTool {
|
|
34
50
|
const size = this.getSizeOnCanvas();
|
35
51
|
const renderer = this.editor.display.getWetInkRenderer();
|
36
52
|
const rect = this.getEraserRect(point);
|
53
|
+
const rect2 = this.getEraserRect(this.lastPoint ?? point);
|
37
54
|
const fill = {
|
38
|
-
fill: Color4.
|
55
|
+
fill: Color4.transparent,
|
56
|
+
stroke: { width: size / 10, color: Color4.gray },
|
39
57
|
};
|
40
|
-
renderer.
|
58
|
+
renderer.drawPath(pathToRenderable(Path.fromConvexHullOf([...rect.corners, ...rect2.corners]), fill));
|
41
59
|
}
|
60
|
+
/**
|
61
|
+
* @returns the eraser rectangle in canvas coordinates.
|
62
|
+
*
|
63
|
+
* For now, all erasers are rectangles or points.
|
64
|
+
*/
|
42
65
|
getEraserRect(centerPoint) {
|
43
66
|
const size = this.getSizeOnCanvas();
|
44
67
|
const halfSize = Vec2.of(size / 2, size / 2);
|
45
68
|
return Rect2.fromCorners(centerPoint.minus(halfSize), centerPoint.plus(halfSize));
|
46
69
|
}
|
70
|
+
/** Erases in a line from the last point to the current. */
|
47
71
|
eraseTo(currentPoint) {
|
48
72
|
if (!this.isFirstEraseEvt && currentPoint.distanceTo(this.lastPoint) === 0) {
|
49
73
|
return;
|
@@ -60,13 +84,55 @@ export default class Eraser extends BaseTool {
|
|
60
84
|
});
|
61
85
|
// Only erase components that could be selected (and thus interacted with)
|
62
86
|
// by the user.
|
63
|
-
const
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
87
|
+
const eraseableElems = intersectingElems.filter(elem => elem.isSelectable());
|
88
|
+
if (this.modeValue.get() === EraserMode.FullStroke) {
|
89
|
+
// Remove any intersecting elements.
|
90
|
+
this.toRemove.push(...eraseableElems);
|
91
|
+
// Create new Erase commands for the now-to-be-erased elements and apply them.
|
92
|
+
const newPartialCommands = eraseableElems.map(elem => new Erase([elem]));
|
93
|
+
newPartialCommands.forEach(cmd => cmd.apply(this.editor));
|
94
|
+
this.eraseCommands.push(...newPartialCommands);
|
95
|
+
}
|
96
|
+
else {
|
97
|
+
const toErase = [];
|
98
|
+
const toAdd = [];
|
99
|
+
for (const targetElem of eraseableElems) {
|
100
|
+
toErase.push(targetElem);
|
101
|
+
// Completely delete items that can't be divided.
|
102
|
+
if (!targetElem.withRegionErased) {
|
103
|
+
continue;
|
104
|
+
}
|
105
|
+
// Completely delete items that are completely or almost completely
|
106
|
+
// contained within the eraser.
|
107
|
+
const grownRect = eraserRect.grownBy(eraserRect.maxDimension / 3);
|
108
|
+
if (grownRect.containsRect(targetElem.getExactBBox())) {
|
109
|
+
continue;
|
110
|
+
}
|
111
|
+
// Join the current and previous rectangles so that points between events are also
|
112
|
+
// erased.
|
113
|
+
const erasePath = Path.fromConvexHullOf([
|
114
|
+
...eraserRect.corners, ...this.getEraserRect(this.lastPoint ?? currentPoint).corners
|
115
|
+
].map(p => this.editor.viewport.roundPoint(p)));
|
116
|
+
toAdd.push(...targetElem.withRegionErased(erasePath, this.editor.viewport));
|
117
|
+
}
|
118
|
+
const eraseCommand = new Erase(toErase);
|
119
|
+
const newAddCommands = toAdd.map(elem => EditorImage.addElement(elem));
|
120
|
+
eraseCommand.apply(this.editor);
|
121
|
+
newAddCommands.forEach(command => command.apply(this.editor));
|
122
|
+
const finalToErase = [];
|
123
|
+
for (const item of toErase) {
|
124
|
+
if (this.toAdd.includes(item)) {
|
125
|
+
this.toAdd = this.toAdd.filter(i => i !== item);
|
126
|
+
}
|
127
|
+
else {
|
128
|
+
finalToErase.push(item);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
this.toRemove.push(...finalToErase);
|
132
|
+
this.toAdd.push(...toAdd);
|
133
|
+
this.eraseCommands.push(new Erase(finalToErase));
|
134
|
+
this.addCommands.push(...newAddCommands);
|
135
|
+
}
|
70
136
|
this.drawPreviewAt(currentPoint);
|
71
137
|
this.lastPoint = currentPoint;
|
72
138
|
}
|
@@ -74,6 +140,7 @@ export default class Eraser extends BaseTool {
|
|
74
140
|
if (event.allPointers.length === 1 || event.current.device === PointerDevice.Eraser) {
|
75
141
|
this.lastPoint = event.current.canvasPos;
|
76
142
|
this.toRemove = [];
|
143
|
+
this.toAdd = [];
|
77
144
|
this.isFirstEraseEvt = true;
|
78
145
|
this.drawPreviewAt(event.current.canvasPos);
|
79
146
|
return true;
|
@@ -86,18 +153,32 @@ export default class Eraser extends BaseTool {
|
|
86
153
|
}
|
87
154
|
onPointerUp(event) {
|
88
155
|
this.eraseTo(event.current.canvasPos);
|
89
|
-
|
156
|
+
const commands = [];
|
157
|
+
if (this.addCommands.length > 0) {
|
158
|
+
this.addCommands.forEach(cmd => cmd.unapply(this.editor));
|
159
|
+
commands.push(...this.toAdd.map(a => EditorImage.addElement(a)));
|
160
|
+
this.addCommands = [];
|
161
|
+
}
|
162
|
+
if (this.eraseCommands.length > 0) {
|
90
163
|
// Undo commands for each individual component and unite into a single command.
|
91
|
-
this.
|
92
|
-
this.
|
164
|
+
this.eraseCommands.forEach(cmd => cmd.unapply(this.editor));
|
165
|
+
this.eraseCommands = [];
|
93
166
|
const command = new Erase(this.toRemove);
|
94
|
-
|
167
|
+
commands.push(command);
|
168
|
+
}
|
169
|
+
if (commands.length === 1) {
|
170
|
+
this.editor.dispatch(commands[0]); // dispatch: Makes undo-able.
|
171
|
+
}
|
172
|
+
else {
|
173
|
+
this.editor.dispatch(uniteCommands(commands));
|
95
174
|
}
|
96
175
|
this.clearPreview();
|
97
176
|
}
|
98
177
|
onGestureCancel() {
|
99
|
-
this.
|
100
|
-
this.
|
178
|
+
this.addCommands.forEach(cmd => cmd.unapply(this.editor));
|
179
|
+
this.eraseCommands.forEach(cmd => cmd.unapply(this.editor));
|
180
|
+
this.eraseCommands = [];
|
181
|
+
this.addCommands = [];
|
101
182
|
this.clearPreview();
|
102
183
|
}
|
103
184
|
onKeyPress(event) {
|
@@ -116,9 +197,14 @@ export default class Eraser extends BaseTool {
|
|
116
197
|
}
|
117
198
|
return false;
|
118
199
|
}
|
200
|
+
/** Returns the side-length of the tip of this eraser. */
|
119
201
|
getThickness() {
|
120
202
|
return this.thickness;
|
121
203
|
}
|
204
|
+
/** Sets the side-length of this' tip. */
|
205
|
+
setThickness(thickness) {
|
206
|
+
this.thicknessValue.set(thickness);
|
207
|
+
}
|
122
208
|
/**
|
123
209
|
* Returns a {@link MutableReactiveValue} that can be used to watch
|
124
210
|
* this tool's thickness.
|
@@ -126,7 +212,7 @@ export default class Eraser extends BaseTool {
|
|
126
212
|
getThicknessValue() {
|
127
213
|
return this.thicknessValue;
|
128
214
|
}
|
129
|
-
|
130
|
-
this.
|
215
|
+
getModeValue() {
|
216
|
+
return this.modeValue;
|
131
217
|
}
|
132
218
|
}
|
package/dist/mjs/tools/lib.d.ts
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
/**
|
2
|
-
* @packageDocumentation
|
3
|
-
*/
|
4
1
|
export { default as BaseTool } from './BaseTool';
|
5
2
|
export { default as ToolController } from './ToolController';
|
6
3
|
export { default as ToolEnabledGroup } from './ToolEnabledGroup';
|
@@ -11,7 +8,7 @@ export { default as PenTool, PenStyle } from './Pen';
|
|
11
8
|
export { default as TextTool } from './TextTool';
|
12
9
|
export { default as SelectionTool } from './SelectionTool/SelectionTool';
|
13
10
|
export { default as SelectAllShortcutHandler } from './SelectionTool/SelectAllShortcutHandler';
|
14
|
-
export { default as EraserTool } from './Eraser';
|
11
|
+
export { default as EraserTool, EraserMode } from './Eraser';
|
15
12
|
export { default as PasteHandler } from './PasteHandler';
|
16
13
|
export { default as SoundUITool } from './SoundUITool';
|
17
14
|
export { default as ToolbarShortcutHandler } from './ToolbarShortcutHandler';
|
package/dist/mjs/tools/lib.mjs
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
/**
|
2
|
-
* @packageDocumentation
|
3
|
-
*/
|
4
1
|
export { default as BaseTool } from './BaseTool.mjs';
|
5
2
|
export { default as ToolController } from './ToolController.mjs';
|
6
3
|
export { default as ToolEnabledGroup } from './ToolEnabledGroup.mjs';
|
@@ -11,7 +8,7 @@ export { default as PenTool } from './Pen.mjs';
|
|
11
8
|
export { default as TextTool } from './TextTool.mjs';
|
12
9
|
export { default as SelectionTool } from './SelectionTool/SelectionTool.mjs';
|
13
10
|
export { default as SelectAllShortcutHandler } from './SelectionTool/SelectAllShortcutHandler.mjs';
|
14
|
-
export { default as EraserTool } from './Eraser.mjs';
|
11
|
+
export { default as EraserTool, EraserMode } from './Eraser.mjs';
|
15
12
|
export { default as PasteHandler } from './PasteHandler.mjs';
|
16
13
|
export { default as SoundUITool } from './SoundUITool.mjs';
|
17
14
|
export { default as ToolbarShortcutHandler } from './ToolbarShortcutHandler.mjs';
|
package/dist/mjs/version.mjs
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "js-draw",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.18.0",
|
4
4
|
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
|
5
5
|
"types": "./dist/mjs/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/lib.js",
|
@@ -64,7 +64,7 @@
|
|
64
64
|
"postpack": "ts-node tools/copyREADME.ts revert"
|
65
65
|
},
|
66
66
|
"dependencies": {
|
67
|
-
"@js-draw/math": "^1.
|
67
|
+
"@js-draw/math": "^1.18.0",
|
68
68
|
"@melloware/coloris": "0.22.0"
|
69
69
|
},
|
70
70
|
"devDependencies": {
|
@@ -86,5 +86,5 @@
|
|
86
86
|
"freehand",
|
87
87
|
"svg"
|
88
88
|
],
|
89
|
-
"gitHead": "
|
89
|
+
"gitHead": "73c0d802a8439b5d408ba1e60f91be029db7e402"
|
90
90
|
}
|