js-draw 0.9.2 → 0.9.3
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/CHANGELOG.md +4 -0
- package/dist/bundle.js +1 -1
- package/dist/src/Editor.d.ts +2 -2
- package/dist/src/EditorImage.d.ts +1 -1
- package/dist/src/EventDispatcher.d.ts +1 -1
- package/dist/src/SVGLoader.d.ts +2 -2
- package/dist/src/UndoRedoHistory.d.ts +2 -2
- package/dist/src/Viewport.d.ts +1 -1
- package/dist/src/commands/SerializableCommand.d.ts +1 -1
- package/dist/src/components/AbstractComponent.d.ts +3 -3
- package/dist/src/components/SVGGlobalAttributesObject.d.ts +1 -1
- package/dist/src/components/builders/FreehandLineBuilder.d.ts +2 -0
- package/dist/src/components/builders/FreehandLineBuilder.js +10 -2
- package/dist/src/components/builders/types.d.ts +1 -1
- package/dist/src/components/util/StrokeSmoother.d.ts +1 -1
- package/dist/src/math/Mat33.d.ts +1 -1
- package/dist/src/math/Path.d.ts +1 -1
- package/dist/src/math/Vec2.d.ts +2 -2
- package/dist/src/rendering/caching/testUtils.d.ts +1 -1
- package/dist/src/rendering/caching/types.d.ts +2 -2
- package/dist/src/rendering/renderers/SVGRenderer.js +1 -1
- package/dist/src/toolbar/IconProvider.d.ts +1 -1
- package/dist/src/toolbar/localization.d.ts +1 -0
- package/dist/src/toolbar/localization.js +1 -0
- package/dist/src/toolbar/makeColorInput.d.ts +2 -2
- package/dist/src/toolbar/widgets/BaseWidget.d.ts +1 -1
- package/dist/src/toolbar/widgets/TextToolWidget.js +23 -2
- package/dist/src/tools/BaseTool.js +4 -4
- package/dist/src/tools/PipetteTool.d.ts +1 -1
- package/dist/src/tools/SelectionTool/SelectionHandle.d.ts +3 -3
- package/dist/src/tools/TextTool.js +8 -2
- package/dist/src/tools/ToolbarShortcutHandler.d.ts +1 -1
- package/dist/src/types.d.ts +8 -8
- package/package.json +16 -16
- package/src/components/builders/FreehandLineBuilder.ts +12 -2
- package/src/rendering/renderers/SVGRenderer.ts +1 -1
- package/src/toolbar/localization.ts +2 -0
- package/src/toolbar/widgets/TextToolWidget.ts +29 -1
- package/src/tools/TextTool.ts +10 -2
package/dist/src/Editor.d.ts
CHANGED
|
@@ -29,8 +29,8 @@ import Pointer from './Pointer';
|
|
|
29
29
|
import Rect2 from './math/Rect2';
|
|
30
30
|
import { EditorLocalization } from './localization';
|
|
31
31
|
import IconProvider from './toolbar/IconProvider';
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
type HTMLPointerEventType = 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel';
|
|
33
|
+
type HTMLPointerEventFilter = (eventName: HTMLPointerEventType, event: PointerEvent) => boolean;
|
|
34
34
|
export interface EditorSettings {
|
|
35
35
|
/** Defaults to `RenderingMode.CanvasRenderer` */
|
|
36
36
|
renderingMode: RenderingMode;
|
|
@@ -27,7 +27,7 @@ export default class EditorImage {
|
|
|
27
27
|
static addElement(elem: AbstractComponent, applyByFlattening?: boolean): SerializableCommand;
|
|
28
28
|
private static AddElementCommand;
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
type TooSmallToRenderCheck = (rect: Rect2) => boolean;
|
|
31
31
|
/** Part of the Editor's image. @internal */
|
|
32
32
|
export declare class ImageNode {
|
|
33
33
|
private parent;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*
|
|
16
16
|
* @packageDocumentation
|
|
17
17
|
*/
|
|
18
|
-
|
|
18
|
+
type CallbackHandler<EventType> = (data: EventType) => void;
|
|
19
19
|
export default class EventDispatcher<EventKeyType extends string | symbol | number, EventMessageType> {
|
|
20
20
|
private listeners;
|
|
21
21
|
constructor();
|
package/dist/src/SVGLoader.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { ComponentAddedListener, ImageLoader, OnDetermineExportRectListener, OnP
|
|
|
3
3
|
export declare const defaultSVGViewRect: Rect2;
|
|
4
4
|
export declare const svgAttributesDataKey = "svgAttrs";
|
|
5
5
|
export declare const svgStyleAttributesDataKey = "svgStyleAttrs";
|
|
6
|
-
export
|
|
7
|
-
export
|
|
6
|
+
export type SVGLoaderUnknownAttribute = [string, string];
|
|
7
|
+
export type SVGLoaderUnknownStyleAttribute = {
|
|
8
8
|
key: string;
|
|
9
9
|
value: string;
|
|
10
10
|
priority?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Editor from './Editor';
|
|
2
2
|
import Command from './commands/Command';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type AnnounceRedoCallback = (command: Command) => void;
|
|
4
|
+
type AnnounceUndoCallback = (command: Command) => void;
|
|
5
5
|
declare class UndoRedoHistory {
|
|
6
6
|
private readonly editor;
|
|
7
7
|
private announceRedoCallback;
|
package/dist/src/Viewport.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import Rect2 from './math/Rect2';
|
|
|
4
4
|
import { Point2, Vec2 } from './math/Vec2';
|
|
5
5
|
import { StrokeDataPoint } from './types';
|
|
6
6
|
import { EditorNotifier } from './types';
|
|
7
|
-
|
|
7
|
+
type PointDataType<T extends Point2 | StrokeDataPoint | number> = T extends Point2 ? Point2 : number;
|
|
8
8
|
export declare abstract class ViewportTransform extends Command {
|
|
9
9
|
abstract readonly transform: Mat33;
|
|
10
10
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Editor from '../Editor';
|
|
2
2
|
import Command from './Command';
|
|
3
|
-
export
|
|
3
|
+
export type DeserializationCallback = (data: Record<string, any> | any[], editor: Editor) => SerializableCommand;
|
|
4
4
|
export default abstract class SerializableCommand extends Command {
|
|
5
5
|
private commandTypeId;
|
|
6
6
|
constructor(commandTypeId: string);
|
|
@@ -4,9 +4,9 @@ import Mat33 from '../math/Mat33';
|
|
|
4
4
|
import Rect2 from '../math/Rect2';
|
|
5
5
|
import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
|
|
6
6
|
import { ImageComponentLocalization } from './localization';
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
7
|
+
export type LoadSaveData = (string[] | Record<symbol, string | number>);
|
|
8
|
+
export type LoadSaveDataTable = Record<string, Array<LoadSaveData>>;
|
|
9
|
+
export type DeserializeCallback = (data: string) => AbstractComponent;
|
|
10
10
|
export default abstract class AbstractComponent {
|
|
11
11
|
private readonly componentKind;
|
|
12
12
|
protected lastChangedTime: number;
|
|
@@ -4,7 +4,7 @@ import Rect2 from '../math/Rect2';
|
|
|
4
4
|
import AbstractRenderer from '../rendering/renderers/AbstractRenderer';
|
|
5
5
|
import AbstractComponent from './AbstractComponent';
|
|
6
6
|
import { ImageComponentLocalization } from './localization';
|
|
7
|
-
|
|
7
|
+
type GlobalAttrsList = Array<[string, string | null]>;
|
|
8
8
|
export default class SVGGlobalAttributesObject extends AbstractComponent {
|
|
9
9
|
private readonly attrs;
|
|
10
10
|
protected contentBBox: Rect2;
|
|
@@ -24,7 +24,9 @@ export default class FreehandLineBuilder implements ComponentBuilder {
|
|
|
24
24
|
private previewStroke;
|
|
25
25
|
preview(renderer: AbstractRenderer): void;
|
|
26
26
|
build(): Stroke;
|
|
27
|
+
private getMinFit;
|
|
27
28
|
private roundPoint;
|
|
29
|
+
private roundDistance;
|
|
28
30
|
private curveToPathCommands;
|
|
29
31
|
private addCurve;
|
|
30
32
|
addPoint(newPoint: StrokeDataPoint): void;
|
|
@@ -33,7 +33,7 @@ export default class FreehandLineBuilder {
|
|
|
33
33
|
fill: Color4.transparent,
|
|
34
34
|
stroke: {
|
|
35
35
|
color: this.startPoint.color,
|
|
36
|
-
width: this.averageWidth,
|
|
36
|
+
width: this.roundDistance(this.averageWidth),
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
39
|
}
|
|
@@ -76,13 +76,21 @@ export default class FreehandLineBuilder {
|
|
|
76
76
|
this.curveFitter.finalizeCurrentCurve();
|
|
77
77
|
return this.previewStroke();
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
getMinFit() {
|
|
80
80
|
let minFit = Math.min(this.minFitAllowed, this.averageWidth / 2);
|
|
81
81
|
if (minFit < 1e-10) {
|
|
82
82
|
minFit = this.minFitAllowed;
|
|
83
83
|
}
|
|
84
|
+
return minFit;
|
|
85
|
+
}
|
|
86
|
+
roundPoint(point) {
|
|
87
|
+
const minFit = this.getMinFit();
|
|
84
88
|
return Viewport.roundPoint(point, minFit);
|
|
85
89
|
}
|
|
90
|
+
roundDistance(dist) {
|
|
91
|
+
const minFit = this.getMinFit();
|
|
92
|
+
return Viewport.roundPoint(dist, minFit);
|
|
93
|
+
}
|
|
86
94
|
curveToPathCommands(curve) {
|
|
87
95
|
// Case where no points have been added
|
|
88
96
|
if (!curve) {
|
|
@@ -9,4 +9,4 @@ export interface ComponentBuilder {
|
|
|
9
9
|
preview(renderer: AbstractRenderer): void;
|
|
10
10
|
addPoint(point: StrokeDataPoint): void;
|
|
11
11
|
}
|
|
12
|
-
export
|
|
12
|
+
export type ComponentBuilderFactory = (startPoint: StrokeDataPoint, viewport: Viewport) => ComponentBuilder;
|
|
@@ -8,7 +8,7 @@ export interface Curve {
|
|
|
8
8
|
endWidth: number;
|
|
9
9
|
endPoint: Vec2;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
type OnCurveAddedCallback = (curve: Curve | null) => void;
|
|
12
12
|
export declare class StrokeSmoother {
|
|
13
13
|
private startPoint;
|
|
14
14
|
private minFitAllowed;
|
package/dist/src/math/Mat33.d.ts
CHANGED
package/dist/src/math/Path.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface MoveToPathCommand {
|
|
|
30
30
|
kind: PathCommandType.MoveTo;
|
|
31
31
|
point: Point2;
|
|
32
32
|
}
|
|
33
|
-
export
|
|
33
|
+
export type PathCommand = CubicBezierPathCommand | LinePathCommand | QuadraticBezierPathCommand | MoveToPathCommand;
|
|
34
34
|
interface IntersectionResult {
|
|
35
35
|
curve: LineSegment2 | Bezier;
|
|
36
36
|
parameterValue: number;
|
package/dist/src/math/Vec2.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import DummyRenderer from '../renderers/DummyRenderer';
|
|
2
2
|
import RenderingCache from './RenderingCache';
|
|
3
3
|
import { CacheProps } from './types';
|
|
4
|
-
|
|
4
|
+
type RenderAllocCallback = (renderer: DummyRenderer) => void;
|
|
5
5
|
export declare const createCache: (onRenderAlloc?: RenderAllocCallback, cacheOptions?: Partial<CacheProps>) => {
|
|
6
6
|
cache: RenderingCache;
|
|
7
7
|
editor: import("../../Editor").Editor;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Vec2 } from '../../math/Vec2';
|
|
2
2
|
import AbstractRenderer from '../renderers/AbstractRenderer';
|
|
3
3
|
import { CacheRecordManager } from './CacheRecordManager';
|
|
4
|
-
export
|
|
5
|
-
export
|
|
4
|
+
export type CacheAddress = number;
|
|
5
|
+
export type BeforeDeallocCallback = () => void;
|
|
6
6
|
export interface CacheProps {
|
|
7
7
|
createRenderer(): AbstractRenderer;
|
|
8
8
|
isOfCorrectType(renderer: AbstractRenderer): boolean;
|
|
@@ -87,7 +87,7 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
|
87
87
|
}
|
|
88
88
|
if (style.stroke) {
|
|
89
89
|
pathElem.setAttribute('stroke', style.stroke.color.toHexString());
|
|
90
|
-
pathElem.setAttribute('stroke-width', style.stroke.width
|
|
90
|
+
pathElem.setAttribute('stroke-width', toRoundedString(style.stroke.width));
|
|
91
91
|
}
|
|
92
92
|
this.elem.appendChild(pathElem);
|
|
93
93
|
(_a = this.objectElems) === null || _a === void 0 ? void 0 : _a.push(pathElem);
|
|
@@ -2,7 +2,7 @@ import Color4 from '../Color4';
|
|
|
2
2
|
import { ComponentBuilderFactory } from '../components/builders/types';
|
|
3
3
|
import { TextStyle } from '../components/TextComponent';
|
|
4
4
|
import Pen from '../tools/Pen';
|
|
5
|
-
|
|
5
|
+
type IconType = SVGSVGElement | HTMLImageElement;
|
|
6
6
|
export default class IconProvider {
|
|
7
7
|
makeUndoIcon(): IconType;
|
|
8
8
|
makeRedoIcon(mirror?: boolean): IconType;
|
|
@@ -8,6 +8,7 @@ export const defaultToolbarLocalization = {
|
|
|
8
8
|
thicknessLabel: 'Thickness: ',
|
|
9
9
|
colorLabel: 'Color: ',
|
|
10
10
|
fontLabel: 'Font: ',
|
|
11
|
+
textSize: 'Size: ',
|
|
11
12
|
resizeImageToSelection: 'Resize image to selection',
|
|
12
13
|
deleteSelection: 'Delete selection',
|
|
13
14
|
duplicateSelection: 'Duplicate selection',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Color4 from '../Color4';
|
|
2
2
|
import Editor from '../Editor';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type OnColorChangeListener = (color: Color4) => void;
|
|
4
|
+
type SetColorCallback = (color: Color4 | string) => void;
|
|
5
5
|
export declare const makeColorInput: (editor: Editor, onColorChange: OnColorChangeListener) => [HTMLInputElement, HTMLElement, SetColorCallback];
|
|
6
6
|
export default makeColorInput;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Editor from '../../Editor';
|
|
2
2
|
import { KeyPressEvent } from '../../types';
|
|
3
3
|
import { ToolbarLocalization } from '../localization';
|
|
4
|
-
export
|
|
4
|
+
export type SavedToolbuttonState = Record<string, any>;
|
|
5
5
|
export default abstract class BaseWidget {
|
|
6
6
|
#private;
|
|
7
7
|
protected editor: Editor;
|
|
@@ -26,8 +26,11 @@ export default class TextToolWidget extends BaseToolWidget {
|
|
|
26
26
|
fillDropdown(dropdown) {
|
|
27
27
|
const fontRow = document.createElement('div');
|
|
28
28
|
const colorRow = document.createElement('div');
|
|
29
|
+
const sizeRow = document.createElement('div');
|
|
29
30
|
const fontInput = document.createElement('select');
|
|
30
31
|
const fontLabel = document.createElement('label');
|
|
32
|
+
const sizeInput = document.createElement('input');
|
|
33
|
+
const sizeLabel = document.createElement('label');
|
|
31
34
|
const [colorInput, colorInputContainer, setColorInputValue] = makeColorInput(this.editor, color => {
|
|
32
35
|
this.tool.setColor(color);
|
|
33
36
|
});
|
|
@@ -40,10 +43,16 @@ export default class TextToolWidget extends BaseToolWidget {
|
|
|
40
43
|
fontInput.appendChild(option);
|
|
41
44
|
fontsInInput.add(fontName);
|
|
42
45
|
};
|
|
46
|
+
sizeInput.setAttribute('type', 'number');
|
|
47
|
+
sizeInput.min = '1';
|
|
48
|
+
sizeInput.max = '128';
|
|
43
49
|
fontLabel.innerText = this.localizationTable.fontLabel;
|
|
44
50
|
colorLabel.innerText = this.localizationTable.colorLabel;
|
|
51
|
+
sizeLabel.innerText = this.localizationTable.textSize;
|
|
45
52
|
colorInput.id = `${toolbarCSSPrefix}-text-color-input-${TextToolWidget.idCounter++}`;
|
|
46
53
|
colorLabel.setAttribute('for', colorInput.id);
|
|
54
|
+
sizeInput.id = `${toolbarCSSPrefix}-text-size-input-${TextToolWidget.idCounter++}`;
|
|
55
|
+
sizeLabel.setAttribute('for', sizeInput.id);
|
|
47
56
|
addFontToInput('monospace');
|
|
48
57
|
addFontToInput('serif');
|
|
49
58
|
addFontToInput('sans-serif');
|
|
@@ -52,10 +61,18 @@ export default class TextToolWidget extends BaseToolWidget {
|
|
|
52
61
|
fontInput.onchange = () => {
|
|
53
62
|
this.tool.setFontFamily(fontInput.value);
|
|
54
63
|
};
|
|
64
|
+
sizeInput.onchange = () => {
|
|
65
|
+
const size = parseInt(sizeInput.value);
|
|
66
|
+
if (!isNaN(size) && size > 0) {
|
|
67
|
+
this.tool.setFontSize(size);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
55
70
|
colorRow.appendChild(colorLabel);
|
|
56
71
|
colorRow.appendChild(colorInputContainer);
|
|
57
72
|
fontRow.appendChild(fontLabel);
|
|
58
73
|
fontRow.appendChild(fontInput);
|
|
74
|
+
sizeRow.appendChild(sizeLabel);
|
|
75
|
+
sizeRow.appendChild(sizeInput);
|
|
59
76
|
this.updateDropdownInputs = () => {
|
|
60
77
|
const style = this.tool.getTextStyle();
|
|
61
78
|
setColorInputValue(style.renderingStyle.fill);
|
|
@@ -63,14 +80,15 @@ export default class TextToolWidget extends BaseToolWidget {
|
|
|
63
80
|
addFontToInput(style.fontFamily);
|
|
64
81
|
}
|
|
65
82
|
fontInput.value = style.fontFamily;
|
|
83
|
+
sizeInput.value = `${style.size}`;
|
|
66
84
|
};
|
|
67
85
|
this.updateDropdownInputs();
|
|
68
|
-
dropdown.replaceChildren(colorRow, fontRow);
|
|
86
|
+
dropdown.replaceChildren(colorRow, sizeRow, fontRow);
|
|
69
87
|
return true;
|
|
70
88
|
}
|
|
71
89
|
serializeState() {
|
|
72
90
|
const textStyle = this.tool.getTextStyle();
|
|
73
|
-
return Object.assign(Object.assign({}, super.serializeState()), { fontFamily: textStyle.fontFamily, color: textStyle.renderingStyle.fill.toHexString() });
|
|
91
|
+
return Object.assign(Object.assign({}, super.serializeState()), { fontFamily: textStyle.fontFamily, textSize: textStyle.size, color: textStyle.renderingStyle.fill.toHexString() });
|
|
74
92
|
}
|
|
75
93
|
deserializeFrom(state) {
|
|
76
94
|
if (state.fontFamily && typeof (state.fontFamily) === 'string') {
|
|
@@ -79,6 +97,9 @@ export default class TextToolWidget extends BaseToolWidget {
|
|
|
79
97
|
if (state.color && typeof (state.color) === 'string') {
|
|
80
98
|
this.tool.setColor(Color4.fromHex(state.color));
|
|
81
99
|
}
|
|
100
|
+
if (state.textSize && typeof (state.textSize) === 'number') {
|
|
101
|
+
this.tool.setFontSize(state.textSize);
|
|
102
|
+
}
|
|
82
103
|
super.deserializeFrom(state);
|
|
83
104
|
}
|
|
84
105
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { EditorEventType } from '../types';
|
|
2
2
|
export default class BaseTool {
|
|
3
|
+
onPointerDown(_event) { return false; }
|
|
4
|
+
onPointerMove(_event) { }
|
|
5
|
+
onPointerUp(_event) { }
|
|
6
|
+
onGestureCancel() { }
|
|
3
7
|
constructor(notifier, description) {
|
|
4
8
|
this.notifier = notifier;
|
|
5
9
|
this.description = description;
|
|
6
10
|
this.enabled = true;
|
|
7
11
|
this.group = null;
|
|
8
12
|
}
|
|
9
|
-
onPointerDown(_event) { return false; }
|
|
10
|
-
onPointerMove(_event) { }
|
|
11
|
-
onPointerUp(_event) { }
|
|
12
|
-
onGestureCancel() { }
|
|
13
13
|
onWheel(_event) {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
@@ -2,7 +2,7 @@ import Color4 from '../Color4';
|
|
|
2
2
|
import Editor from '../Editor';
|
|
3
3
|
import { PointerEvt } from '../types';
|
|
4
4
|
import BaseTool from './BaseTool';
|
|
5
|
-
|
|
5
|
+
type ColorListener = (color: Color4 | null) => void;
|
|
6
6
|
export default class PipetteTool extends BaseTool {
|
|
7
7
|
private editor;
|
|
8
8
|
private colorPreviewListener;
|
|
@@ -6,9 +6,9 @@ export declare enum HandleShape {
|
|
|
6
6
|
Square = 1
|
|
7
7
|
}
|
|
8
8
|
export declare const handleSize = 30;
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
export
|
|
9
|
+
export type DragStartCallback = (startPoint: Point2) => void;
|
|
10
|
+
export type DragUpdateCallback = (canvasPoint: Point2) => void;
|
|
11
|
+
export type DragEndCallback = () => void;
|
|
12
12
|
export default class SelectionHandle {
|
|
13
13
|
readonly shape: HandleShape;
|
|
14
14
|
private readonly parentSide;
|
|
@@ -108,8 +108,10 @@ export default class TextTool extends BaseTool {
|
|
|
108
108
|
this.textInputElem.style.margin = '0';
|
|
109
109
|
this.textInputElem.style.width = `${this.textInputElem.scrollWidth}px`;
|
|
110
110
|
this.textInputElem.style.height = `${this.textInputElem.scrollHeight}px`;
|
|
111
|
+
// Get the ascent based on the font, using a character that is tall in most fonts.
|
|
112
|
+
const tallCharacter = '⎢';
|
|
113
|
+
const ascent = this.getTextAscent(tallCharacter, this.textStyle);
|
|
111
114
|
const rotation = this.textRotation + viewport.getRotationAngle();
|
|
112
|
-
const ascent = this.getTextAscent(this.textInputElem.value || 'W', this.textStyle);
|
|
113
115
|
const scale = this.getTextScaleMatrix();
|
|
114
116
|
this.textInputElem.style.transform = `${scale.toCSSMatrix()} rotate(${rotation * 180 / Math.PI}deg) translate(0, ${-ascent}px)`;
|
|
115
117
|
this.textInputElem.style.transformOrigin = 'top left';
|
|
@@ -171,7 +173,11 @@ export default class TextTool extends BaseTool {
|
|
|
171
173
|
const halfTestRegionSize = Vec2.of(2.5, 2.5).times(this.editor.viewport.getSizeOfPixelOnCanvas());
|
|
172
174
|
const testRegion = Rect2.fromCorners(canvasPos.minus(halfTestRegionSize), canvasPos.plus(halfTestRegionSize));
|
|
173
175
|
const targetNodes = this.editor.image.getElementsIntersectingRegion(testRegion);
|
|
174
|
-
|
|
176
|
+
let targetTextNodes = targetNodes.filter(node => node instanceof TextComponent);
|
|
177
|
+
// Don't try to edit text nodes that contain the viewport (this allows us
|
|
178
|
+
// to zoom in on text nodes and add text on top of them.)
|
|
179
|
+
const visibleRect = this.editor.viewport.visibleRect;
|
|
180
|
+
targetTextNodes = targetTextNodes.filter(node => !node.getBBox().containsRect(visibleRect));
|
|
175
181
|
// End any TextNodes we're currently editing.
|
|
176
182
|
this.flushInput();
|
|
177
183
|
if (targetTextNodes.length > 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Editor from '../Editor';
|
|
2
2
|
import { KeyPressEvent } from '../types';
|
|
3
3
|
import BaseTool from './BaseTool';
|
|
4
|
-
|
|
4
|
+
type KeyPressListener = (event: KeyPressEvent) => boolean;
|
|
5
5
|
export default class ToolbarShortcutHandler extends BaseTool {
|
|
6
6
|
private listeners;
|
|
7
7
|
constructor(editor: Editor);
|
package/dist/src/types.d.ts
CHANGED
|
@@ -68,9 +68,9 @@ export interface PointerMoveEvt extends PointerEvtBase {
|
|
|
68
68
|
export interface PointerUpEvt extends PointerEvtBase {
|
|
69
69
|
readonly kind: InputEvtType.PointerUpEvt;
|
|
70
70
|
}
|
|
71
|
-
export
|
|
72
|
-
export
|
|
73
|
-
export
|
|
71
|
+
export type PointerEvt = PointerDownEvt | PointerMoveEvt | PointerUpEvt;
|
|
72
|
+
export type InputEvt = KeyPressEvent | KeyUpEvent | WheelEvt | GestureCancelEvt | PointerEvt | CopyEvent | PasteEvent;
|
|
73
|
+
export type EditorNotifier = EventDispatcher<EditorEventType, EditorEventDataType>;
|
|
74
74
|
export declare enum EditorEventType {
|
|
75
75
|
ToolEnabled = 0,
|
|
76
76
|
ToolDisabled = 1,
|
|
@@ -85,7 +85,7 @@ export declare enum EditorEventType {
|
|
|
85
85
|
ColorPickerColorSelected = 10,
|
|
86
86
|
ToolbarDropdownShown = 11
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
type EditorToolEventType = EditorEventType.ToolEnabled | EditorEventType.ToolDisabled | EditorEventType.ToolUpdated;
|
|
89
89
|
export interface EditorToolEvent {
|
|
90
90
|
readonly kind: EditorToolEventType;
|
|
91
91
|
readonly tool: BaseTool;
|
|
@@ -128,10 +128,10 @@ export interface ToolbarDropdownShownEvent {
|
|
|
128
128
|
readonly kind: EditorEventType.ToolbarDropdownShown;
|
|
129
129
|
readonly parentWidget: BaseWidget;
|
|
130
130
|
}
|
|
131
|
-
export
|
|
132
|
-
export
|
|
133
|
-
export
|
|
134
|
-
export
|
|
131
|
+
export type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | ColorPickerToggled | ColorPickerColorSelected | ToolbarDropdownShownEvent;
|
|
132
|
+
export type OnProgressListener = (amountProcessed: number, totalToProcess: number) => Promise<void> | null;
|
|
133
|
+
export type ComponentAddedListener = (component: AbstractComponent) => void;
|
|
134
|
+
export type OnDetermineExportRectListener = (exportRect: Rect2) => void;
|
|
135
135
|
export interface ImageLoader {
|
|
136
136
|
start(onAddComponent: ComponentAddedListener, onProgressListener: OnProgressListener, onDetermineExportRect?: OnDetermineExportRectListener): Promise<void>;
|
|
137
137
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-draw",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ",
|
|
5
5
|
"main": "./dist/src/lib.d.ts",
|
|
6
6
|
"types": "./dist/src/lib.js",
|
|
@@ -83,27 +83,27 @@
|
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@types/bezier-js": "^4.1.0",
|
|
86
|
-
"@types/jest": "^29.
|
|
87
|
-
"@types/jsdom": "^20.0.
|
|
88
|
-
"@types/node": "^18.
|
|
89
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
90
|
-
"@typescript-eslint/parser": "^5.
|
|
91
|
-
"css-loader": "^6.7.
|
|
92
|
-
"eslint": "^8.
|
|
93
|
-
"husky": "^8.0.
|
|
94
|
-
"jest": "^29.
|
|
95
|
-
"jest-environment-jsdom": "^29.
|
|
96
|
-
"jsdom": "^20.0.
|
|
86
|
+
"@types/jest": "^29.2.3",
|
|
87
|
+
"@types/jsdom": "^20.0.1",
|
|
88
|
+
"@types/node": "^18.11.9",
|
|
89
|
+
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
|
90
|
+
"@typescript-eslint/parser": "^5.44.0",
|
|
91
|
+
"css-loader": "^6.7.2",
|
|
92
|
+
"eslint": "^8.28.0",
|
|
93
|
+
"husky": "^8.0.2",
|
|
94
|
+
"jest": "^29.2.3",
|
|
95
|
+
"jest-environment-jsdom": "^29.3.1",
|
|
96
|
+
"jsdom": "^20.0.3",
|
|
97
97
|
"lint-staged": "^13.0.3",
|
|
98
98
|
"pinst": "^3.0.0",
|
|
99
99
|
"style-loader": "^3.3.1",
|
|
100
100
|
"terser-webpack-plugin": "^5.3.6",
|
|
101
|
-
"ts-jest": "^29.0.
|
|
101
|
+
"ts-jest": "^29.0.3",
|
|
102
102
|
"ts-loader": "^9.4.1",
|
|
103
103
|
"ts-node": "^10.9.1",
|
|
104
|
-
"typedoc": "^0.23.
|
|
105
|
-
"typescript": "^4.
|
|
106
|
-
"webpack": "^5.
|
|
104
|
+
"typedoc": "^0.23.21",
|
|
105
|
+
"typescript": "^4.9.3",
|
|
106
|
+
"webpack": "^5.75.0"
|
|
107
107
|
},
|
|
108
108
|
"bugs": {
|
|
109
109
|
"url": "https://github.com/personalizedrefrigerator/js-draw/issues"
|
|
@@ -55,7 +55,7 @@ export default class FreehandLineBuilder implements ComponentBuilder {
|
|
|
55
55
|
fill: Color4.transparent,
|
|
56
56
|
stroke: {
|
|
57
57
|
color: this.startPoint.color,
|
|
58
|
-
width: this.averageWidth,
|
|
58
|
+
width: this.roundDistance(this.averageWidth),
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
}
|
|
@@ -107,16 +107,26 @@ export default class FreehandLineBuilder implements ComponentBuilder {
|
|
|
107
107
|
return this.previewStroke()!;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
private
|
|
110
|
+
private getMinFit(): number {
|
|
111
111
|
let minFit = Math.min(this.minFitAllowed, this.averageWidth / 2);
|
|
112
112
|
|
|
113
113
|
if (minFit < 1e-10) {
|
|
114
114
|
minFit = this.minFitAllowed;
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
return minFit;
|
|
118
|
+
}
|
|
116
119
|
|
|
120
|
+
private roundPoint(point: Point2): Point2 {
|
|
121
|
+
const minFit = this.getMinFit();
|
|
117
122
|
return Viewport.roundPoint(point, minFit);
|
|
118
123
|
}
|
|
119
124
|
|
|
125
|
+
private roundDistance(dist: number): number {
|
|
126
|
+
const minFit = this.getMinFit();
|
|
127
|
+
return Viewport.roundPoint(dist, minFit);
|
|
128
|
+
}
|
|
129
|
+
|
|
120
130
|
private curveToPathCommands(curve: Curve|null): PathCommand[] {
|
|
121
131
|
// Case where no points have been added
|
|
122
132
|
if (!curve) {
|
|
@@ -102,7 +102,7 @@ export default class SVGRenderer extends AbstractRenderer {
|
|
|
102
102
|
|
|
103
103
|
if (style.stroke) {
|
|
104
104
|
pathElem.setAttribute('stroke', style.stroke.color.toHexString());
|
|
105
|
-
pathElem.setAttribute('stroke-width', style.stroke.width
|
|
105
|
+
pathElem.setAttribute('stroke-width', toRoundedString(style.stroke.width));
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
this.elem.appendChild(pathElem);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
export interface ToolbarLocalization {
|
|
4
4
|
fontLabel: string;
|
|
5
|
+
textSize: string;
|
|
5
6
|
touchPanning: string;
|
|
6
7
|
lockRotation: string;
|
|
7
8
|
outlinedRectanglePen: string;
|
|
@@ -44,6 +45,7 @@ export const defaultToolbarLocalization: ToolbarLocalization = {
|
|
|
44
45
|
thicknessLabel: 'Thickness: ',
|
|
45
46
|
colorLabel: 'Color: ',
|
|
46
47
|
fontLabel: 'Font: ',
|
|
48
|
+
textSize: 'Size: ',
|
|
47
49
|
resizeImageToSelection: 'Resize image to selection',
|
|
48
50
|
deleteSelection: 'Delete selection',
|
|
49
51
|
duplicateSelection: 'Duplicate selection',
|