js-draw 0.19.0 → 0.21.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 +11 -0
- package/README.md +4 -4
- 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.d.ts +4 -1
- package/dist/cjs/src/Editor.js +30 -12
- 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/AbstractComponent.d.ts +13 -1
- package/dist/cjs/src/components/AbstractComponent.js +19 -9
- 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.d.ts +1 -0
- package/dist/cjs/src/components/Stroke.js +15 -2
- 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 +26 -18
- package/dist/cjs/src/localizations/de.js +1 -1
- package/dist/cjs/src/localizations/es.js +1 -1
- package/dist/cjs/src/math/LineSegment2.d.ts +2 -0
- package/dist/cjs/src/math/LineSegment2.js +4 -0
- package/dist/cjs/src/math/Path.d.ts +24 -3
- package/dist/cjs/src/math/Path.js +225 -4
- package/dist/cjs/src/math/Rect2.js +4 -3
- package/dist/cjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/cjs/src/math/polynomial/QuadraticBezier.js +114 -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/HTMLToolbar.js +7 -0
- 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.d.ts +4 -1
- package/dist/mjs/src/Editor.mjs +29 -11
- 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/AbstractComponent.d.ts +13 -1
- package/dist/mjs/src/components/AbstractComponent.mjs +19 -9
- 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.d.ts +1 -0
- package/dist/mjs/src/components/Stroke.mjs +15 -2
- 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 +26 -18
- package/dist/mjs/src/localizations/de.mjs +1 -1
- package/dist/mjs/src/localizations/es.mjs +1 -1
- package/dist/mjs/src/math/LineSegment2.d.ts +2 -0
- package/dist/mjs/src/math/LineSegment2.mjs +4 -0
- package/dist/mjs/src/math/Path.d.ts +24 -3
- package/dist/mjs/src/math/Path.mjs +225 -4
- package/dist/mjs/src/math/Rect2.mjs +4 -3
- package/dist/mjs/src/math/polynomial/QuadraticBezier.d.ts +28 -0
- package/dist/mjs/src/math/polynomial/QuadraticBezier.mjs +108 -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/HTMLToolbar.mjs +8 -1
- 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/src/Coloris.css +52 -0
- package/src/Editor.css +12 -0
- package/src/toolbar/toolbar.css +9 -0
- package/dist/cjs/src/components/ImageBackground.js +0 -146
- package/dist/mjs/src/components/ImageBackground.mjs +0 -139
@@ -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.21.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"
|
package/src/Coloris.css
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
/* Imports Coloris' CSS and makes additional changes to the color picker */
|
3
|
+
|
4
|
+
#clr-picker {
|
5
|
+
--clr-slider-size: 30px;
|
6
|
+
}
|
7
|
+
|
8
|
+
/* Coloris: Try to avoid scrolling instead of updating the color input. */
|
9
|
+
#clr-picker #clr-color-area, #clr-picker .clr_hue {
|
10
|
+
touch-action: none;
|
11
|
+
}
|
12
|
+
|
13
|
+
/* Increase space between inputs */
|
14
|
+
#clr-picker .clr-alpha {
|
15
|
+
margin-top: 15px;
|
16
|
+
margin-bottom: 15px;
|
17
|
+
}
|
18
|
+
|
19
|
+
/* Increase size of input thumb to make it easier to select colors. */
|
20
|
+
#clr-picker.clr-picker input[type="range"]::-moz-range-thumb {
|
21
|
+
width: var(--clr-slider-size);
|
22
|
+
height: var(--clr-slider-size);
|
23
|
+
}
|
24
|
+
|
25
|
+
/* Also apply to Chrome/iOS */
|
26
|
+
#clr-picker.clr-picker input[type="range"]::-webkit-slider-thumb {
|
27
|
+
/*
|
28
|
+
Note: This doesn't seem to take effect in iOS if it's combined with the
|
29
|
+
::-moz-range-thumb rule above
|
30
|
+
*/
|
31
|
+
width: var(--clr-slider-size);
|
32
|
+
height: var(--clr-slider-size);
|
33
|
+
}
|
34
|
+
|
35
|
+
#clr-picker.clr-picker input[type="range"]::-webkit-slider-runnable-track {
|
36
|
+
height: var(--clr-slider-size);
|
37
|
+
}
|
38
|
+
|
39
|
+
#clr-picker.clr-picker input[type="range"]::-moz-range-track {
|
40
|
+
height: var(--clr-slider-size);
|
41
|
+
}
|
42
|
+
|
43
|
+
/*
|
44
|
+
Debugging: Uncommenting this rule makes Coloris' sliders more
|
45
|
+
visible.
|
46
|
+
|
47
|
+
#clr-picker.clr-picker input[type="range"] {
|
48
|
+
opacity: 0.5;
|
49
|
+
-webkit-appearance: auto;
|
50
|
+
appearance: auto;
|
51
|
+
}
|
52
|
+
*/
|
package/src/Editor.css
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
@import url('./toolbar/toolbar.css');
|
3
3
|
@import url('./tools/tools.css');
|
4
|
+
@import url('./Coloris.css');
|
4
5
|
|
5
6
|
.imageEditorContainer {
|
6
7
|
/* Deafult colors for the editor */
|
@@ -84,3 +85,14 @@
|
|
84
85
|
overflow: visible;
|
85
86
|
z-index: 5;
|
86
87
|
}
|
88
|
+
|
89
|
+
@media print {
|
90
|
+
.imageEditorContainer .loadingMessage {
|
91
|
+
display: none;
|
92
|
+
}
|
93
|
+
|
94
|
+
.imageEditorContainer .imageEditorRenderArea canvas {
|
95
|
+
width: 100%;
|
96
|
+
height: initial;
|
97
|
+
}
|
98
|
+
}
|
package/src/toolbar/toolbar.css
CHANGED
@@ -160,6 +160,8 @@
|
|
160
160
|
bottom: 0;
|
161
161
|
right: 0;
|
162
162
|
|
163
|
+
touch-action: none;
|
164
|
+
|
163
165
|
background-color: var(--primary-background-color);
|
164
166
|
opacity: 0.3;
|
165
167
|
}
|
@@ -210,4 +212,11 @@
|
|
210
212
|
.toolbar-spacedList > * {
|
211
213
|
padding-bottom: 5px;
|
212
214
|
padding-top: 5px;
|
215
|
+
}
|
216
|
+
|
217
|
+
@media print {
|
218
|
+
/* Hide the toolbar on print. */
|
219
|
+
.toolbar-root {
|
220
|
+
display: none;
|
221
|
+
}
|
213
222
|
}
|
@@ -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);
|