js-draw 1.21.3 → 1.23.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +104 -76
- package/build-config.json +2 -2
- package/dist/Editor.css +29 -16
- package/dist/bundle.js +2 -2
- package/dist/bundledStyles.js +1 -1
- package/dist/cjs/Editor.d.ts +1 -3
- package/dist/cjs/Editor.js +38 -26
- package/dist/cjs/EventDispatcher.js +1 -1
- package/dist/cjs/Pointer.js +3 -3
- package/dist/cjs/SVGLoader/SVGLoader.js +15 -6
- package/dist/cjs/UndoRedoHistory.js +1 -1
- package/dist/cjs/Viewport.d.ts +1 -1
- package/dist/cjs/Viewport.js +5 -3
- package/dist/cjs/commands/Command.js +7 -5
- package/dist/cjs/commands/Duplicate.js +2 -2
- package/dist/cjs/commands/Erase.js +3 -4
- package/dist/cjs/commands/invertCommand.js +4 -4
- package/dist/cjs/commands/lib.d.ts +1 -1
- package/dist/cjs/commands/uniteCommands.js +4 -4
- package/dist/cjs/components/AbstractComponent.d.ts +2 -2
- package/dist/cjs/components/AbstractComponent.js +4 -4
- package/dist/cjs/components/BackgroundComponent.js +8 -6
- package/dist/cjs/components/ImageComponent.js +12 -5
- package/dist/cjs/components/RestylableComponent.js +1 -1
- package/dist/cjs/components/SVGGlobalAttributesObject.js +1 -2
- package/dist/cjs/components/Stroke.js +37 -24
- package/dist/cjs/components/TextComponent.js +13 -10
- package/dist/cjs/components/UnknownSVGObject.js +2 -3
- package/dist/cjs/components/builders/ArrowBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/ArrowBuilder.js +9 -3
- package/dist/cjs/components/builders/CircleBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/CircleBuilder.js +11 -4
- package/dist/cjs/components/builders/FreehandLineBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/FreehandLineBuilder.js +10 -4
- package/dist/cjs/components/builders/LineBuilder.d.ts +6 -0
- package/dist/cjs/components/builders/LineBuilder.js +8 -4
- package/dist/cjs/components/builders/PolylineBuilder.d.ts +4 -1
- package/dist/cjs/components/builders/PolylineBuilder.js +9 -5
- package/dist/cjs/components/builders/PressureSensitiveFreehandLineBuilder.js +16 -10
- package/dist/cjs/components/builders/RectangleBuilder.d.ts +12 -0
- package/dist/cjs/components/builders/RectangleBuilder.js +17 -3
- package/dist/cjs/components/builders/autocorrect/makeShapeFitAutocorrect.js +5 -8
- package/dist/cjs/components/builders/autocorrect/makeSnapToGridAutocorrect.js +1 -1
- package/dist/cjs/components/builders/lib.d.ts +7 -0
- package/dist/cjs/components/builders/lib.js +18 -0
- package/dist/cjs/components/lib.d.ts +1 -4
- package/dist/cjs/components/lib.js +2 -9
- package/dist/cjs/components/util/StrokeSmoother.js +5 -6
- package/dist/cjs/dialogs/makeAboutDialog.js +1 -1
- package/dist/cjs/dialogs/makeMessageDialog.js +2 -2
- package/dist/cjs/image/EditorImage.d.ts +30 -7
- package/dist/cjs/image/EditorImage.js +43 -22
- package/dist/cjs/image/export/editorImageToSVG.js +1 -1
- package/dist/cjs/inputEvents.js +3 -3
- package/dist/cjs/lib.d.ts +2 -2
- package/dist/cjs/localizations/de.js +2 -2
- package/dist/cjs/localizations/es.js +7 -3
- package/dist/cjs/rendering/Display.js +7 -3
- package/dist/cjs/rendering/RenderablePathSpec.js +26 -11
- package/dist/cjs/rendering/RenderingStyle.js +22 -15
- package/dist/cjs/rendering/TextRenderingStyle.js +1 -1
- package/dist/cjs/rendering/caching/CacheRecord.js +1 -1
- package/dist/cjs/rendering/caching/CacheRecordManager.js +1 -1
- package/dist/cjs/rendering/caching/RenderingCache.js +1 -1
- package/dist/cjs/rendering/caching/RenderingCacheNode.js +26 -15
- package/dist/cjs/rendering/caching/testUtils.js +2 -2
- package/dist/cjs/rendering/renderers/AbstractRenderer.js +3 -1
- package/dist/cjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
- package/dist/cjs/rendering/renderers/CanvasRenderer.js +6 -28
- package/dist/cjs/rendering/renderers/DummyRenderer.js +1 -1
- package/dist/cjs/rendering/renderers/SVGRenderer.js +39 -21
- package/dist/cjs/rendering/renderers/TextOnlyRenderer.js +13 -15
- package/dist/cjs/shortcuts/KeyBinding.js +6 -12
- package/dist/cjs/shortcuts/KeyboardShortcutManager.js +2 -2
- package/dist/cjs/testing/createEditor.js +6 -1
- package/dist/cjs/testing/findNodeWithText.d.ts +4 -1
- package/dist/cjs/testing/findNodeWithText.js +12 -3
- package/dist/cjs/testing/getUniquePointerId.js +1 -1
- package/dist/cjs/testing/sendHtmlSwipe.js +7 -3
- package/dist/cjs/testing/sendPenEvent.js +1 -3
- package/dist/cjs/testing/sendTouchEvent.js +1 -4
- package/dist/cjs/testing/startPinchGesture.js +3 -1
- package/dist/cjs/toolbar/AbstractToolbar.d.ts +19 -0
- package/dist/cjs/toolbar/AbstractToolbar.js +26 -11
- package/dist/cjs/toolbar/EdgeToolbar.js +11 -15
- package/dist/cjs/toolbar/IconProvider.d.ts +5 -1
- package/dist/cjs/toolbar/IconProvider.js +117 -149
- package/dist/cjs/toolbar/localization.js +5 -5
- package/dist/cjs/toolbar/utils/HelpDisplay.js +8 -6
- package/dist/cjs/toolbar/utils/makeDraggable.js +4 -7
- package/dist/cjs/toolbar/widgets/BaseToolWidget.js +3 -2
- package/dist/cjs/toolbar/widgets/BaseWidget.d.ts +1 -1
- package/dist/cjs/toolbar/widgets/BaseWidget.js +8 -8
- package/dist/cjs/toolbar/widgets/DocumentPropertiesWidget.js +2 -2
- package/dist/cjs/toolbar/widgets/EraserToolWidget.js +5 -3
- package/dist/cjs/toolbar/widgets/HandToolWidget.js +8 -6
- package/dist/cjs/toolbar/widgets/InsertImageWidget/InsertImageWidget.js +9 -10
- package/dist/cjs/toolbar/widgets/PenToolWidget.js +22 -13
- package/dist/cjs/toolbar/widgets/SelectionToolWidget.js +2 -2
- package/dist/cjs/toolbar/widgets/TextToolWidget.js +5 -5
- package/dist/cjs/toolbar/widgets/components/makeFileInput.js +7 -7
- package/dist/cjs/toolbar/widgets/components/makeGridSelector.js +5 -5
- package/dist/cjs/toolbar/widgets/components/makeSnappedList.js +9 -5
- package/dist/cjs/toolbar/widgets/keybindings.js +2 -2
- package/dist/cjs/toolbar/widgets/layout/DropdownLayoutManager.js +6 -6
- package/dist/cjs/tools/BaseTool.js +5 -3
- package/dist/cjs/tools/Eraser.js +25 -20
- package/dist/cjs/tools/FindTool.js +2 -2
- package/dist/cjs/tools/InputFilter/ContextMenuRecognizer.js +1 -3
- package/dist/cjs/tools/InputFilter/InputMapper.js +1 -1
- package/dist/cjs/tools/InputFilter/InputPipeline.js +1 -1
- package/dist/cjs/tools/InputFilter/InputStabilizer.js +12 -5
- package/dist/cjs/tools/InputFilter/StrokeKeyboardControl.js +7 -4
- package/dist/cjs/tools/PanZoom.d.ts +1 -1
- package/dist/cjs/tools/PanZoom.js +18 -13
- package/dist/cjs/tools/PasteHandler.js +8 -2
- package/dist/cjs/tools/Pen.d.ts +13 -0
- package/dist/cjs/tools/Pen.js +30 -9
- package/dist/cjs/tools/ScrollbarTool.js +8 -7
- package/dist/cjs/tools/SelectionTool/Selection.js +16 -12
- package/dist/cjs/tools/SelectionTool/SelectionHandle.js +5 -2
- package/dist/cjs/tools/SelectionTool/SelectionMenuShortcut.js +3 -1
- package/dist/cjs/tools/SelectionTool/SelectionTool.js +25 -16
- package/dist/cjs/tools/SelectionTool/ToPointerAutoscroller.js +1 -1
- package/dist/cjs/tools/SelectionTool/TransformMode.js +6 -7
- package/dist/cjs/tools/SelectionTool/util/makeClipboardErrorHandlers.js +23 -2
- package/dist/cjs/tools/SelectionTool/util/showSelectionContextMenu.js +29 -20
- package/dist/cjs/tools/SoundUITool.js +5 -3
- package/dist/cjs/tools/TextTool.js +8 -6
- package/dist/cjs/tools/ToolController.js +16 -10
- package/dist/cjs/tools/lib.d.ts +1 -0
- package/dist/cjs/tools/lib.js +3 -1
- package/dist/cjs/tools/localization.d.ts +2 -0
- package/dist/cjs/tools/localization.js +3 -1
- package/dist/cjs/tools/util/StationaryPenDetector.js +3 -3
- package/dist/cjs/tools/util/createMenuOverlay.js +2 -2
- package/dist/cjs/util/ClipboardHandler.d.ts +1 -1
- package/dist/cjs/util/ClipboardHandler.js +19 -18
- package/dist/cjs/util/ReactiveValue.js +16 -12
- package/dist/cjs/util/adjustEditorThemeForContrast.js +6 -2
- package/dist/cjs/util/cloneElementWithStyles.js +1 -1
- package/dist/cjs/util/createElement.d.ts +62 -0
- package/dist/cjs/util/createElement.js +53 -0
- package/dist/cjs/util/guessKeyCodeFromKey.js +1 -1
- package/dist/cjs/util/listenForKeyboardEventsFrom.js +8 -6
- package/dist/cjs/util/waitForAll.js +3 -3
- package/dist/cjs/util/waitForImageLoaded.js +3 -3
- package/dist/cjs/util/waitForTimeout.js +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/mjs/Editor.d.ts +1 -3
- package/dist/mjs/Editor.mjs +39 -27
- package/dist/mjs/EventDispatcher.mjs +1 -1
- package/dist/mjs/Pointer.mjs +3 -3
- package/dist/mjs/SVGLoader/SVGLoader.mjs +16 -7
- package/dist/mjs/UndoRedoHistory.mjs +1 -1
- package/dist/mjs/Viewport.d.ts +1 -1
- package/dist/mjs/Viewport.mjs +5 -3
- package/dist/mjs/commands/Command.mjs +7 -5
- package/dist/mjs/commands/Duplicate.mjs +2 -2
- package/dist/mjs/commands/Erase.mjs +3 -4
- package/dist/mjs/commands/invertCommand.mjs +4 -4
- package/dist/mjs/commands/lib.d.ts +1 -1
- package/dist/mjs/commands/lib.mjs +1 -1
- package/dist/mjs/commands/uniteCommands.mjs +4 -4
- package/dist/mjs/components/AbstractComponent.d.ts +2 -2
- package/dist/mjs/components/AbstractComponent.mjs +4 -4
- package/dist/mjs/components/BackgroundComponent.mjs +10 -8
- package/dist/mjs/components/ImageComponent.mjs +12 -5
- package/dist/mjs/components/RestylableComponent.mjs +2 -2
- package/dist/mjs/components/SVGGlobalAttributesObject.mjs +1 -2
- package/dist/mjs/components/Stroke.mjs +40 -27
- package/dist/mjs/components/TextComponent.mjs +15 -12
- package/dist/mjs/components/UnknownSVGObject.mjs +2 -3
- package/dist/mjs/components/builders/ArrowBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/ArrowBuilder.mjs +9 -3
- package/dist/mjs/components/builders/CircleBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/CircleBuilder.mjs +11 -4
- package/dist/mjs/components/builders/FreehandLineBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/FreehandLineBuilder.mjs +10 -4
- package/dist/mjs/components/builders/LineBuilder.d.ts +6 -0
- package/dist/mjs/components/builders/LineBuilder.mjs +8 -4
- package/dist/mjs/components/builders/PolylineBuilder.d.ts +4 -1
- package/dist/mjs/components/builders/PolylineBuilder.mjs +10 -6
- package/dist/mjs/components/builders/PressureSensitiveFreehandLineBuilder.mjs +17 -11
- package/dist/mjs/components/builders/RectangleBuilder.d.ts +12 -0
- package/dist/mjs/components/builders/RectangleBuilder.mjs +17 -3
- package/dist/mjs/components/builders/autocorrect/makeShapeFitAutocorrect.mjs +5 -8
- package/dist/mjs/components/builders/autocorrect/makeSnapToGridAutocorrect.mjs +1 -1
- package/dist/mjs/components/builders/lib.d.ts +7 -0
- package/dist/mjs/components/builders/lib.mjs +7 -0
- package/dist/mjs/components/lib.d.ts +1 -4
- package/dist/mjs/components/lib.mjs +2 -5
- package/dist/mjs/components/util/StrokeSmoother.mjs +5 -6
- package/dist/mjs/dialogs/makeAboutDialog.mjs +1 -1
- package/dist/mjs/dialogs/makeMessageDialog.mjs +2 -2
- package/dist/mjs/image/EditorImage.d.ts +30 -7
- package/dist/mjs/image/EditorImage.mjs +43 -22
- package/dist/mjs/image/export/editorImageToSVG.mjs +1 -1
- package/dist/mjs/inputEvents.mjs +3 -3
- package/dist/mjs/lib.d.ts +2 -2
- package/dist/mjs/lib.mjs +2 -2
- package/dist/mjs/localization.mjs +2 -2
- package/dist/mjs/localizations/de.mjs +2 -2
- package/dist/mjs/localizations/es.mjs +7 -3
- package/dist/mjs/rendering/Display.mjs +7 -3
- package/dist/mjs/rendering/RenderablePathSpec.mjs +26 -11
- package/dist/mjs/rendering/RenderingStyle.mjs +22 -15
- package/dist/mjs/rendering/TextRenderingStyle.mjs +1 -1
- package/dist/mjs/rendering/caching/CacheRecord.mjs +1 -1
- package/dist/mjs/rendering/caching/CacheRecordManager.mjs +1 -1
- package/dist/mjs/rendering/caching/RenderingCache.mjs +1 -1
- package/dist/mjs/rendering/caching/RenderingCacheNode.mjs +26 -15
- package/dist/mjs/rendering/caching/testUtils.mjs +2 -2
- package/dist/mjs/rendering/renderers/AbstractRenderer.mjs +3 -1
- package/dist/mjs/rendering/renderers/CanvasRenderer.d.ts +2 -25
- package/dist/mjs/rendering/renderers/CanvasRenderer.mjs +6 -28
- package/dist/mjs/rendering/renderers/DummyRenderer.mjs +1 -1
- package/dist/mjs/rendering/renderers/SVGRenderer.mjs +40 -22
- package/dist/mjs/rendering/renderers/TextOnlyRenderer.mjs +13 -15
- package/dist/mjs/shortcuts/KeyBinding.mjs +6 -12
- package/dist/mjs/shortcuts/KeyboardShortcutManager.mjs +2 -2
- package/dist/mjs/testing/createEditor.mjs +6 -1
- package/dist/mjs/testing/findNodeWithText.d.ts +4 -1
- package/dist/mjs/testing/findNodeWithText.mjs +12 -3
- package/dist/mjs/testing/getUniquePointerId.mjs +1 -1
- package/dist/mjs/testing/sendHtmlSwipe.mjs +7 -3
- package/dist/mjs/testing/sendPenEvent.mjs +1 -3
- package/dist/mjs/testing/sendTouchEvent.mjs +1 -4
- package/dist/mjs/testing/startPinchGesture.mjs +3 -1
- package/dist/mjs/toolbar/AbstractToolbar.d.ts +19 -0
- package/dist/mjs/toolbar/AbstractToolbar.mjs +26 -11
- package/dist/mjs/toolbar/EdgeToolbar.mjs +11 -15
- package/dist/mjs/toolbar/IconProvider.d.ts +5 -1
- package/dist/mjs/toolbar/IconProvider.mjs +117 -149
- package/dist/mjs/toolbar/localization.mjs +5 -5
- package/dist/mjs/toolbar/utils/HelpDisplay.mjs +8 -6
- package/dist/mjs/toolbar/utils/makeDraggable.mjs +4 -7
- package/dist/mjs/toolbar/widgets/BaseToolWidget.mjs +3 -2
- package/dist/mjs/toolbar/widgets/BaseWidget.d.ts +1 -1
- package/dist/mjs/toolbar/widgets/BaseWidget.mjs +9 -9
- package/dist/mjs/toolbar/widgets/DocumentPropertiesWidget.mjs +2 -2
- package/dist/mjs/toolbar/widgets/EraserToolWidget.mjs +5 -3
- package/dist/mjs/toolbar/widgets/HandToolWidget.mjs +8 -6
- package/dist/mjs/toolbar/widgets/InsertImageWidget/InsertImageWidget.mjs +9 -10
- package/dist/mjs/toolbar/widgets/PenToolWidget.mjs +23 -14
- package/dist/mjs/toolbar/widgets/SelectionToolWidget.mjs +2 -2
- package/dist/mjs/toolbar/widgets/TextToolWidget.mjs +5 -5
- package/dist/mjs/toolbar/widgets/components/makeFileInput.mjs +7 -7
- package/dist/mjs/toolbar/widgets/components/makeGridSelector.mjs +5 -5
- package/dist/mjs/toolbar/widgets/components/makeSnappedList.mjs +9 -5
- package/dist/mjs/toolbar/widgets/keybindings.mjs +2 -2
- package/dist/mjs/toolbar/widgets/layout/DropdownLayoutManager.mjs +6 -6
- package/dist/mjs/tools/BaseTool.mjs +6 -4
- package/dist/mjs/tools/Eraser.mjs +25 -20
- package/dist/mjs/tools/FindTool.mjs +2 -2
- package/dist/mjs/tools/InputFilter/ContextMenuRecognizer.mjs +2 -4
- package/dist/mjs/tools/InputFilter/InputMapper.mjs +1 -1
- package/dist/mjs/tools/InputFilter/InputPipeline.mjs +1 -1
- package/dist/mjs/tools/InputFilter/InputStabilizer.mjs +13 -6
- package/dist/mjs/tools/InputFilter/StrokeKeyboardControl.mjs +7 -4
- package/dist/mjs/tools/PanZoom.d.ts +1 -1
- package/dist/mjs/tools/PanZoom.mjs +19 -14
- package/dist/mjs/tools/PasteHandler.mjs +8 -2
- package/dist/mjs/tools/Pen.d.ts +13 -0
- package/dist/mjs/tools/Pen.mjs +31 -10
- package/dist/mjs/tools/ScrollbarTool.mjs +8 -7
- package/dist/mjs/tools/SelectionTool/Selection.mjs +16 -12
- package/dist/mjs/tools/SelectionTool/SelectionHandle.mjs +5 -2
- package/dist/mjs/tools/SelectionTool/SelectionMenuShortcut.mjs +3 -1
- package/dist/mjs/tools/SelectionTool/SelectionTool.mjs +26 -17
- package/dist/mjs/tools/SelectionTool/ToPointerAutoscroller.mjs +1 -1
- package/dist/mjs/tools/SelectionTool/TransformMode.mjs +6 -7
- package/dist/mjs/tools/SelectionTool/util/makeClipboardErrorHandlers.mjs +23 -2
- package/dist/mjs/tools/SelectionTool/util/showSelectionContextMenu.mjs +29 -20
- package/dist/mjs/tools/SoundUITool.mjs +5 -3
- package/dist/mjs/tools/TextTool.mjs +8 -6
- package/dist/mjs/tools/ToolController.mjs +16 -10
- package/dist/mjs/tools/lib.d.ts +1 -0
- package/dist/mjs/tools/lib.mjs +1 -0
- package/dist/mjs/tools/localization.d.ts +2 -0
- package/dist/mjs/tools/localization.mjs +3 -1
- package/dist/mjs/tools/util/StationaryPenDetector.mjs +3 -3
- package/dist/mjs/tools/util/createMenuOverlay.mjs +2 -2
- package/dist/mjs/util/ClipboardHandler.d.ts +1 -1
- package/dist/mjs/util/ClipboardHandler.mjs +19 -18
- package/dist/mjs/util/ReactiveValue.mjs +16 -12
- package/dist/mjs/util/adjustEditorThemeForContrast.mjs +6 -2
- package/dist/mjs/util/cloneElementWithStyles.mjs +1 -1
- package/dist/mjs/util/createElement.d.ts +62 -0
- package/dist/mjs/util/createElement.mjs +47 -0
- package/dist/mjs/util/guessKeyCodeFromKey.mjs +1 -1
- package/dist/mjs/util/listenForKeyboardEventsFrom.mjs +8 -6
- package/dist/mjs/util/waitForAll.mjs +3 -3
- package/dist/mjs/util/waitForImageLoaded.mjs +3 -3
- package/dist/mjs/util/waitForTimeout.mjs +1 -1
- package/dist/mjs/version.mjs +1 -1
- package/package.json +88 -88
- package/src/Coloris.css +6 -6
- package/src/Editor.scss +7 -5
- package/src/dialogs/dialogs.scss +3 -4
- package/src/dialogs/makeAboutDialog.scss +2 -2
- package/src/dialogs/makeMessageDialog.scss +11 -7
- package/src/styles.js +1 -1
- package/src/toolbar/AbstractToolbar.scss +20 -12
- package/src/toolbar/DropdownToolbar.scss +5 -4
- package/src/toolbar/EdgeToolbar.scss +65 -31
- package/src/toolbar/toolbar.scss +5 -5
- package/src/toolbar/utils/HelpDisplay.scss +48 -25
- package/src/toolbar/utils/labelVisibleOnHover.scss +39 -16
- package/src/toolbar/widgets/DocumentPropertiesWidget.scss +0 -1
- package/src/toolbar/widgets/HandToolWidget.scss +0 -1
- package/src/toolbar/widgets/InsertImageWidget/InsertImageWidget.scss +2 -3
- package/src/toolbar/widgets/OverflowWidget.css +1 -2
- package/src/toolbar/widgets/PenToolWidget.scss +0 -2
- package/src/toolbar/widgets/SelectionToolWidget.scss +1 -2
- package/src/toolbar/widgets/components/components.scss +6 -6
- package/src/toolbar/widgets/components/makeColorInput.scss +0 -2
- package/src/toolbar/widgets/components/makeFileInput.scss +5 -7
- package/src/toolbar/widgets/components/makeGridSelector.scss +6 -9
- package/src/toolbar/widgets/components/makeSnappedList.scss +3 -4
- package/src/toolbar/widgets/components/makeThicknessSlider.scss +1 -2
- package/src/toolbar/widgets/widgets.scss +7 -7
- package/src/tools/FindTool.css +1 -2
- package/src/tools/ScrollbarTool.scss +9 -5
- package/src/tools/SelectionTool/SelectionTool.scss +15 -7
- package/src/tools/SelectionTool/util/makeClipboardErrorHandlers.scss +1 -2
- package/src/tools/SoundUITool.scss +4 -4
- package/src/tools/tools.scss +5 -6
- package/src/tools/util/createMenuOverlay.scss +10 -4
- package/tsconfig.json +1 -3
- package/typedoc.json +1 -1
@@ -3,6 +3,12 @@ import Stroke from '../Stroke.mjs';
|
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import { StrokeSmoother } from '../util/StrokeSmoother.mjs';
|
5
5
|
import makeShapeFitAutocorrect from './autocorrect/makeShapeFitAutocorrect.mjs';
|
6
|
+
/**
|
7
|
+
* Creates a stroke builder that draws freehand lines.
|
8
|
+
*
|
9
|
+
* Example:
|
10
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
11
|
+
*/
|
6
12
|
export const makeFreehandLineBuilder = makeShapeFitAutocorrect((initialPoint, viewport) => {
|
7
13
|
// Don't smooth if input is more than ± 3 pixels from the true curve, do smooth if
|
8
14
|
// less than ±1 px from the curve.
|
@@ -32,7 +38,7 @@ export default class FreehandLineBuilder {
|
|
32
38
|
stroke: {
|
33
39
|
color: this.startPoint.color,
|
34
40
|
width: this.roundDistance(this.averageWidth),
|
35
|
-
}
|
41
|
+
},
|
36
42
|
};
|
37
43
|
}
|
38
44
|
previewCurrentPath() {
|
@@ -129,7 +135,7 @@ export default class FreehandLineBuilder {
|
|
129
135
|
kind: PathCommandType.QuadraticBezierTo,
|
130
136
|
controlPoint: center.plus(Vec2.of(width, -width)),
|
131
137
|
endPoint: center.plus(Vec2.of(width, 0)),
|
132
|
-
}
|
138
|
+
},
|
133
139
|
];
|
134
140
|
}
|
135
141
|
const result = [];
|
@@ -157,7 +163,7 @@ export default class FreehandLineBuilder {
|
|
157
163
|
this.curveFitter.addPoint(newPoint);
|
158
164
|
this.widthAverageNumSamples++;
|
159
165
|
this.averageWidth =
|
160
|
-
this.averageWidth * (this.widthAverageNumSamples - 1) / this.widthAverageNumSamples
|
161
|
-
|
166
|
+
(this.averageWidth * (this.widthAverageNumSamples - 1)) / this.widthAverageNumSamples +
|
167
|
+
newPoint.width / this.widthAverageNumSamples;
|
162
168
|
}
|
163
169
|
}
|
@@ -4,6 +4,12 @@ import { StrokeDataPoint } from '../../types';
|
|
4
4
|
import Viewport from '../../Viewport';
|
5
5
|
import AbstractComponent from '../AbstractComponent';
|
6
6
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
7
|
+
/**
|
8
|
+
* Creates a stroke builder that generates filled lines.
|
9
|
+
*
|
10
|
+
* Example:
|
11
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
|
+
*/
|
7
13
|
export declare const makeLineBuilder: ComponentBuilderFactory;
|
8
14
|
export default class LineBuilder implements ComponentBuilder {
|
9
15
|
private readonly startPoint;
|
@@ -2,6 +2,12 @@ import { Path, PathCommandType } from '@js-draw/math';
|
|
2
2
|
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
3
3
|
import Stroke from '../Stroke.mjs';
|
4
4
|
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
5
|
+
/**
|
6
|
+
* Creates a stroke builder that generates filled lines.
|
7
|
+
*
|
8
|
+
* Example:
|
9
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
10
|
+
*/
|
5
11
|
export const makeLineBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
6
12
|
return new LineBuilder(initialPoint, viewport);
|
7
13
|
});
|
@@ -42,10 +48,8 @@ export default class LineBuilder {
|
|
42
48
|
kind: PathCommandType.LineTo,
|
43
49
|
point: startPoint.minus(scaledStartNormal),
|
44
50
|
},
|
45
|
-
]).mapPoints(point => this.viewport.roundPoint(point));
|
46
|
-
const preview = new Stroke([
|
47
|
-
pathToRenderable(path, { fill: this.startPoint.color })
|
48
|
-
]);
|
51
|
+
]).mapPoints((point) => this.viewport.roundPoint(point));
|
52
|
+
const preview = new Stroke([pathToRenderable(path, { fill: this.startPoint.color })]);
|
49
53
|
return preview;
|
50
54
|
}
|
51
55
|
build() {
|
@@ -7,8 +7,11 @@ import { StrokeDataPoint } from '../../types';
|
|
7
7
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
8
8
|
import RenderingStyle from '../../rendering/RenderingStyle';
|
9
9
|
/**
|
10
|
-
* Creates
|
10
|
+
* Creates a freehand line builder that creates strokes from line segments
|
11
|
+
* rather than Bézier curves.
|
11
12
|
*
|
13
|
+
* Example:
|
14
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
15
|
*/
|
13
16
|
export declare const makePolylineBuilder: ComponentBuilderFactory;
|
14
17
|
export default class PolylineBuilder implements ComponentBuilder {
|
@@ -1,10 +1,13 @@
|
|
1
|
-
import { Rect2, Color4, PathCommandType, Vec2, LineSegment2 } from '@js-draw/math';
|
1
|
+
import { Rect2, Color4, PathCommandType, Vec2, LineSegment2, } from '@js-draw/math';
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import makeShapeFitAutocorrect from './autocorrect/makeShapeFitAutocorrect.mjs';
|
5
5
|
/**
|
6
|
-
* Creates
|
6
|
+
* Creates a freehand line builder that creates strokes from line segments
|
7
|
+
* rather than Bézier curves.
|
7
8
|
*
|
9
|
+
* Example:
|
10
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
8
11
|
*/
|
9
12
|
export const makePolylineBuilder = makeShapeFitAutocorrect((initialPoint, viewport) => {
|
10
13
|
// Fit to a value slightly smaller than the pixel size. A larger value can
|
@@ -42,7 +45,7 @@ export default class PolylineBuilder {
|
|
42
45
|
stroke: {
|
43
46
|
color: this.startPoint.color,
|
44
47
|
width: this.roundDistance(this.averageWidth),
|
45
|
-
}
|
48
|
+
},
|
46
49
|
};
|
47
50
|
}
|
48
51
|
previewCurrentPath() {
|
@@ -96,12 +99,13 @@ export default class PolylineBuilder {
|
|
96
99
|
addPoint(newPoint) {
|
97
100
|
this.widthAverageNumSamples++;
|
98
101
|
this.averageWidth =
|
99
|
-
this.averageWidth * (this.widthAverageNumSamples - 1) / this.widthAverageNumSamples
|
100
|
-
|
102
|
+
(this.averageWidth * (this.widthAverageNumSamples - 1)) / this.widthAverageNumSamples +
|
103
|
+
newPoint.width / this.widthAverageNumSamples;
|
101
104
|
const roundedPoint = this.roundPoint(newPoint.pos);
|
102
105
|
if (!roundedPoint.eq(this.lastPoint)) {
|
103
106
|
// If almost exactly in the same line as the previous
|
104
|
-
if (this.lastLineSegment &&
|
107
|
+
if (this.lastLineSegment &&
|
108
|
+
this.lastLineSegment.direction.dot(roundedPoint.minus(this.lastPoint).normalized()) > 0.997) {
|
105
109
|
this.parts.pop();
|
106
110
|
this.lastPoint = this.lastLineSegment.p1;
|
107
111
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Vec2, Rect2, PathCommandType, QuadraticBezier } from '@js-draw/math';
|
1
|
+
import { Vec2, Rect2, PathCommandType, QuadraticBezier, } from '@js-draw/math';
|
2
2
|
import Stroke from '../Stroke.mjs';
|
3
3
|
import Viewport from '../../Viewport.mjs';
|
4
4
|
import { StrokeSmoother } from '../util/StrokeSmoother.mjs';
|
@@ -30,7 +30,7 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
30
30
|
this.parts = [];
|
31
31
|
this.upperSegments = [];
|
32
32
|
this.lowerSegments = [];
|
33
|
-
this.curveFitter = new StrokeSmoother(startPoint, minFitAllowed, maxFitAllowed, curve => this.addCurve(curve));
|
33
|
+
this.curveFitter = new StrokeSmoother(startPoint, minFitAllowed, maxFitAllowed, (curve) => this.addCurve(curve));
|
34
34
|
this.curveStartWidth = startPoint.width;
|
35
35
|
this.bbox = new Rect2(this.startPoint.pos.x, this.startPoint.pos.y, 0, 0);
|
36
36
|
}
|
@@ -64,7 +64,8 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
64
64
|
}
|
65
65
|
let startPoint;
|
66
66
|
const lastLowerSegment = lowerPath[lowerPath.length - 1];
|
67
|
-
if (lastLowerSegment.kind === PathCommandType.LineTo ||
|
67
|
+
if (lastLowerSegment.kind === PathCommandType.LineTo ||
|
68
|
+
lastLowerSegment.kind === PathCommandType.MoveTo) {
|
68
69
|
startPoint = lastLowerSegment.point;
|
69
70
|
}
|
70
71
|
else {
|
@@ -163,11 +164,11 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
163
164
|
// where the next stroke and the previous stroke are in different directions.
|
164
165
|
//
|
165
166
|
// Are the exit/enter directions of the previous and current curves in different enough directions?
|
166
|
-
if (getEnterDirection(upperCurve).dot(getExitDirection(this.lastUpperBezier)) < 0.35
|
167
|
-
|
167
|
+
if (getEnterDirection(upperCurve).dot(getExitDirection(this.lastUpperBezier)) < 0.35 ||
|
168
|
+
getEnterDirection(lowerCurve).dot(getExitDirection(this.lastLowerBezier)) < 0.35 ||
|
168
169
|
// Also handle if the curves exit/enter directions differ
|
169
|
-
|
170
|
-
|
170
|
+
getEnterDirection(upperCurve).dot(getExitDirection(upperCurve)) < 0 ||
|
171
|
+
getEnterDirection(lowerCurve).dot(getExitDirection(lowerCurve)) < 0) {
|
171
172
|
return true;
|
172
173
|
}
|
173
174
|
// Check whether the lower curve intersects the other wall:
|
@@ -274,8 +275,9 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
274
275
|
// Approximate the normal at the location of the control point
|
275
276
|
const projectionT = bezier.nearestPointTo(controlPoint).parameterValue;
|
276
277
|
const halfVecT = projectionT;
|
277
|
-
const halfVec = bezier
|
278
|
-
|
278
|
+
const halfVec = bezier
|
279
|
+
.normal(halfVecT)
|
280
|
+
.times((curve.startWidth / 2) * halfVecT + (curve.endWidth / 2) * (1 - halfVecT));
|
279
281
|
// Each starts at startPt ± startVec
|
280
282
|
const lowerCurveStartPoint = this.roundPoint(startPt.plus(startVec));
|
281
283
|
const lowerCurveControlPoint = this.roundPoint(controlPoint.plus(halfVec));
|
@@ -318,8 +320,12 @@ export default class PressureSensitiveFreehandLineBuilder {
|
|
318
320
|
const upperCurve = new QuadraticBezier(upperCurveStartPoint, upperCurveControlPoint, upperCurveEndPoint);
|
319
321
|
const lowerCurve = new QuadraticBezier(lowerCurveStartPoint, lowerCurveControlPoint, lowerCurveEndPoint);
|
320
322
|
return {
|
321
|
-
upperCurveCommand,
|
322
|
-
|
323
|
+
upperCurveCommand,
|
324
|
+
upperToLowerConnector,
|
325
|
+
lowerToUpperConnector,
|
326
|
+
lowerCurveCommand,
|
327
|
+
upperCurve,
|
328
|
+
lowerCurve,
|
323
329
|
nextCurveStartConnector,
|
324
330
|
};
|
325
331
|
}
|
@@ -4,7 +4,19 @@ import { StrokeDataPoint } from '../../types';
|
|
4
4
|
import Viewport from '../../Viewport';
|
5
5
|
import AbstractComponent from '../AbstractComponent';
|
6
6
|
import { ComponentBuilder, ComponentBuilderFactory } from './types';
|
7
|
+
/**
|
8
|
+
* Creates filled rectangles with sharp corners.
|
9
|
+
*
|
10
|
+
* Example:
|
11
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
12
|
+
*/
|
7
13
|
export declare const makeFilledRectangleBuilder: ComponentBuilderFactory;
|
14
|
+
/**
|
15
|
+
* Creates outlined rectangles with sharp corners.
|
16
|
+
*
|
17
|
+
* Example:
|
18
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
19
|
+
*/
|
8
20
|
export declare const makeOutlinedRectangleBuilder: ComponentBuilderFactory;
|
9
21
|
export default class RectangleBuilder implements ComponentBuilder {
|
10
22
|
private readonly startPoint;
|
@@ -2,9 +2,21 @@ import { Mat33, Rect2, Path } from '@js-draw/math';
|
|
2
2
|
import { pathToRenderable } from '../../rendering/RenderablePathSpec.mjs';
|
3
3
|
import Stroke from '../Stroke.mjs';
|
4
4
|
import makeSnapToGridAutocorrect from './autocorrect/makeSnapToGridAutocorrect.mjs';
|
5
|
+
/**
|
6
|
+
* Creates filled rectangles with sharp corners.
|
7
|
+
*
|
8
|
+
* Example:
|
9
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
10
|
+
*/
|
5
11
|
export const makeFilledRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
6
12
|
return new RectangleBuilder(initialPoint, true, viewport);
|
7
13
|
});
|
14
|
+
/**
|
15
|
+
* Creates outlined rectangles with sharp corners.
|
16
|
+
*
|
17
|
+
* Example:
|
18
|
+
* [[include:doc-pages/inline-examples/changing-pen-types.md]]
|
19
|
+
*/
|
8
20
|
export const makeOutlinedRectangleBuilder = makeSnapToGridAutocorrect((initialPoint, viewport) => {
|
9
21
|
return new RectangleBuilder(initialPoint, false, viewport);
|
10
22
|
});
|
@@ -28,12 +40,14 @@ export default class RectangleBuilder {
|
|
28
40
|
const startPoint = rotationMat.inverse().transformVec2(this.startPoint.pos);
|
29
41
|
const endPoint = rotationMat.inverse().transformVec2(this.endPoint.pos);
|
30
42
|
const rect = Rect2.fromCorners(startPoint, endPoint);
|
31
|
-
const path = Path.fromRect(rect, this.filled ? null : this.endPoint.width)
|
43
|
+
const path = Path.fromRect(rect, this.filled ? null : this.endPoint.width)
|
44
|
+
.transformedBy(
|
32
45
|
// Rotate the canvas rectangle so that its rotation matches the screen
|
33
|
-
rotationMat)
|
46
|
+
rotationMat)
|
47
|
+
.mapPoints((point) => this.viewport.roundPoint(point));
|
34
48
|
const preview = new Stroke([
|
35
49
|
pathToRenderable(path, {
|
36
|
-
fill: this.endPoint.color
|
50
|
+
fill: this.endPoint.color,
|
37
51
|
}),
|
38
52
|
]);
|
39
53
|
return preview;
|
@@ -6,14 +6,11 @@ const makeShapeFitAutocorrect = (sourceFactory) => {
|
|
6
6
|
};
|
7
7
|
export default makeShapeFitAutocorrect;
|
8
8
|
const makeLineTemplate = (startPoint, points, _bbox) => {
|
9
|
-
const templatePoints = [
|
10
|
-
|
11
|
-
points[points.length - 1],
|
12
|
-
];
|
13
|
-
return { points: templatePoints, };
|
9
|
+
const templatePoints = [startPoint, points[points.length - 1]];
|
10
|
+
return { points: templatePoints };
|
14
11
|
};
|
15
12
|
const makeRectangleTemplate = (_startPoint, _points, bbox) => {
|
16
|
-
return { points: [...bbox.corners, bbox.corners[0]]
|
13
|
+
return { points: [...bbox.corners, bbox.corners[0]] };
|
17
14
|
};
|
18
15
|
class ShapeFitBuilder {
|
19
16
|
constructor(sourceFactory, startPoint, viewport) {
|
@@ -39,10 +36,10 @@ class ShapeFitBuilder {
|
|
39
36
|
async autocorrectShape() {
|
40
37
|
// Use screen points so that autocorrected shapes rotate with the screen.
|
41
38
|
const startPoint = this.viewport.canvasToScreen(this.startPoint.pos);
|
42
|
-
const points = this.points.map(point => this.viewport.canvasToScreen(point.pos));
|
39
|
+
const points = this.points.map((point) => this.viewport.canvasToScreen(point.pos));
|
43
40
|
const bbox = Rect2.bboxOf(points);
|
44
41
|
const snappedStartPoint = this.viewport.canvasToScreen(this.viewport.snapToGrid(this.startPoint.pos));
|
45
|
-
const snappedPoints = this.points.map(point => this.viewport.canvasToScreen(this.viewport.snapToGrid(point.pos)));
|
42
|
+
const snappedPoints = this.points.map((point) => this.viewport.canvasToScreen(this.viewport.snapToGrid(point.pos)));
|
46
43
|
const snappedBBox = Rect2.bboxOf(snappedPoints);
|
47
44
|
// Only fit larger shapes
|
48
45
|
if (bbox.maxDimension < 32) {
|
@@ -35,7 +35,7 @@ class SnapToGridAutocompleteBuilder {
|
|
35
35
|
// Use screen points so that snapped shapes rotate with the screen.
|
36
36
|
const startPoint = snapToGrid(this.startPoint);
|
37
37
|
const builder = this.sourceFactory(startPoint, this.viewport);
|
38
|
-
const points = this.points.map(point => snapToGrid(point));
|
38
|
+
const points = this.points.map((point) => snapToGrid(point));
|
39
39
|
for (const point of points) {
|
40
40
|
builder.addPoint(point);
|
41
41
|
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
export { makeFreehandLineBuilder } from './FreehandLineBuilder';
|
2
|
+
export { makePolylineBuilder } from './PolylineBuilder';
|
3
|
+
export { makePressureSensitiveFreehandLineBuilder } from './PressureSensitiveFreehandLineBuilder';
|
4
|
+
export { makeOutlinedCircleBuilder } from './CircleBuilder';
|
5
|
+
export { makeArrowBuilder } from './ArrowBuilder';
|
6
|
+
export { makeLineBuilder } from './LineBuilder';
|
7
|
+
export { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from './RectangleBuilder';
|
@@ -0,0 +1,7 @@
|
|
1
|
+
export { makeFreehandLineBuilder } from './FreehandLineBuilder.mjs';
|
2
|
+
export { makePolylineBuilder } from './PolylineBuilder.mjs';
|
3
|
+
export { makePressureSensitiveFreehandLineBuilder } from './PressureSensitiveFreehandLineBuilder.mjs';
|
4
|
+
export { makeOutlinedCircleBuilder } from './CircleBuilder.mjs';
|
5
|
+
export { makeArrowBuilder } from './ArrowBuilder.mjs';
|
6
|
+
export { makeLineBuilder } from './LineBuilder.mjs';
|
7
|
+
export { makeFilledRectangleBuilder, makeOutlinedRectangleBuilder } from './RectangleBuilder.mjs';
|
@@ -1,8 +1,5 @@
|
|
1
1
|
export * from './builders/types';
|
2
|
-
export
|
3
|
-
export { makePolylineBuilder } from './builders/PolylineBuilder';
|
4
|
-
export { makePressureSensitiveFreehandLineBuilder } from './builders/PressureSensitiveFreehandLineBuilder';
|
5
|
-
export { makeOutlinedCircleBuilder } from './builders/CircleBuilder';
|
2
|
+
export * from './builders/lib';
|
6
3
|
export { default as StrokeSmoother, Curve as StrokeSmootherCurve } from './util/StrokeSmoother';
|
7
4
|
export * from './AbstractComponent';
|
8
5
|
export { default as AbstractComponent } from './AbstractComponent';
|
@@ -1,15 +1,12 @@
|
|
1
1
|
export * from './builders/types.mjs';
|
2
|
-
export
|
3
|
-
export { makePolylineBuilder } from './builders/PolylineBuilder.mjs';
|
4
|
-
export { makePressureSensitiveFreehandLineBuilder } from './builders/PressureSensitiveFreehandLineBuilder.mjs';
|
5
|
-
export { makeOutlinedCircleBuilder } from './builders/CircleBuilder.mjs';
|
2
|
+
export * from './builders/lib.mjs';
|
6
3
|
export { default as StrokeSmoother } from './util/StrokeSmoother.mjs';
|
7
4
|
export * from './AbstractComponent.mjs';
|
8
5
|
export { default as AbstractComponent } from './AbstractComponent.mjs';
|
9
6
|
import Stroke from './Stroke.mjs';
|
10
7
|
import TextComponent from './TextComponent.mjs';
|
11
8
|
import ImageComponent from './ImageComponent.mjs';
|
12
|
-
import { createRestyleComponentCommand, isRestylableComponent } from './RestylableComponent.mjs';
|
9
|
+
import { createRestyleComponentCommand, isRestylableComponent, } from './RestylableComponent.mjs';
|
13
10
|
import BackgroundComponent, { BackgroundType } from './BackgroundComponent.mjs';
|
14
11
|
export { Stroke, createRestyleComponentCommand, isRestylableComponent, TextComponent,
|
15
12
|
/** @deprecated use {@link TextComponent} */
|
@@ -53,9 +53,7 @@ export class StrokeSmoother {
|
|
53
53
|
console.assert(this.lastExitingVec.magnitude() !== 0, 'lastExitingVec has zero length!');
|
54
54
|
// Use the last two points to start a new curve (the last point isn't used
|
55
55
|
// in the current curve and we want connected curves to share end points)
|
56
|
-
this.buffer = [
|
57
|
-
this.buffer[this.buffer.length - 2], lastPoint,
|
58
|
-
];
|
56
|
+
this.buffer = [this.buffer[this.buffer.length - 2], lastPoint];
|
59
57
|
this.currentCurve = null;
|
60
58
|
this.isFirstSegment = false;
|
61
59
|
}
|
@@ -96,8 +94,7 @@ export class StrokeSmoother {
|
|
96
94
|
return;
|
97
95
|
}
|
98
96
|
const threshold = Math.min(this.lastPoint.width, newPoint.width) / 3;
|
99
|
-
const shouldSnapToInitial = this.startPoint.pos.distanceTo(newPoint.pos) < threshold
|
100
|
-
&& this.isFirstSegment;
|
97
|
+
const shouldSnapToInitial = this.startPoint.pos.distanceTo(newPoint.pos) < threshold && this.isFirstSegment;
|
101
98
|
// Snap to the starting point if the stroke is contained within a small ball centered
|
102
99
|
// at the starting point.
|
103
100
|
// This allows us to create a circle/dot at the start of the stroke.
|
@@ -150,7 +147,9 @@ export class StrokeSmoother {
|
|
150
147
|
const startEndDist = segmentEnd.distanceTo(segmentStart);
|
151
148
|
const maxControlPointDist = maxRelativeLength * startEndDist;
|
152
149
|
// Exit in cases where we would divide by zero
|
153
|
-
if (maxControlPointDist === 0 ||
|
150
|
+
if (maxControlPointDist === 0 ||
|
151
|
+
exitingVec.magnitude() === 0 ||
|
152
|
+
!isFinite(exitingVec.magnitude())) {
|
154
153
|
return;
|
155
154
|
}
|
156
155
|
console.assert(isFinite(enteringVec.magnitude()), 'Pre-normalized enteringVec has NaN or ∞ magnitude!');
|
@@ -8,7 +8,7 @@ const makeAboutDialog = (editor, entries) => {
|
|
8
8
|
const container = document.createElement(entry.minimized ? 'details' : 'div');
|
9
9
|
container.classList.add('about-entry');
|
10
10
|
const header = document.createElement(entry.minimized ? 'summary' : 'h2');
|
11
|
-
if (typeof
|
11
|
+
if (typeof entry.heading === 'string') {
|
12
12
|
header.innerText = entry.heading;
|
13
13
|
}
|
14
14
|
else {
|
@@ -15,7 +15,7 @@ const makeAboutDialog = (editor, options) => {
|
|
15
15
|
const scrollRegion = document.createElement('div');
|
16
16
|
scrollRegion.classList.add('scroll');
|
17
17
|
// Allow scrolling in the scrollable container -- don't forward wheel events.
|
18
|
-
scrollRegion.onwheel = evt => evt.stopPropagation();
|
18
|
+
scrollRegion.onwheel = (evt) => evt.stopPropagation();
|
19
19
|
contentWrapper.replaceChildren(heading, scrollRegion, closeButton);
|
20
20
|
dialog.replaceChildren(contentWrapper);
|
21
21
|
overlay.replaceChildren(dialog);
|
@@ -27,7 +27,7 @@ const makeAboutDialog = (editor, options) => {
|
|
27
27
|
dialog.close();
|
28
28
|
};
|
29
29
|
const addCloseListeners = () => {
|
30
|
-
dialog.addEventListener('pointerdown', event => {
|
30
|
+
dialog.addEventListener('pointerdown', (event) => {
|
31
31
|
if (event.target === dialog) {
|
32
32
|
void closeDialog();
|
33
33
|
}
|
@@ -22,7 +22,20 @@ export type EditorImageNotifier = EventDispatcher<EditorImageEventType, {
|
|
22
22
|
*/
|
23
23
|
export type PreRenderComponentCallback = (component: AbstractComponent, componentsProcessed: number, totalComponents: number) => Promise<boolean>;
|
24
24
|
/**
|
25
|
-
* Handles lookup/storage of elements in the image.
|
25
|
+
* @summary Handles lookup/storage of elements in the image.
|
26
|
+
*
|
27
|
+
* `js-draw` images are made up of a collection of {@link AbstractComponent}s (which
|
28
|
+
* includes {@link Stroke}s, {@link TextComponent}s, etc.). An `EditorImage`
|
29
|
+
* is the data structure that stores these components.
|
30
|
+
*
|
31
|
+
* Here's how to do a few common operations:
|
32
|
+
* - **Get all components in a {@link @js-draw/math!Rect2 | Rect2}**:
|
33
|
+
* {@link EditorImage.getElementsIntersectingRegion}.
|
34
|
+
* - **Draw an `EditorImage` onto a canvas/SVG**: {@link EditorImage.render}.
|
35
|
+
* - **Adding a new component**: {@link EditorImage.addElement}.
|
36
|
+
*
|
37
|
+
* **Example**:
|
38
|
+
* [[include:doc-pages/inline-examples/image-add-and-lookup.md]]
|
26
39
|
*/
|
27
40
|
export default class EditorImage {
|
28
41
|
private root;
|
@@ -40,10 +53,13 @@ export default class EditorImage {
|
|
40
53
|
/** @internal */
|
41
54
|
renderWithCache(screenRenderer: AbstractRenderer, cache: RenderingCache, viewport: Viewport): void;
|
42
55
|
/**
|
43
|
-
* Renders
|
56
|
+
* Renders this image to the given `renderer`.
|
44
57
|
*
|
45
|
-
* `viewport` is
|
46
|
-
*
|
58
|
+
* If `viewport` is non-null, only components that can be seen from that viewport
|
59
|
+
* will be rendered. If `viewport` is `null`, **all** components are rendered.
|
60
|
+
*
|
61
|
+
* **Example**:
|
62
|
+
* [[include:doc-pages/inline-examples/canvas-renderer.md]]
|
47
63
|
*/
|
48
64
|
render(renderer: AbstractRenderer, viewport: Viewport | null): void;
|
49
65
|
/**
|
@@ -63,14 +79,21 @@ export default class EditorImage {
|
|
63
79
|
*/
|
64
80
|
renderAll(renderer: AbstractRenderer): void;
|
65
81
|
/**
|
66
|
-
* @returns all elements in the image, sorted by z-index
|
82
|
+
* @returns all elements in the image, sorted by z-index (low to high).
|
67
83
|
*
|
68
|
-
*
|
84
|
+
* This can be slow for large images. If you only need all elemenst in part of the image,
|
85
|
+
* consider using {@link getElementsIntersectingRegion} instead.
|
86
|
+
*
|
87
|
+
* **Note**: The result does not include background elements. See {@link getBackgroundComponents}.
|
69
88
|
*/
|
70
89
|
getAllElements(): AbstractComponent[];
|
71
90
|
/** Returns the number of elements added to this image. @internal */
|
72
91
|
estimateNumElements(): number;
|
73
|
-
/**
|
92
|
+
/**
|
93
|
+
* @returns a list of `AbstractComponent`s intersecting `region`, sorted by increasing z-index.
|
94
|
+
*
|
95
|
+
* Components in the background layer are only included if `includeBackground` is `true`.
|
96
|
+
*/
|
74
97
|
getElementsIntersectingRegion(region: Rect2, includeBackground?: boolean): AbstractComponent[];
|
75
98
|
/** Called whenever (just after) an element is completely removed. @internal */
|
76
99
|
onDestroyElement(elem: AbstractComponent): void;
|
@@ -21,7 +21,20 @@ export var EditorImageEventType;
|
|
21
21
|
})(EditorImageEventType || (EditorImageEventType = {}));
|
22
22
|
let debugMode = false;
|
23
23
|
/**
|
24
|
-
* Handles lookup/storage of elements in the image.
|
24
|
+
* @summary Handles lookup/storage of elements in the image.
|
25
|
+
*
|
26
|
+
* `js-draw` images are made up of a collection of {@link AbstractComponent}s (which
|
27
|
+
* includes {@link Stroke}s, {@link TextComponent}s, etc.). An `EditorImage`
|
28
|
+
* is the data structure that stores these components.
|
29
|
+
*
|
30
|
+
* Here's how to do a few common operations:
|
31
|
+
* - **Get all components in a {@link @js-draw/math!Rect2 | Rect2}**:
|
32
|
+
* {@link EditorImage.getElementsIntersectingRegion}.
|
33
|
+
* - **Draw an `EditorImage` onto a canvas/SVG**: {@link EditorImage.render}.
|
34
|
+
* - **Adding a new component**: {@link EditorImage.addElement}.
|
35
|
+
*
|
36
|
+
* **Example**:
|
37
|
+
* [[include:doc-pages/inline-examples/image-add-and-lookup.md]]
|
25
38
|
*/
|
26
39
|
class EditorImage {
|
27
40
|
// @internal
|
@@ -80,10 +93,13 @@ class EditorImage {
|
|
80
93
|
}
|
81
94
|
}
|
82
95
|
/**
|
83
|
-
* Renders
|
96
|
+
* Renders this image to the given `renderer`.
|
84
97
|
*
|
85
|
-
* `viewport` is
|
86
|
-
*
|
98
|
+
* If `viewport` is non-null, only components that can be seen from that viewport
|
99
|
+
* will be rendered. If `viewport` is `null`, **all** components are rendered.
|
100
|
+
*
|
101
|
+
* **Example**:
|
102
|
+
* [[include:doc-pages/inline-examples/canvas-renderer.md]]
|
87
103
|
*/
|
88
104
|
render(renderer, viewport) {
|
89
105
|
this.background.render(renderer, viewport?.visibleRect);
|
@@ -114,27 +130,34 @@ class EditorImage {
|
|
114
130
|
this.render(renderer, null);
|
115
131
|
}
|
116
132
|
/**
|
117
|
-
* @returns all elements in the image, sorted by z-index
|
133
|
+
* @returns all elements in the image, sorted by z-index (low to high).
|
118
134
|
*
|
119
|
-
*
|
135
|
+
* This can be slow for large images. If you only need all elemenst in part of the image,
|
136
|
+
* consider using {@link getElementsIntersectingRegion} instead.
|
137
|
+
*
|
138
|
+
* **Note**: The result does not include background elements. See {@link getBackgroundComponents}.
|
120
139
|
*/
|
121
140
|
getAllElements() {
|
122
141
|
const leaves = this.root.getLeaves();
|
123
142
|
sortLeavesByZIndex(leaves);
|
124
|
-
return leaves.map(leaf => leaf.getContent());
|
143
|
+
return leaves.map((leaf) => leaf.getContent());
|
125
144
|
}
|
126
145
|
/** Returns the number of elements added to this image. @internal */
|
127
146
|
estimateNumElements() {
|
128
147
|
return this.componentCount;
|
129
148
|
}
|
130
|
-
/**
|
149
|
+
/**
|
150
|
+
* @returns a list of `AbstractComponent`s intersecting `region`, sorted by increasing z-index.
|
151
|
+
*
|
152
|
+
* Components in the background layer are only included if `includeBackground` is `true`.
|
153
|
+
*/
|
131
154
|
getElementsIntersectingRegion(region, includeBackground = false) {
|
132
155
|
let leaves = this.root.getLeavesIntersectingRegion(region);
|
133
156
|
if (includeBackground) {
|
134
157
|
leaves = leaves.concat(this.background.getLeavesIntersectingRegion(region));
|
135
158
|
}
|
136
159
|
sortLeavesByZIndex(leaves);
|
137
|
-
return leaves.map(leaf => leaf.getContent());
|
160
|
+
return leaves.map((leaf) => leaf.getContent());
|
138
161
|
}
|
139
162
|
/** Called whenever (just after) an element is completely removed. @internal */
|
140
163
|
onDestroyElement(elem) {
|
@@ -474,8 +497,8 @@ export const computeFirstIndexToRender = (sortedLeaves, visibleRect) => {
|
|
474
497
|
for (let i = sortedLeaves.length - 1; i >= 1; i--) {
|
475
498
|
if (
|
476
499
|
// Check for occlusion
|
477
|
-
sortedLeaves[i].getBBox().containsRect(visibleRect)
|
478
|
-
|
500
|
+
sortedLeaves[i].getBBox().containsRect(visibleRect) &&
|
501
|
+
sortedLeaves[i].getContent()?.occludesEverythingBelowWhenRenderedInRect(visibleRect)) {
|
479
502
|
startIndex = i;
|
480
503
|
break;
|
481
504
|
}
|
@@ -510,7 +533,7 @@ export class ImageNode {
|
|
510
533
|
}
|
511
534
|
// Override this to change how children are considered within a given region.
|
512
535
|
getChildrenIntersectingRegion(region, isTooSmallFilter) {
|
513
|
-
return this.children.filter(child => {
|
536
|
+
return this.children.filter((child) => {
|
514
537
|
const bbox = child.getBBox();
|
515
538
|
return !isTooSmallFilter?.(bbox) && bbox.intersects(region);
|
516
539
|
});
|
@@ -601,7 +624,7 @@ export class ImageNode {
|
|
601
624
|
}
|
602
625
|
return nodeForNewLeaf.addLeaf(leaf);
|
603
626
|
}
|
604
|
-
const containingNodes = this.children.filter(child => child.getBBox().containsRect(leafBBox));
|
627
|
+
const containingNodes = this.children.filter((child) => child.getBBox().containsRect(leafBBox));
|
605
628
|
// Does the leaf already fit within one of the children?
|
606
629
|
if (containingNodes.length > 0 && this.children.length >= this.targetChildCount) {
|
607
630
|
// Sort the containers in ascending order by area
|
@@ -639,7 +662,7 @@ export class ImageNode {
|
|
639
662
|
this.bbox = this.content.getBBox();
|
640
663
|
}
|
641
664
|
else {
|
642
|
-
this.bbox = Rect2.union(...this.children.map(child => child.getBBox()));
|
665
|
+
this.bbox = Rect2.union(...this.children.map((child) => child.getBBox()));
|
643
666
|
}
|
644
667
|
if (bubbleUp && !oldBBox.eq(this.bbox)) {
|
645
668
|
if (this.bbox.containsRect(oldBBox)) {
|
@@ -674,7 +697,7 @@ export class ImageNode {
|
|
674
697
|
const oldParent = this.parent;
|
675
698
|
if (oldParent.parent !== null) {
|
676
699
|
const newParent = oldParent.parent;
|
677
|
-
newParent.children = newParent.children.filter(c => c !== oldParent);
|
700
|
+
newParent.children = newParent.children.filter((c) => c !== oldParent);
|
678
701
|
oldParent.parent = null;
|
679
702
|
oldParent.children = [];
|
680
703
|
this.parent = newParent;
|
@@ -746,11 +769,11 @@ export class ImageNode {
|
|
746
769
|
removeChild(child) {
|
747
770
|
this.checkRep();
|
748
771
|
const oldChildCount = this.children.length;
|
749
|
-
this.children = this.children.filter(node => {
|
772
|
+
this.children = this.children.filter((node) => {
|
750
773
|
return node !== child;
|
751
774
|
});
|
752
775
|
console.assert(this.children.length === oldChildCount - 1, `${oldChildCount - 1} ≠ ${this.children.length} after removing all nodes equal to ${child}. Nodes should only be removed once.`);
|
753
|
-
this.children.forEach(child => {
|
776
|
+
this.children.forEach((child) => {
|
754
777
|
child.rebalance();
|
755
778
|
});
|
756
779
|
this.recomputeBBox(true);
|
@@ -799,7 +822,7 @@ export class ImageNode {
|
|
799
822
|
render(renderer, visibleRect) {
|
800
823
|
let leaves;
|
801
824
|
if (visibleRect) {
|
802
|
-
leaves = this.getLeavesIntersectingRegion(visibleRect, rect => renderer.isTooSmallToRender(rect));
|
825
|
+
leaves = this.getLeavesIntersectingRegion(visibleRect, (rect) => renderer.isTooSmallToRender(rect));
|
803
826
|
}
|
804
827
|
else {
|
805
828
|
leaves = this.getLeaves();
|
@@ -909,10 +932,8 @@ export class RootImageNode extends ImageNode {
|
|
909
932
|
};
|
910
933
|
// Check whether the child is stored in the data/fullscreen
|
911
934
|
// component arrays first.
|
912
|
-
this.dataComponents = this.dataComponents
|
913
|
-
|
914
|
-
this.fullscreenChildren = this.fullscreenChildren
|
915
|
-
.filter(checkTargetChild);
|
935
|
+
this.dataComponents = this.dataComponents.filter(checkTargetChild);
|
936
|
+
this.fullscreenChildren = this.fullscreenChildren.filter(checkTargetChild);
|
916
937
|
if (!removed) {
|
917
938
|
super.removeChild(child);
|
918
939
|
}
|