js-draw 0.19.0 → 0.20.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/.eslintrc.js +1 -0
- package/CHANGELOG.md +3 -0
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/src/Color4.js +3 -3
- package/dist/cjs/src/Editor.js +5 -5
- package/dist/cjs/src/SVGLoader.js +69 -7
- package/dist/cjs/src/Viewport.d.ts +2 -0
- package/dist/cjs/src/Viewport.js +6 -2
- package/dist/cjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
- package/dist/cjs/src/components/BackgroundComponent.js +309 -0
- package/dist/cjs/src/components/Stroke.js +1 -1
- package/dist/cjs/src/components/TextComponent.d.ts +1 -13
- package/dist/cjs/src/components/TextComponent.js +1 -1
- package/dist/cjs/src/components/lib.d.ts +2 -2
- package/dist/cjs/src/components/lib.js +2 -2
- package/dist/cjs/src/components/util/StrokeSmoother.js +25 -15
- package/dist/cjs/src/localizations/de.js +1 -1
- package/dist/cjs/src/localizations/es.js +1 -1
- package/dist/cjs/src/math/Path.js +1 -1
- package/dist/cjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/cjs/src/math/polynomial/QuadraticBezier.js +115 -0
- package/dist/cjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
- package/dist/cjs/src/math/polynomial/solveQuadratic.js +36 -0
- package/dist/cjs/src/rendering/renderers/CanvasRenderer.js +5 -3
- package/dist/cjs/src/rendering/renderers/SVGRenderer.js +15 -6
- package/dist/cjs/src/toolbar/localization.d.ts +2 -1
- package/dist/cjs/src/toolbar/localization.js +2 -1
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
- package/dist/cjs/src/toolbar/widgets/DocumentPropertiesWidget.js +77 -2
- package/dist/cjs/src/toolbar/widgets/PenToolWidget.js +1 -1
- package/dist/cjs/src/tools/FindTool.js +1 -1
- package/dist/cjs/src/tools/SoundUITool.js +1 -1
- package/dist/mjs/src/Color4.mjs +3 -3
- package/dist/mjs/src/Editor.mjs +4 -4
- package/dist/mjs/src/SVGLoader.mjs +68 -6
- package/dist/mjs/src/Viewport.d.ts +2 -0
- package/dist/mjs/src/Viewport.mjs +6 -2
- package/dist/mjs/src/components/{ImageBackground.d.ts → BackgroundComponent.d.ts} +23 -3
- package/dist/mjs/src/components/BackgroundComponent.mjs +279 -0
- package/dist/mjs/src/components/Stroke.mjs +1 -1
- package/dist/mjs/src/components/TextComponent.d.ts +1 -13
- package/dist/mjs/src/components/TextComponent.mjs +1 -1
- package/dist/mjs/src/components/lib.d.ts +2 -2
- package/dist/mjs/src/components/lib.mjs +2 -2
- package/dist/mjs/src/components/util/StrokeSmoother.mjs +25 -15
- package/dist/mjs/src/localizations/de.mjs +1 -1
- package/dist/mjs/src/localizations/es.mjs +1 -1
- package/dist/mjs/src/math/Path.mjs +1 -1
- package/dist/mjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/mjs/src/math/polynomial/QuadraticBezier.mjs +109 -0
- package/dist/mjs/src/math/polynomial/solveQuadratic.d.ts +6 -0
- package/dist/mjs/src/math/polynomial/solveQuadratic.mjs +34 -0
- package/dist/mjs/src/rendering/renderers/CanvasRenderer.mjs +5 -3
- package/dist/mjs/src/rendering/renderers/SVGRenderer.mjs +15 -6
- package/dist/mjs/src/toolbar/localization.d.ts +2 -1
- package/dist/mjs/src/toolbar/localization.mjs +2 -1
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.d.ts +5 -0
- package/dist/mjs/src/toolbar/widgets/DocumentPropertiesWidget.mjs +54 -2
- package/dist/mjs/src/toolbar/widgets/PenToolWidget.mjs +1 -1
- package/dist/mjs/src/tools/FindTool.mjs +1 -1
- package/dist/mjs/src/tools/SoundUITool.mjs +1 -1
- package/jest.config.js +1 -1
- package/package.json +14 -14
- package/dist/cjs/src/components/ImageBackground.js +0 -146
- package/dist/mjs/src/components/ImageBackground.mjs +0 -139
@@ -186,14 +186,16 @@ export default class CanvasRenderer extends AbstractRenderer {
|
|
186
186
|
}
|
187
187
|
}
|
188
188
|
endObject() {
|
189
|
+
// Cache this.objectLevel — it may be decremented by super.endObject.
|
190
|
+
const objectLevel = this.objectLevel;
|
191
|
+
this.currentObjectBBox = null;
|
192
|
+
super.endObject();
|
189
193
|
if (!this.ignoringObject && this.clipLevels.length > 0) {
|
190
|
-
if (this.clipLevels[this.clipLevels.length - 1] ===
|
194
|
+
if (this.clipLevels[this.clipLevels.length - 1] === objectLevel) {
|
191
195
|
this.ctx.restore();
|
192
196
|
this.clipLevels.pop();
|
193
197
|
}
|
194
198
|
}
|
195
|
-
this.currentObjectBBox = null;
|
196
|
-
super.endObject();
|
197
199
|
// If exiting an object with a too-small-to-draw bounding box,
|
198
200
|
if (this.ignoreObjectsAboveLevel !== null && this.getNestingLevel() <= this.ignoreObjectsAboveLevel) {
|
199
201
|
this.ignoreObjectsAboveLevel = null;
|
@@ -3,6 +3,7 @@ import Path from '../../math/Path.mjs';
|
|
3
3
|
import { toRoundedString } from '../../math/rounding.mjs';
|
4
4
|
import { Vec2 } from '../../math/Vec2.mjs';
|
5
5
|
import { svgAttributesDataKey, svgStyleAttributesDataKey } from '../../SVGLoader.mjs';
|
6
|
+
import { stylesEqual } from '../RenderingStyle.mjs';
|
6
7
|
import AbstractRenderer from './AbstractRenderer.mjs';
|
7
8
|
export const renderedStylesheetId = 'js-draw-style-sheet';
|
8
9
|
const svgNameSpace = 'http://www.w3.org/2000/svg';
|
@@ -108,11 +109,10 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
108
109
|
(_a = this.objectElems) === null || _a === void 0 ? void 0 : _a.push(pathElem);
|
109
110
|
}
|
110
111
|
drawPath(pathSpec) {
|
111
|
-
var _a;
|
112
112
|
const style = pathSpec.style;
|
113
113
|
const path = Path.fromRenderable(pathSpec).transformedBy(this.getCanvasToScreenTransform());
|
114
114
|
// Try to extend the previous path, if possible
|
115
|
-
if (
|
115
|
+
if (this.lastPathString.length === 0 || !this.lastPathStyle || !stylesEqual(this.lastPathStyle, style)) {
|
116
116
|
this.addPathToSVG();
|
117
117
|
this.lastPathStyle = style;
|
118
118
|
this.lastPathString = [];
|
@@ -226,7 +226,7 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
226
226
|
this.objectElems = [];
|
227
227
|
}
|
228
228
|
endObject(loaderData, elemClassNames) {
|
229
|
-
var _a
|
229
|
+
var _a;
|
230
230
|
super.endObject(loaderData);
|
231
231
|
// Don't extend paths across objects
|
232
232
|
this.addPathToSVG();
|
@@ -248,9 +248,18 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
248
248
|
}
|
249
249
|
}
|
250
250
|
// Add class names to the object, if given.
|
251
|
-
if (elemClassNames) {
|
252
|
-
|
253
|
-
|
251
|
+
if (elemClassNames && this.objectElems) {
|
252
|
+
if (this.objectElems.length === 1) {
|
253
|
+
this.objectElems[0].classList.add(...elemClassNames);
|
254
|
+
}
|
255
|
+
else {
|
256
|
+
const wrapper = document.createElementNS(svgNameSpace, 'g');
|
257
|
+
wrapper.classList.add(...elemClassNames);
|
258
|
+
for (const elem of this.objectElems) {
|
259
|
+
elem.remove();
|
260
|
+
wrapper.appendChild(elem);
|
261
|
+
}
|
262
|
+
this.elem.appendChild(wrapper);
|
254
263
|
}
|
255
264
|
}
|
256
265
|
}
|
@@ -14,7 +14,7 @@ export interface ToolbarLocalization {
|
|
14
14
|
submit: string;
|
15
15
|
freehandPen: string;
|
16
16
|
pressureSensitiveFreehandPen: string;
|
17
|
-
|
17
|
+
selectPenType: string;
|
18
18
|
colorLabel: string;
|
19
19
|
pen: string;
|
20
20
|
eraser: string;
|
@@ -37,6 +37,7 @@ export interface ToolbarLocalization {
|
|
37
37
|
backgroundColor: string;
|
38
38
|
imageWidthOption: string;
|
39
39
|
imageHeightOption: string;
|
40
|
+
useGridOption: string;
|
40
41
|
toggleOverflow: string;
|
41
42
|
errorImageHasZeroSize: string;
|
42
43
|
dropdownShown: (toolName: string) => string;
|
@@ -20,7 +20,7 @@ export const defaultToolbarLocalization = {
|
|
20
20
|
duplicateSelection: 'Duplicate selection',
|
21
21
|
undo: 'Undo',
|
22
22
|
redo: 'Redo',
|
23
|
-
|
23
|
+
selectPenType: 'Pen type: ',
|
24
24
|
pickColorFromScreen: 'Pick color from screen',
|
25
25
|
clickToPickColorAnnouncement: 'Click on the screen to pick a color',
|
26
26
|
selectionToolKeyboardShortcuts: 'Selection tool: Use arrow keys to move selected items, lowercase/uppercase ‘i’ and ‘o’ to resize.',
|
@@ -28,6 +28,7 @@ export const defaultToolbarLocalization = {
|
|
28
28
|
backgroundColor: 'Background Color: ',
|
29
29
|
imageWidthOption: 'Width: ',
|
30
30
|
imageHeightOption: 'Height: ',
|
31
|
+
useGridOption: 'Grid: ',
|
31
32
|
toggleOverflow: 'More',
|
32
33
|
touchPanning: 'Touchscreen panning',
|
33
34
|
freehandPen: 'Freehand',
|
@@ -12,6 +12,11 @@ export default class DocumentPropertiesWidget extends BaseWidget {
|
|
12
12
|
private updateDropdown;
|
13
13
|
private setBackgroundColor;
|
14
14
|
private getBackgroundColor;
|
15
|
+
private removeBackgroundComponents;
|
16
|
+
/** Replace existing background components with a background of the given type. */
|
17
|
+
private setBackgroundType;
|
18
|
+
/** Returns the type of the topmost background component */
|
19
|
+
private getBackgroundType;
|
15
20
|
private updateImportExportRectSize;
|
16
21
|
private static idCounter;
|
17
22
|
protected fillDropdown(dropdown: HTMLElement): boolean;
|
@@ -1,3 +1,6 @@
|
|
1
|
+
import Erase from '../../commands/Erase.mjs';
|
2
|
+
import uniteCommands from '../../commands/uniteCommands.mjs';
|
3
|
+
import BackgroundComponent, { BackgroundType } from '../../components/BackgroundComponent.mjs';
|
1
4
|
import { EditorImageEventType } from '../../EditorImage.mjs';
|
2
5
|
import Rect2 from '../../math/Rect2.mjs';
|
3
6
|
import { EditorEventType } from '../../types.mjs';
|
@@ -6,7 +9,7 @@ import makeColorInput from '../makeColorInput.mjs';
|
|
6
9
|
import BaseWidget from './BaseWidget.mjs';
|
7
10
|
export default class DocumentPropertiesWidget extends BaseWidget {
|
8
11
|
constructor(editor, localizationTable) {
|
9
|
-
super(editor, '
|
12
|
+
super(editor, 'document-properties-widget', localizationTable);
|
10
13
|
this.updateDropdownContent = () => { };
|
11
14
|
this.dropdownUpdateQueued = false;
|
12
15
|
// Make it possible to open the dropdown, even if this widget isn't selected.
|
@@ -46,6 +49,33 @@ export default class DocumentPropertiesWidget extends BaseWidget {
|
|
46
49
|
getBackgroundColor() {
|
47
50
|
return this.editor.estimateBackgroundColor();
|
48
51
|
}
|
52
|
+
removeBackgroundComponents() {
|
53
|
+
const previousBackgrounds = [];
|
54
|
+
for (const component of this.editor.image.getBackgroundComponents()) {
|
55
|
+
if (component instanceof BackgroundComponent) {
|
56
|
+
previousBackgrounds.push(component);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
return new Erase(previousBackgrounds);
|
60
|
+
}
|
61
|
+
/** Replace existing background components with a background of the given type. */
|
62
|
+
setBackgroundType(backgroundType) {
|
63
|
+
const prevBackgroundColor = this.editor.estimateBackgroundColor();
|
64
|
+
const newBackground = new BackgroundComponent(backgroundType, prevBackgroundColor);
|
65
|
+
const addBackgroundCommand = this.editor.image.addElement(newBackground);
|
66
|
+
return uniteCommands([this.removeBackgroundComponents(), addBackgroundCommand]);
|
67
|
+
}
|
68
|
+
/** Returns the type of the topmost background component */
|
69
|
+
getBackgroundType() {
|
70
|
+
const backgroundComponents = this.editor.image.getBackgroundComponents();
|
71
|
+
for (let i = backgroundComponents.length - 1; i >= 0; i--) {
|
72
|
+
const component = backgroundComponents[i];
|
73
|
+
if (component instanceof BackgroundComponent) {
|
74
|
+
return component.getBackgroundType();
|
75
|
+
}
|
76
|
+
}
|
77
|
+
return BackgroundType.None;
|
78
|
+
}
|
49
79
|
updateImportExportRectSize(size) {
|
50
80
|
const filterDimension = (dim) => {
|
51
81
|
if (dim !== undefined && (!isFinite(dim) || dim <= 0)) {
|
@@ -74,6 +104,27 @@ export default class DocumentPropertiesWidget extends BaseWidget {
|
|
74
104
|
colorInput.id = `${toolbarCSSPrefix}docPropertiesColorInput-${DocumentPropertiesWidget.idCounter++}`;
|
75
105
|
backgroundColorLabel.htmlFor = colorInput.id;
|
76
106
|
backgroundColorRow.replaceChildren(backgroundColorLabel, backgroundColorInputContainer);
|
107
|
+
const useGridRow = document.createElement('div');
|
108
|
+
const useGridLabel = document.createElement('label');
|
109
|
+
const useGridCheckbox = document.createElement('input');
|
110
|
+
useGridCheckbox.id = `${toolbarCSSPrefix}docPropertiesUseGridCheckbox-${DocumentPropertiesWidget.idCounter++}`;
|
111
|
+
useGridLabel.htmlFor = useGridCheckbox.id;
|
112
|
+
useGridCheckbox.type = 'checkbox';
|
113
|
+
useGridLabel.innerText = this.localizationTable.useGridOption;
|
114
|
+
useGridCheckbox.oninput = () => {
|
115
|
+
const prevBackgroundType = this.getBackgroundType();
|
116
|
+
const wasGrid = prevBackgroundType === BackgroundType.Grid;
|
117
|
+
if (wasGrid === useGridCheckbox.checked) {
|
118
|
+
// Already the requested background type.
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
let newBackgroundType = BackgroundType.SolidColor;
|
122
|
+
if (useGridCheckbox.checked) {
|
123
|
+
newBackgroundType = BackgroundType.Grid;
|
124
|
+
}
|
125
|
+
this.editor.dispatch(this.setBackgroundType(newBackgroundType));
|
126
|
+
};
|
127
|
+
useGridRow.replaceChildren(useGridLabel, useGridCheckbox);
|
77
128
|
const addDimensionRow = (labelContent, onChange) => {
|
78
129
|
const row = document.createElement('div');
|
79
130
|
const label = document.createElement('label');
|
@@ -110,9 +161,10 @@ export default class DocumentPropertiesWidget extends BaseWidget {
|
|
110
161
|
const importExportRect = this.editor.getImportExportRect();
|
111
162
|
imageWidthRow.setValue(importExportRect.width);
|
112
163
|
imageHeightRow.setValue(importExportRect.height);
|
164
|
+
useGridCheckbox.checked = this.getBackgroundType() === BackgroundType.Grid;
|
113
165
|
};
|
114
166
|
this.updateDropdownContent();
|
115
|
-
container.replaceChildren(backgroundColorRow, imageWidthRow.element, imageHeightRow.element);
|
167
|
+
container.replaceChildren(backgroundColorRow, useGridRow, imageWidthRow.element, imageHeightRow.element);
|
116
168
|
dropdown.replaceChildren(container);
|
117
169
|
return true;
|
118
170
|
}
|
@@ -110,7 +110,7 @@ export default class PenToolWidget extends BaseToolWidget {
|
|
110
110
|
objectTypeSelect.id = `${toolbarCSSPrefix}penBuilderSelect${PenToolWidget.idCounter++}`;
|
111
111
|
thicknessLabel.innerText = this.localizationTable.thicknessLabel;
|
112
112
|
thicknessLabel.setAttribute('for', thicknessInput.id);
|
113
|
-
objectSelectLabel.innerText = this.localizationTable.
|
113
|
+
objectSelectLabel.innerText = this.localizationTable.selectPenType;
|
114
114
|
objectSelectLabel.setAttribute('for', objectTypeSelect.id);
|
115
115
|
// Use a logarithmic scale for thicknessInput (finer control over thinner strokewidths.)
|
116
116
|
const inverseThicknessInputFn = (t) => Math.log10(t);
|
@@ -69,7 +69,7 @@ class SoundFeedback {
|
|
69
69
|
announceBoundaryCross(boundaryCrossCount) {
|
70
70
|
this.boundaryGain.gain.cancelScheduledValues(this.ctx.currentTime);
|
71
71
|
this.boundaryGain.gain.setValueAtTime(0, this.ctx.currentTime);
|
72
|
-
this.boundaryGain.gain.linearRampToValueAtTime(0.
|
72
|
+
this.boundaryGain.gain.linearRampToValueAtTime(0.018, this.ctx.currentTime + 0.1);
|
73
73
|
this.boundaryOsc.frequency.setValueAtTime(440 + Math.atan(boundaryCrossCount / 2) * 100, this.ctx.currentTime);
|
74
74
|
this.boundaryGain.gain.linearRampToValueAtTime(0, this.ctx.currentTime + 0.25);
|
75
75
|
}
|
package/jest.config.js
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "js-draw",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.20.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/src/lib.d.ts",
|
6
6
|
"main": "./dist/cjs/src/lib.js",
|
@@ -87,27 +87,27 @@
|
|
87
87
|
},
|
88
88
|
"devDependencies": {
|
89
89
|
"@types/bezier-js": "^4.1.0",
|
90
|
-
"@types/jest": "^29.4.
|
90
|
+
"@types/jest": "^29.4.2",
|
91
91
|
"@types/jsdom": "^21.1.0",
|
92
|
-
"@types/node": "^18.
|
93
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
94
|
-
"@typescript-eslint/parser": "^5.
|
92
|
+
"@types/node": "^18.15.3",
|
93
|
+
"@typescript-eslint/eslint-plugin": "^5.55.0",
|
94
|
+
"@typescript-eslint/parser": "^5.55.0",
|
95
95
|
"css-loader": "^6.7.3",
|
96
|
-
"eslint": "^8.
|
96
|
+
"eslint": "^8.36.0",
|
97
97
|
"husky": "^8.0.3",
|
98
|
-
"jest": "^29.
|
99
|
-
"jest-environment-jsdom": "^29.
|
100
|
-
"jsdom": "^21.1.
|
101
|
-
"lint-staged": "^13.
|
98
|
+
"jest": "^29.5.0",
|
99
|
+
"jest-environment-jsdom": "^29.5.0",
|
100
|
+
"jsdom": "^21.1.1",
|
101
|
+
"lint-staged": "^13.2.0",
|
102
102
|
"pinst": "^3.0.0",
|
103
|
-
"style-loader": "^3.3.
|
104
|
-
"terser-webpack-plugin": "^5.3.
|
103
|
+
"style-loader": "^3.3.2",
|
104
|
+
"terser-webpack-plugin": "^5.3.7",
|
105
105
|
"ts-jest": "^29.0.5",
|
106
106
|
"ts-loader": "^9.4.2",
|
107
107
|
"ts-node": "^10.9.1",
|
108
|
-
"typedoc": "^0.23.
|
108
|
+
"typedoc": "^0.23.28",
|
109
109
|
"typescript": "^4.9.5",
|
110
|
-
"webpack": "^5.
|
110
|
+
"webpack": "^5.76.1"
|
111
111
|
},
|
112
112
|
"bugs": {
|
113
113
|
"url": "https://github.com/personalizedrefrigerator/js-draw/issues"
|
@@ -1,146 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.imageBackgroundCSSClassName = exports.BackgroundType = void 0;
|
7
|
-
const Color4_1 = __importDefault(require("../Color4"));
|
8
|
-
const EditorImage_1 = require("../EditorImage");
|
9
|
-
const Rect2_1 = __importDefault(require("../math/Rect2"));
|
10
|
-
const AbstractComponent_1 = __importDefault(require("./AbstractComponent"));
|
11
|
-
const RestylableComponent_1 = require("./RestylableComponent");
|
12
|
-
var BackgroundType;
|
13
|
-
(function (BackgroundType) {
|
14
|
-
BackgroundType[BackgroundType["SolidColor"] = 0] = "SolidColor";
|
15
|
-
BackgroundType[BackgroundType["None"] = 1] = "None";
|
16
|
-
})(BackgroundType = exports.BackgroundType || (exports.BackgroundType = {}));
|
17
|
-
exports.imageBackgroundCSSClassName = 'js-draw-image-background';
|
18
|
-
// Represents the background of the editor's canvas.
|
19
|
-
class ImageBackground extends AbstractComponent_1.default {
|
20
|
-
constructor(backgroundType, mainColor) {
|
21
|
-
super('image-background', 0);
|
22
|
-
this.backgroundType = backgroundType;
|
23
|
-
this.mainColor = mainColor;
|
24
|
-
this.viewportSizeChangeListener = null;
|
25
|
-
// eslint-disable-next-line @typescript-eslint/prefer-as-const
|
26
|
-
this.isRestylableComponent = true;
|
27
|
-
this.contentBBox = Rect2_1.default.empty;
|
28
|
-
}
|
29
|
-
getStyle() {
|
30
|
-
let color = this.mainColor;
|
31
|
-
if (this.backgroundType === BackgroundType.None) {
|
32
|
-
color = undefined;
|
33
|
-
}
|
34
|
-
return {
|
35
|
-
color,
|
36
|
-
};
|
37
|
-
}
|
38
|
-
updateStyle(style) {
|
39
|
-
return (0, RestylableComponent_1.createRestyleComponentCommand)(this.getStyle(), style, this);
|
40
|
-
}
|
41
|
-
// @internal
|
42
|
-
forceStyle(style, editor) {
|
43
|
-
const fill = style.color;
|
44
|
-
if (!fill) {
|
45
|
-
return;
|
46
|
-
}
|
47
|
-
this.mainColor = fill;
|
48
|
-
if (fill.eq(Color4_1.default.transparent)) {
|
49
|
-
this.backgroundType = BackgroundType.None;
|
50
|
-
}
|
51
|
-
else {
|
52
|
-
this.backgroundType = BackgroundType.SolidColor;
|
53
|
-
}
|
54
|
-
if (editor) {
|
55
|
-
editor.image.queueRerenderOf(this);
|
56
|
-
editor.queueRerender();
|
57
|
-
}
|
58
|
-
}
|
59
|
-
onAddToImage(image) {
|
60
|
-
if (this.viewportSizeChangeListener) {
|
61
|
-
console.warn('onAddToImage called when background is already in an image');
|
62
|
-
this.onRemoveFromImage();
|
63
|
-
}
|
64
|
-
this.viewportSizeChangeListener = image.notifier.on(EditorImage_1.EditorImageEventType.ExportViewportChanged, () => {
|
65
|
-
this.recomputeBBox(image);
|
66
|
-
});
|
67
|
-
this.recomputeBBox(image);
|
68
|
-
}
|
69
|
-
onRemoveFromImage() {
|
70
|
-
var _a;
|
71
|
-
(_a = this.viewportSizeChangeListener) === null || _a === void 0 ? void 0 : _a.remove();
|
72
|
-
this.viewportSizeChangeListener = null;
|
73
|
-
}
|
74
|
-
recomputeBBox(image) {
|
75
|
-
const importExportRect = image.getImportExportViewport().visibleRect;
|
76
|
-
if (!this.contentBBox.eq(importExportRect)) {
|
77
|
-
this.contentBBox = importExportRect;
|
78
|
-
// Re-render this if already added to the EditorImage.
|
79
|
-
image.queueRerenderOf(this);
|
80
|
-
}
|
81
|
-
}
|
82
|
-
render(canvas, visibleRect) {
|
83
|
-
if (this.backgroundType === BackgroundType.None) {
|
84
|
-
return;
|
85
|
-
}
|
86
|
-
canvas.startObject(this.contentBBox);
|
87
|
-
if (this.backgroundType === BackgroundType.SolidColor) {
|
88
|
-
// If the rectangle for this region contains the visible rect,
|
89
|
-
// we can fill the entire visible rectangle (which may be more efficient than
|
90
|
-
// filling the entire region for this.)
|
91
|
-
if (visibleRect) {
|
92
|
-
const intersection = visibleRect.intersection(this.contentBBox);
|
93
|
-
if (intersection) {
|
94
|
-
canvas.fillRect(intersection, this.mainColor);
|
95
|
-
}
|
96
|
-
}
|
97
|
-
else {
|
98
|
-
canvas.fillRect(this.contentBBox, this.mainColor);
|
99
|
-
}
|
100
|
-
}
|
101
|
-
canvas.endObject(this.getLoadSaveData(), [exports.imageBackgroundCSSClassName]);
|
102
|
-
}
|
103
|
-
intersects(lineSegment) {
|
104
|
-
return this.contentBBox.getEdges().some(edge => edge.intersects(lineSegment));
|
105
|
-
}
|
106
|
-
isSelectable() {
|
107
|
-
return false;
|
108
|
-
}
|
109
|
-
isBackground() {
|
110
|
-
return true;
|
111
|
-
}
|
112
|
-
serializeToJSON() {
|
113
|
-
return {
|
114
|
-
mainColor: this.mainColor.toHexString(),
|
115
|
-
backgroundType: this.backgroundType,
|
116
|
-
};
|
117
|
-
}
|
118
|
-
applyTransformation(_affineTransfm) {
|
119
|
-
// Do nothing — it doesn't make sense to transform the background.
|
120
|
-
}
|
121
|
-
description(localizationTable) {
|
122
|
-
if (this.backgroundType === BackgroundType.SolidColor) {
|
123
|
-
return localizationTable.filledBackgroundWithColor(this.mainColor.toString());
|
124
|
-
}
|
125
|
-
else {
|
126
|
-
return localizationTable.emptyBackground;
|
127
|
-
}
|
128
|
-
}
|
129
|
-
createClone() {
|
130
|
-
return new ImageBackground(this.backgroundType, this.mainColor);
|
131
|
-
}
|
132
|
-
// @internal
|
133
|
-
static deserializeFromJSON(json) {
|
134
|
-
if (typeof json === 'string') {
|
135
|
-
json = JSON.parse(json);
|
136
|
-
}
|
137
|
-
if (typeof json.mainColor !== 'string') {
|
138
|
-
throw new Error('Error deserializing — mainColor must be of type string.');
|
139
|
-
}
|
140
|
-
const backgroundType = json.backgroundType === BackgroundType.SolidColor ? BackgroundType.SolidColor : BackgroundType.None;
|
141
|
-
const mainColor = Color4_1.default.fromHex(json.mainColor);
|
142
|
-
return new ImageBackground(backgroundType, mainColor);
|
143
|
-
}
|
144
|
-
}
|
145
|
-
exports.default = ImageBackground;
|
146
|
-
AbstractComponent_1.default.registerComponent('image-background', ImageBackground.deserializeFromJSON);
|
@@ -1,139 +0,0 @@
|
|
1
|
-
import Color4 from '../Color4.mjs';
|
2
|
-
import { EditorImageEventType } from '../EditorImage.mjs';
|
3
|
-
import Rect2 from '../math/Rect2.mjs';
|
4
|
-
import AbstractComponent from './AbstractComponent.mjs';
|
5
|
-
import { createRestyleComponentCommand } from './RestylableComponent.mjs';
|
6
|
-
export var BackgroundType;
|
7
|
-
(function (BackgroundType) {
|
8
|
-
BackgroundType[BackgroundType["SolidColor"] = 0] = "SolidColor";
|
9
|
-
BackgroundType[BackgroundType["None"] = 1] = "None";
|
10
|
-
})(BackgroundType || (BackgroundType = {}));
|
11
|
-
export const imageBackgroundCSSClassName = 'js-draw-image-background';
|
12
|
-
// Represents the background of the editor's canvas.
|
13
|
-
export default class ImageBackground extends AbstractComponent {
|
14
|
-
constructor(backgroundType, mainColor) {
|
15
|
-
super('image-background', 0);
|
16
|
-
this.backgroundType = backgroundType;
|
17
|
-
this.mainColor = mainColor;
|
18
|
-
this.viewportSizeChangeListener = null;
|
19
|
-
// eslint-disable-next-line @typescript-eslint/prefer-as-const
|
20
|
-
this.isRestylableComponent = true;
|
21
|
-
this.contentBBox = Rect2.empty;
|
22
|
-
}
|
23
|
-
getStyle() {
|
24
|
-
let color = this.mainColor;
|
25
|
-
if (this.backgroundType === BackgroundType.None) {
|
26
|
-
color = undefined;
|
27
|
-
}
|
28
|
-
return {
|
29
|
-
color,
|
30
|
-
};
|
31
|
-
}
|
32
|
-
updateStyle(style) {
|
33
|
-
return createRestyleComponentCommand(this.getStyle(), style, this);
|
34
|
-
}
|
35
|
-
// @internal
|
36
|
-
forceStyle(style, editor) {
|
37
|
-
const fill = style.color;
|
38
|
-
if (!fill) {
|
39
|
-
return;
|
40
|
-
}
|
41
|
-
this.mainColor = fill;
|
42
|
-
if (fill.eq(Color4.transparent)) {
|
43
|
-
this.backgroundType = BackgroundType.None;
|
44
|
-
}
|
45
|
-
else {
|
46
|
-
this.backgroundType = BackgroundType.SolidColor;
|
47
|
-
}
|
48
|
-
if (editor) {
|
49
|
-
editor.image.queueRerenderOf(this);
|
50
|
-
editor.queueRerender();
|
51
|
-
}
|
52
|
-
}
|
53
|
-
onAddToImage(image) {
|
54
|
-
if (this.viewportSizeChangeListener) {
|
55
|
-
console.warn('onAddToImage called when background is already in an image');
|
56
|
-
this.onRemoveFromImage();
|
57
|
-
}
|
58
|
-
this.viewportSizeChangeListener = image.notifier.on(EditorImageEventType.ExportViewportChanged, () => {
|
59
|
-
this.recomputeBBox(image);
|
60
|
-
});
|
61
|
-
this.recomputeBBox(image);
|
62
|
-
}
|
63
|
-
onRemoveFromImage() {
|
64
|
-
var _a;
|
65
|
-
(_a = this.viewportSizeChangeListener) === null || _a === void 0 ? void 0 : _a.remove();
|
66
|
-
this.viewportSizeChangeListener = null;
|
67
|
-
}
|
68
|
-
recomputeBBox(image) {
|
69
|
-
const importExportRect = image.getImportExportViewport().visibleRect;
|
70
|
-
if (!this.contentBBox.eq(importExportRect)) {
|
71
|
-
this.contentBBox = importExportRect;
|
72
|
-
// Re-render this if already added to the EditorImage.
|
73
|
-
image.queueRerenderOf(this);
|
74
|
-
}
|
75
|
-
}
|
76
|
-
render(canvas, visibleRect) {
|
77
|
-
if (this.backgroundType === BackgroundType.None) {
|
78
|
-
return;
|
79
|
-
}
|
80
|
-
canvas.startObject(this.contentBBox);
|
81
|
-
if (this.backgroundType === BackgroundType.SolidColor) {
|
82
|
-
// If the rectangle for this region contains the visible rect,
|
83
|
-
// we can fill the entire visible rectangle (which may be more efficient than
|
84
|
-
// filling the entire region for this.)
|
85
|
-
if (visibleRect) {
|
86
|
-
const intersection = visibleRect.intersection(this.contentBBox);
|
87
|
-
if (intersection) {
|
88
|
-
canvas.fillRect(intersection, this.mainColor);
|
89
|
-
}
|
90
|
-
}
|
91
|
-
else {
|
92
|
-
canvas.fillRect(this.contentBBox, this.mainColor);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
canvas.endObject(this.getLoadSaveData(), [imageBackgroundCSSClassName]);
|
96
|
-
}
|
97
|
-
intersects(lineSegment) {
|
98
|
-
return this.contentBBox.getEdges().some(edge => edge.intersects(lineSegment));
|
99
|
-
}
|
100
|
-
isSelectable() {
|
101
|
-
return false;
|
102
|
-
}
|
103
|
-
isBackground() {
|
104
|
-
return true;
|
105
|
-
}
|
106
|
-
serializeToJSON() {
|
107
|
-
return {
|
108
|
-
mainColor: this.mainColor.toHexString(),
|
109
|
-
backgroundType: this.backgroundType,
|
110
|
-
};
|
111
|
-
}
|
112
|
-
applyTransformation(_affineTransfm) {
|
113
|
-
// Do nothing — it doesn't make sense to transform the background.
|
114
|
-
}
|
115
|
-
description(localizationTable) {
|
116
|
-
if (this.backgroundType === BackgroundType.SolidColor) {
|
117
|
-
return localizationTable.filledBackgroundWithColor(this.mainColor.toString());
|
118
|
-
}
|
119
|
-
else {
|
120
|
-
return localizationTable.emptyBackground;
|
121
|
-
}
|
122
|
-
}
|
123
|
-
createClone() {
|
124
|
-
return new ImageBackground(this.backgroundType, this.mainColor);
|
125
|
-
}
|
126
|
-
// @internal
|
127
|
-
static deserializeFromJSON(json) {
|
128
|
-
if (typeof json === 'string') {
|
129
|
-
json = JSON.parse(json);
|
130
|
-
}
|
131
|
-
if (typeof json.mainColor !== 'string') {
|
132
|
-
throw new Error('Error deserializing — mainColor must be of type string.');
|
133
|
-
}
|
134
|
-
const backgroundType = json.backgroundType === BackgroundType.SolidColor ? BackgroundType.SolidColor : BackgroundType.None;
|
135
|
-
const mainColor = Color4.fromHex(json.mainColor);
|
136
|
-
return new ImageBackground(backgroundType, mainColor);
|
137
|
-
}
|
138
|
-
}
|
139
|
-
AbstractComponent.registerComponent('image-background', ImageBackground.deserializeFromJSON);
|