ding-image-editor 3.15.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/README.md +193 -0
- package/dist/svg/icon-a.svg +376 -0
- package/dist/svg/icon-b.svg +369 -0
- package/dist/svg/icon-c.svg +369 -0
- package/dist/svg/icon-d.svg +369 -0
- package/dist/tui-image-editor.css +6 -0
- package/dist/tui-image-editor.js +62329 -0
- package/dist/tui-image-editor.min.css +5 -0
- package/dist/tui-image-editor.min.js +15 -0
- package/index.d.ts +334 -0
- package/package.json +52 -0
- package/src/css/buttons.styl +102 -0
- package/src/css/checkbox.styl +86 -0
- package/src/css/colorpicker.styl +98 -0
- package/src/css/gridtable.styl +45 -0
- package/src/css/icon.styl +44 -0
- package/src/css/index.styl +17 -0
- package/src/css/main.styl +163 -0
- package/src/css/position.styl +309 -0
- package/src/css/range.styl +91 -0
- package/src/css/submenu.styl +168 -0
- package/src/index.js +29 -0
- package/src/js/action.js +686 -0
- package/src/js/command/addIcon.js +42 -0
- package/src/js/command/addImageObject.js +34 -0
- package/src/js/command/addObject.js +43 -0
- package/src/js/command/addShape.js +51 -0
- package/src/js/command/addText.js +73 -0
- package/src/js/command/applyFilter.js +95 -0
- package/src/js/command/changeIconColor.js +48 -0
- package/src/js/command/changeSelection.js +31 -0
- package/src/js/command/changeShape.js +84 -0
- package/src/js/command/changeText.js +44 -0
- package/src/js/command/changeTextStyle.js +80 -0
- package/src/js/command/clearObjects.js +33 -0
- package/src/js/command/flip.js +36 -0
- package/src/js/command/loadImage.js +58 -0
- package/src/js/command/removeFilter.js +38 -0
- package/src/js/command/removeObject.js +37 -0
- package/src/js/command/resize.js +41 -0
- package/src/js/command/resizeCanvasDimension.js +40 -0
- package/src/js/command/rotate.js +64 -0
- package/src/js/command/setObjectPosition.js +50 -0
- package/src/js/command/setObjectProperties.js +55 -0
- package/src/js/component/cropper.js +407 -0
- package/src/js/component/filter.js +229 -0
- package/src/js/component/flip.js +146 -0
- package/src/js/component/freeDrawing.js +144 -0
- package/src/js/component/icon.js +246 -0
- package/src/js/component/imageLoader.js +84 -0
- package/src/js/component/line.js +205 -0
- package/src/js/component/resize.js +103 -0
- package/src/js/component/rotation.js +91 -0
- package/src/js/component/shape.js +601 -0
- package/src/js/component/text.js +572 -0
- package/src/js/component/zoom.js +708 -0
- package/src/js/consts.js +404 -0
- package/src/js/drawingMode/cropper.js +35 -0
- package/src/js/drawingMode/freeDrawing.js +36 -0
- package/src/js/drawingMode/icon.js +35 -0
- package/src/js/drawingMode/lineDrawing.js +36 -0
- package/src/js/drawingMode/resize.js +35 -0
- package/src/js/drawingMode/shape.js +35 -0
- package/src/js/drawingMode/text.js +35 -0
- package/src/js/drawingMode/zoom.js +37 -0
- package/src/js/extension/arrowLine.js +172 -0
- package/src/js/extension/blur.js +29 -0
- package/src/js/extension/colorFilter.js +104 -0
- package/src/js/extension/cropzone.js +568 -0
- package/src/js/extension/emboss.js +29 -0
- package/src/js/extension/mask.js +90 -0
- package/src/js/extension/sharpen.js +29 -0
- package/src/js/factory/command.js +36 -0
- package/src/js/factory/errorMessage.js +27 -0
- package/src/js/graphics.js +1539 -0
- package/src/js/helper/imagetracer.js +1396 -0
- package/src/js/helper/selectionModifyHelper.js +86 -0
- package/src/js/helper/shapeFilterFillHelper.js +564 -0
- package/src/js/helper/shapeResizeHelper.js +237 -0
- package/src/js/imageEditor.js +1795 -0
- package/src/js/interface/command.js +131 -0
- package/src/js/interface/component.js +127 -0
- package/src/js/interface/drawingMode.js +47 -0
- package/src/js/invoker.js +292 -0
- package/src/js/polyfill.js +498 -0
- package/src/js/ui/crop.js +139 -0
- package/src/js/ui/draw.js +187 -0
- package/src/js/ui/filter.js +510 -0
- package/src/js/ui/flip.js +87 -0
- package/src/js/ui/history.js +171 -0
- package/src/js/ui/icon.js +191 -0
- package/src/js/ui/locale/locale.js +19 -0
- package/src/js/ui/mask.js +96 -0
- package/src/js/ui/panelMenu.js +130 -0
- package/src/js/ui/resize.js +241 -0
- package/src/js/ui/rotate.js +123 -0
- package/src/js/ui/shape.js +265 -0
- package/src/js/ui/submenuBase.js +122 -0
- package/src/js/ui/template/controls.js +21 -0
- package/src/js/ui/template/mainContainer.js +38 -0
- package/src/js/ui/template/style.js +146 -0
- package/src/js/ui/template/submenu/crop.js +73 -0
- package/src/js/ui/template/submenu/draw.js +42 -0
- package/src/js/ui/template/submenu/filter.js +157 -0
- package/src/js/ui/template/submenu/flip.js +41 -0
- package/src/js/ui/template/submenu/history.js +22 -0
- package/src/js/ui/template/submenu/icon.js +108 -0
- package/src/js/ui/template/submenu/mask.js +30 -0
- package/src/js/ui/template/submenu/resize.js +54 -0
- package/src/js/ui/template/submenu/rotate.js +32 -0
- package/src/js/ui/template/submenu/shape.js +45 -0
- package/src/js/ui/template/submenu/text.js +67 -0
- package/src/js/ui/template/submenu/zoom.js +41 -0
- package/src/js/ui/text.js +279 -0
- package/src/js/ui/theme/standard.js +220 -0
- package/src/js/ui/theme/theme.js +249 -0
- package/src/js/ui/tools/colorpicker.js +250 -0
- package/src/js/ui/tools/range.js +390 -0
- package/src/js/ui.js +858 -0
- package/src/js/util.js +551 -0
- package/src/svg/default.svg +335 -0
- package/src/svg/icon-a/ic-apply.svg +6 -0
- package/src/svg/icon-a/ic-cancel.svg +6 -0
- package/src/svg/icon-a/ic-color-transparent-w.svg +12 -0
- package/src/svg/icon-a/ic-crop.svg +7 -0
- package/src/svg/icon-a/ic-delete-all.svg +6 -0
- package/src/svg/icon-a/ic-delete.svg +6 -0
- package/src/svg/icon-a/ic-draw-free.svg +5 -0
- package/src/svg/icon-a/ic-draw-line.svg +5 -0
- package/src/svg/icon-a/ic-draw.svg +6 -0
- package/src/svg/icon-a/ic-filter.svg +7 -0
- package/src/svg/icon-a/ic-flip-reset.svg +7 -0
- package/src/svg/icon-a/ic-flip-x.svg +6 -0
- package/src/svg/icon-a/ic-flip-y.svg +6 -0
- package/src/svg/icon-a/ic-flip.svg +6 -0
- package/src/svg/icon-a/ic-history-check.svg +5 -0
- package/src/svg/icon-a/ic-history-crop.svg +7 -0
- package/src/svg/icon-a/ic-history-delete.svg +9 -0
- package/src/svg/icon-a/ic-history-draw.svg +7 -0
- package/src/svg/icon-a/ic-history-filter.svg +8 -0
- package/src/svg/icon-a/ic-history-flip.svg +6 -0
- package/src/svg/icon-a/ic-history-group.svg +9 -0
- package/src/svg/icon-a/ic-history-icon.svg +6 -0
- package/src/svg/icon-a/ic-history-load.svg +7 -0
- package/src/svg/icon-a/ic-history-mask.svg +9 -0
- package/src/svg/icon-a/ic-history-resize.svg +12 -0
- package/src/svg/icon-a/ic-history-rotate.svg +16 -0
- package/src/svg/icon-a/ic-history-shape.svg +7 -0
- package/src/svg/icon-a/ic-history-text.svg +8 -0
- package/src/svg/icon-a/ic-history.svg +6 -0
- package/src/svg/icon-a/ic-icon-arrow-2.svg +5 -0
- package/src/svg/icon-a/ic-icon-arrow-3.svg +5 -0
- package/src/svg/icon-a/ic-icon-arrow.svg +5 -0
- package/src/svg/icon-a/ic-icon-bubble.svg +5 -0
- package/src/svg/icon-a/ic-icon-heart.svg +5 -0
- package/src/svg/icon-a/ic-icon-load.svg +8 -0
- package/src/svg/icon-a/ic-icon-location.svg +8 -0
- package/src/svg/icon-a/ic-icon-polygon.svg +5 -0
- package/src/svg/icon-a/ic-icon-star-2.svg +5 -0
- package/src/svg/icon-a/ic-icon-star.svg +5 -0
- package/src/svg/icon-a/ic-icon.svg +5 -0
- package/src/svg/icon-a/ic-mask-load.svg +8 -0
- package/src/svg/icon-a/ic-mask.svg +6 -0
- package/src/svg/icon-a/ic-redo.svg +7 -0
- package/src/svg/icon-a/ic-reset.svg +7 -0
- package/src/svg/icon-a/ic-resize.svg +13 -0
- package/src/svg/icon-a/ic-rotate-clockwise.svg +7 -0
- package/src/svg/icon-a/ic-rotate-counterclockwise.svg +7 -0
- package/src/svg/icon-a/ic-rotate.svg +7 -0
- package/src/svg/icon-a/ic-shape-circle.svg +5 -0
- package/src/svg/icon-a/ic-shape-rectangle.svg +5 -0
- package/src/svg/icon-a/ic-shape-triangle.svg +5 -0
- package/src/svg/icon-a/ic-shape.svg +6 -0
- package/src/svg/icon-a/ic-text-align-center.svg +6 -0
- package/src/svg/icon-a/ic-text-align-left.svg +6 -0
- package/src/svg/icon-a/ic-text-align-right.svg +6 -0
- package/src/svg/icon-a/ic-text-bold.svg +7 -0
- package/src/svg/icon-a/ic-text-italic.svg +6 -0
- package/src/svg/icon-a/ic-text-underline.svg +7 -0
- package/src/svg/icon-a/ic-text.svg +7 -0
- package/src/svg/icon-a/ic-undo.svg +7 -0
- package/src/svg/icon-a/ic-zoom-hand.svg +8 -0
- package/src/svg/icon-a/ic-zoom-zoom-in.svg +10 -0
- package/src/svg/icon-a/ic-zoom-zoom-out.svg +9 -0
- package/src/svg/icon-a/img-bi.svg +5 -0
- package/src/svg/icon-b/ic-apply.svg +6 -0
- package/src/svg/icon-b/ic-cancel.svg +6 -0
- package/src/svg/icon-b/ic-crop.svg +7 -0
- package/src/svg/icon-b/ic-delete-all.svg +6 -0
- package/src/svg/icon-b/ic-delete.svg +6 -0
- package/src/svg/icon-b/ic-draw-free.svg +5 -0
- package/src/svg/icon-b/ic-draw-line.svg +5 -0
- package/src/svg/icon-b/ic-draw.svg +6 -0
- package/src/svg/icon-b/ic-filter.svg +7 -0
- package/src/svg/icon-b/ic-flip-reset.svg +7 -0
- package/src/svg/icon-b/ic-flip-x.svg +6 -0
- package/src/svg/icon-b/ic-flip-y.svg +6 -0
- package/src/svg/icon-b/ic-flip.svg +6 -0
- package/src/svg/icon-b/ic-history-check.svg +5 -0
- package/src/svg/icon-b/ic-history-crop.svg +7 -0
- package/src/svg/icon-b/ic-history-delete.svg +9 -0
- package/src/svg/icon-b/ic-history-draw.svg +7 -0
- package/src/svg/icon-b/ic-history-filter.svg +8 -0
- package/src/svg/icon-b/ic-history-flip.svg +6 -0
- package/src/svg/icon-b/ic-history-group.svg +9 -0
- package/src/svg/icon-b/ic-history-icon.svg +6 -0
- package/src/svg/icon-b/ic-history-load.svg +7 -0
- package/src/svg/icon-b/ic-history-mask.svg +9 -0
- package/src/svg/icon-b/ic-history-resize.svg +12 -0
- package/src/svg/icon-b/ic-history-rotate.svg +16 -0
- package/src/svg/icon-b/ic-history-shape.svg +7 -0
- package/src/svg/icon-b/ic-history-text.svg +8 -0
- package/src/svg/icon-b/ic-history.svg +6 -0
- package/src/svg/icon-b/ic-icon-arrow-2.svg +5 -0
- package/src/svg/icon-b/ic-icon-arrow-3.svg +5 -0
- package/src/svg/icon-b/ic-icon-arrow.svg +5 -0
- package/src/svg/icon-b/ic-icon-bubble.svg +5 -0
- package/src/svg/icon-b/ic-icon-heart.svg +5 -0
- package/src/svg/icon-b/ic-icon-load.svg +8 -0
- package/src/svg/icon-b/ic-icon-location.svg +8 -0
- package/src/svg/icon-b/ic-icon-polygon.svg +5 -0
- package/src/svg/icon-b/ic-icon-star-2.svg +5 -0
- package/src/svg/icon-b/ic-icon-star.svg +5 -0
- package/src/svg/icon-b/ic-icon.svg +5 -0
- package/src/svg/icon-b/ic-mask-load.svg +8 -0
- package/src/svg/icon-b/ic-mask.svg +6 -0
- package/src/svg/icon-b/ic-redo.svg +7 -0
- package/src/svg/icon-b/ic-reset.svg +7 -0
- package/src/svg/icon-b/ic-resize.svg +13 -0
- package/src/svg/icon-b/ic-rotate-clockwise.svg +7 -0
- package/src/svg/icon-b/ic-rotate-counterclockwise.svg +7 -0
- package/src/svg/icon-b/ic-rotate.svg +7 -0
- package/src/svg/icon-b/ic-shape-circle.svg +5 -0
- package/src/svg/icon-b/ic-shape-rectangle.svg +5 -0
- package/src/svg/icon-b/ic-shape-triangle.svg +5 -0
- package/src/svg/icon-b/ic-shape.svg +6 -0
- package/src/svg/icon-b/ic-text-align-center.svg +6 -0
- package/src/svg/icon-b/ic-text-align-left.svg +6 -0
- package/src/svg/icon-b/ic-text-align-right.svg +6 -0
- package/src/svg/icon-b/ic-text-bold.svg +7 -0
- package/src/svg/icon-b/ic-text-italic.svg +6 -0
- package/src/svg/icon-b/ic-text-underline.svg +7 -0
- package/src/svg/icon-b/ic-text.svg +7 -0
- package/src/svg/icon-b/ic-undo.svg +7 -0
- package/src/svg/icon-b/ic-zoom-hand.svg +8 -0
- package/src/svg/icon-b/ic-zoom-zoom-in.svg +12 -0
- package/src/svg/icon-b/ic-zoom-zoom-out.svg +11 -0
- package/src/svg/icon-b/img-bi.svg +5 -0
- package/src/svg/icon-c/ic-apply.svg +6 -0
- package/src/svg/icon-c/ic-cancel.svg +6 -0
- package/src/svg/icon-c/ic-crop.svg +7 -0
- package/src/svg/icon-c/ic-delete-all.svg +6 -0
- package/src/svg/icon-c/ic-delete.svg +6 -0
- package/src/svg/icon-c/ic-draw-free.svg +5 -0
- package/src/svg/icon-c/ic-draw-line.svg +5 -0
- package/src/svg/icon-c/ic-draw.svg +6 -0
- package/src/svg/icon-c/ic-filter.svg +7 -0
- package/src/svg/icon-c/ic-flip-reset.svg +7 -0
- package/src/svg/icon-c/ic-flip-x.svg +6 -0
- package/src/svg/icon-c/ic-flip-y.svg +6 -0
- package/src/svg/icon-c/ic-flip.svg +6 -0
- package/src/svg/icon-c/ic-history-check.svg +5 -0
- package/src/svg/icon-c/ic-history-crop.svg +7 -0
- package/src/svg/icon-c/ic-history-delete.svg +9 -0
- package/src/svg/icon-c/ic-history-draw.svg +7 -0
- package/src/svg/icon-c/ic-history-filter.svg +8 -0
- package/src/svg/icon-c/ic-history-flip.svg +6 -0
- package/src/svg/icon-c/ic-history-group.svg +9 -0
- package/src/svg/icon-c/ic-history-icon.svg +6 -0
- package/src/svg/icon-c/ic-history-load.svg +7 -0
- package/src/svg/icon-c/ic-history-mask.svg +9 -0
- package/src/svg/icon-c/ic-history-resize.svg +12 -0
- package/src/svg/icon-c/ic-history-rotate.svg +16 -0
- package/src/svg/icon-c/ic-history-shape.svg +7 -0
- package/src/svg/icon-c/ic-history-text.svg +8 -0
- package/src/svg/icon-c/ic-history.svg +6 -0
- package/src/svg/icon-c/ic-icon-arrow-2.svg +5 -0
- package/src/svg/icon-c/ic-icon-arrow-3.svg +5 -0
- package/src/svg/icon-c/ic-icon-arrow.svg +5 -0
- package/src/svg/icon-c/ic-icon-bubble.svg +5 -0
- package/src/svg/icon-c/ic-icon-heart.svg +5 -0
- package/src/svg/icon-c/ic-icon-load.svg +8 -0
- package/src/svg/icon-c/ic-icon-location.svg +8 -0
- package/src/svg/icon-c/ic-icon-polygon.svg +5 -0
- package/src/svg/icon-c/ic-icon-star-2.svg +5 -0
- package/src/svg/icon-c/ic-icon-star.svg +5 -0
- package/src/svg/icon-c/ic-icon.svg +5 -0
- package/src/svg/icon-c/ic-mask-load.svg +8 -0
- package/src/svg/icon-c/ic-mask.svg +6 -0
- package/src/svg/icon-c/ic-redo.svg +7 -0
- package/src/svg/icon-c/ic-reset.svg +7 -0
- package/src/svg/icon-c/ic-resize.svg +13 -0
- package/src/svg/icon-c/ic-rotate-clockwise.svg +7 -0
- package/src/svg/icon-c/ic-rotate-counterclockwise.svg +7 -0
- package/src/svg/icon-c/ic-rotate.svg +7 -0
- package/src/svg/icon-c/ic-shape-circle.svg +5 -0
- package/src/svg/icon-c/ic-shape-rectangle.svg +5 -0
- package/src/svg/icon-c/ic-shape-triangle.svg +5 -0
- package/src/svg/icon-c/ic-shape.svg +6 -0
- package/src/svg/icon-c/ic-text-align-center.svg +6 -0
- package/src/svg/icon-c/ic-text-align-left.svg +6 -0
- package/src/svg/icon-c/ic-text-align-right.svg +6 -0
- package/src/svg/icon-c/ic-text-bold.svg +7 -0
- package/src/svg/icon-c/ic-text-italic.svg +6 -0
- package/src/svg/icon-c/ic-text-underline.svg +7 -0
- package/src/svg/icon-c/ic-text.svg +7 -0
- package/src/svg/icon-c/ic-undo.svg +7 -0
- package/src/svg/icon-c/ic-zoom-hand.svg +8 -0
- package/src/svg/icon-c/ic-zoom-zoom-in.svg +12 -0
- package/src/svg/icon-c/ic-zoom-zoom-out.svg +11 -0
- package/src/svg/icon-c/img-bi.svg +5 -0
- package/src/svg/icon-d/ic-apply.svg +6 -0
- package/src/svg/icon-d/ic-cancel.svg +6 -0
- package/src/svg/icon-d/ic-crop.svg +7 -0
- package/src/svg/icon-d/ic-delete-all.svg +6 -0
- package/src/svg/icon-d/ic-delete.svg +6 -0
- package/src/svg/icon-d/ic-draw-free.svg +5 -0
- package/src/svg/icon-d/ic-draw-line.svg +5 -0
- package/src/svg/icon-d/ic-draw.svg +6 -0
- package/src/svg/icon-d/ic-filter.svg +7 -0
- package/src/svg/icon-d/ic-flip-reset.svg +7 -0
- package/src/svg/icon-d/ic-flip-x.svg +6 -0
- package/src/svg/icon-d/ic-flip-y.svg +6 -0
- package/src/svg/icon-d/ic-flip.svg +6 -0
- package/src/svg/icon-d/ic-history-check.svg +5 -0
- package/src/svg/icon-d/ic-history-crop.svg +7 -0
- package/src/svg/icon-d/ic-history-delete.svg +9 -0
- package/src/svg/icon-d/ic-history-draw.svg +7 -0
- package/src/svg/icon-d/ic-history-filter.svg +8 -0
- package/src/svg/icon-d/ic-history-flip.svg +6 -0
- package/src/svg/icon-d/ic-history-group.svg +9 -0
- package/src/svg/icon-d/ic-history-icon.svg +6 -0
- package/src/svg/icon-d/ic-history-load.svg +7 -0
- package/src/svg/icon-d/ic-history-mask.svg +9 -0
- package/src/svg/icon-d/ic-history-resize.svg +12 -0
- package/src/svg/icon-d/ic-history-rotate.svg +16 -0
- package/src/svg/icon-d/ic-history-shape.svg +7 -0
- package/src/svg/icon-d/ic-history-text.svg +8 -0
- package/src/svg/icon-d/ic-history.svg +6 -0
- package/src/svg/icon-d/ic-icon-arrow-2.svg +5 -0
- package/src/svg/icon-d/ic-icon-arrow-3.svg +5 -0
- package/src/svg/icon-d/ic-icon-arrow.svg +5 -0
- package/src/svg/icon-d/ic-icon-bubble.svg +5 -0
- package/src/svg/icon-d/ic-icon-heart.svg +5 -0
- package/src/svg/icon-d/ic-icon-load.svg +8 -0
- package/src/svg/icon-d/ic-icon-location.svg +8 -0
- package/src/svg/icon-d/ic-icon-polygon.svg +5 -0
- package/src/svg/icon-d/ic-icon-star-2.svg +5 -0
- package/src/svg/icon-d/ic-icon-star.svg +5 -0
- package/src/svg/icon-d/ic-icon.svg +5 -0
- package/src/svg/icon-d/ic-mask-load.svg +8 -0
- package/src/svg/icon-d/ic-mask.svg +6 -0
- package/src/svg/icon-d/ic-redo.svg +7 -0
- package/src/svg/icon-d/ic-reset.svg +7 -0
- package/src/svg/icon-d/ic-resize.svg +13 -0
- package/src/svg/icon-d/ic-rotate-clockwise.svg +7 -0
- package/src/svg/icon-d/ic-rotate-counterclockwise.svg +7 -0
- package/src/svg/icon-d/ic-rotate.svg +7 -0
- package/src/svg/icon-d/ic-shape-circle.svg +5 -0
- package/src/svg/icon-d/ic-shape-rectangle.svg +5 -0
- package/src/svg/icon-d/ic-shape-triangle.svg +5 -0
- package/src/svg/icon-d/ic-shape.svg +6 -0
- package/src/svg/icon-d/ic-text-align-center.svg +6 -0
- package/src/svg/icon-d/ic-text-align-left.svg +6 -0
- package/src/svg/icon-d/ic-text-align-right.svg +6 -0
- package/src/svg/icon-d/ic-text-bold.svg +7 -0
- package/src/svg/icon-d/ic-text-italic.svg +6 -0
- package/src/svg/icon-d/ic-text-underline.svg +7 -0
- package/src/svg/icon-d/ic-text.svg +7 -0
- package/src/svg/icon-d/ic-undo.svg +7 -0
- package/src/svg/icon-d/ic-zoom-hand.svg +8 -0
- package/src/svg/icon-d/ic-zoom-zoom-in.svg +12 -0
- package/src/svg/icon-d/ic-zoom-zoom-out.svg +11 -0
- package/src/svg/icon-d/img-bi.svg +5 -0
@@ -0,0 +1,1539 @@
|
|
1
|
+
import { fabric } from 'fabric';
|
2
|
+
import extend from 'tui-code-snippet/object/extend';
|
3
|
+
import isArray from 'tui-code-snippet/type/isArray';
|
4
|
+
import isString from 'tui-code-snippet/type/isString';
|
5
|
+
import forEachArray from 'tui-code-snippet/collection/forEachArray';
|
6
|
+
import forEachOwnProperties from 'tui-code-snippet/collection/forEachOwnProperties';
|
7
|
+
import CustomEvents from 'tui-code-snippet/customEvents/customEvents';
|
8
|
+
import ImageLoader from '@/component/imageLoader';
|
9
|
+
import Cropper from '@/component/cropper';
|
10
|
+
import Flip from '@/component/flip';
|
11
|
+
import Rotation from '@/component/rotation';
|
12
|
+
import FreeDrawing from '@/component/freeDrawing';
|
13
|
+
import Line from '@/component/line';
|
14
|
+
import Text from '@/component/text';
|
15
|
+
import Icon from '@/component/icon';
|
16
|
+
import Filter from '@/component/filter';
|
17
|
+
import Shape from '@/component/shape';
|
18
|
+
import Zoom from '@/component/zoom';
|
19
|
+
import CropperDrawingMode from '@/drawingMode/cropper';
|
20
|
+
import FreeDrawingMode from '@/drawingMode/freeDrawing';
|
21
|
+
import LineDrawingMode from '@/drawingMode/lineDrawing';
|
22
|
+
import ShapeDrawingMode from '@/drawingMode/shape';
|
23
|
+
import TextDrawingMode from '@/drawingMode/text';
|
24
|
+
import IconDrawingMode from '@/drawingMode/icon';
|
25
|
+
import ZoomDrawingMode from '@/drawingMode/zoom';
|
26
|
+
import {
|
27
|
+
makeSelectionUndoData,
|
28
|
+
makeSelectionUndoDatum,
|
29
|
+
setCachedUndoDataForDimension,
|
30
|
+
} from '@/helper/selectionModifyHelper';
|
31
|
+
import { getProperties, includes, isShape, stamp } from '@/util';
|
32
|
+
import {
|
33
|
+
componentNames as components,
|
34
|
+
eventNames as events,
|
35
|
+
drawingModes,
|
36
|
+
fObjectOptions,
|
37
|
+
} from '@/consts';
|
38
|
+
import Resize from '@/component/resize';
|
39
|
+
import ResizeDrawingMode from '@/drawingMode/resize';
|
40
|
+
|
41
|
+
const DEFAULT_CSS_MAX_WIDTH = 1000;
|
42
|
+
const DEFAULT_CSS_MAX_HEIGHT = 800;
|
43
|
+
const EXTRA_PX_FOR_PASTE = 10;
|
44
|
+
|
45
|
+
const cssOnly = {
|
46
|
+
cssOnly: true,
|
47
|
+
};
|
48
|
+
const backstoreOnly = {
|
49
|
+
backstoreOnly: true,
|
50
|
+
};
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Graphics class
|
54
|
+
* @class
|
55
|
+
* @param {string|HTMLElement} wrapper - Wrapper's element or selector
|
56
|
+
* @param {Object} [option] - Canvas max width & height of css
|
57
|
+
* @param {number} option.cssMaxWidth - Canvas css-max-width
|
58
|
+
* @param {number} option.cssMaxHeight - Canvas css-max-height
|
59
|
+
* @ignore
|
60
|
+
*/
|
61
|
+
class Graphics {
|
62
|
+
constructor(element, { cssMaxWidth, cssMaxHeight } = {}) {
|
63
|
+
/**
|
64
|
+
* Fabric image instance
|
65
|
+
* @type {fabric.Image}
|
66
|
+
*/
|
67
|
+
this.canvasImage = null;
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Max width of canvas elements
|
71
|
+
* @type {number}
|
72
|
+
*/
|
73
|
+
this.cssMaxWidth = cssMaxWidth || DEFAULT_CSS_MAX_WIDTH;
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Max height of canvas elements
|
77
|
+
* @type {number}
|
78
|
+
*/
|
79
|
+
this.cssMaxHeight = cssMaxHeight || DEFAULT_CSS_MAX_HEIGHT;
|
80
|
+
|
81
|
+
/**
|
82
|
+
* cropper Selection Style
|
83
|
+
* @type {Object}
|
84
|
+
*/
|
85
|
+
this.cropSelectionStyle = {};
|
86
|
+
|
87
|
+
/**
|
88
|
+
* target fabric object for copy paste feature
|
89
|
+
* @type {fabric.Object}
|
90
|
+
* @private
|
91
|
+
*/
|
92
|
+
this.targetObjectForCopyPaste = null;
|
93
|
+
|
94
|
+
/**
|
95
|
+
* Image name
|
96
|
+
* @type {string}
|
97
|
+
*/
|
98
|
+
this.imageName = '';
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Object Map
|
102
|
+
* @type {Object}
|
103
|
+
* @private
|
104
|
+
*/
|
105
|
+
this._objects = {};
|
106
|
+
|
107
|
+
/**
|
108
|
+
* Fabric-Canvas instance
|
109
|
+
* @type {fabric.Canvas}
|
110
|
+
* @private
|
111
|
+
*/
|
112
|
+
this._canvas = null;
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Drawing mode
|
116
|
+
* @type {string}
|
117
|
+
* @private
|
118
|
+
*/
|
119
|
+
this._drawingMode = drawingModes.NORMAL;
|
120
|
+
|
121
|
+
/**
|
122
|
+
* DrawingMode map
|
123
|
+
* @type {Object.<string, DrawingMode>}
|
124
|
+
* @private
|
125
|
+
*/
|
126
|
+
this._drawingModeMap = {};
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Component map
|
130
|
+
* @type {Object.<string, Component>}
|
131
|
+
* @private
|
132
|
+
*/
|
133
|
+
this._componentMap = {};
|
134
|
+
|
135
|
+
/**
|
136
|
+
* fabric event handlers
|
137
|
+
* @type {Object.<string, function>}
|
138
|
+
* @private
|
139
|
+
*/
|
140
|
+
this._handler = {
|
141
|
+
onMouseDown: this._onMouseDown.bind(this),
|
142
|
+
onObjectAdded: this._onObjectAdded.bind(this),
|
143
|
+
onObjectRemoved: this._onObjectRemoved.bind(this),
|
144
|
+
onObjectMoved: this._onObjectMoved.bind(this),
|
145
|
+
onObjectScaled: this._onObjectScaled.bind(this),
|
146
|
+
onObjectModified: this._onObjectModified.bind(this),
|
147
|
+
onObjectRotated: this._onObjectRotated.bind(this),
|
148
|
+
onObjectSelected: this._onObjectSelected.bind(this),
|
149
|
+
onPathCreated: this._onPathCreated.bind(this),
|
150
|
+
onSelectionCleared: this._onSelectionCleared.bind(this),
|
151
|
+
onSelectionCreated: this._onSelectionCreated.bind(this),
|
152
|
+
};
|
153
|
+
|
154
|
+
this._setObjectCachingToFalse();
|
155
|
+
this._setCanvasElement(element);
|
156
|
+
this._createDrawingModeInstances();
|
157
|
+
this._createComponents();
|
158
|
+
this._attachCanvasEvents();
|
159
|
+
this._attachZoomEvents();
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* Destroy canvas element
|
164
|
+
*/
|
165
|
+
destroy() {
|
166
|
+
const { wrapperEl } = this._canvas;
|
167
|
+
|
168
|
+
this._canvas.clear();
|
169
|
+
|
170
|
+
wrapperEl.parentNode.removeChild(wrapperEl);
|
171
|
+
|
172
|
+
this._detachZoomEvents();
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Attach zoom events
|
177
|
+
*/
|
178
|
+
_attachZoomEvents() {
|
179
|
+
const zoom = this.getComponent(components.ZOOM);
|
180
|
+
|
181
|
+
zoom.attachKeyboardZoomEvents();
|
182
|
+
}
|
183
|
+
|
184
|
+
/**
|
185
|
+
* Detach zoom events
|
186
|
+
*/
|
187
|
+
_detachZoomEvents() {
|
188
|
+
const zoom = this.getComponent(components.ZOOM);
|
189
|
+
|
190
|
+
zoom.detachKeyboardZoomEvents();
|
191
|
+
}
|
192
|
+
|
193
|
+
/**
|
194
|
+
* Deactivates all objects on canvas
|
195
|
+
* @returns {Graphics} this
|
196
|
+
*/
|
197
|
+
deactivateAll() {
|
198
|
+
this._canvas.discardActiveObject();
|
199
|
+
|
200
|
+
return this;
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Renders all objects on canvas
|
205
|
+
* @returns {Graphics} this
|
206
|
+
*/
|
207
|
+
renderAll() {
|
208
|
+
this._canvas.renderAll();
|
209
|
+
|
210
|
+
return this;
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* Adds objects on canvas
|
215
|
+
* @param {Object|Array} objects - objects
|
216
|
+
*/
|
217
|
+
add(objects) {
|
218
|
+
let theArgs = [];
|
219
|
+
if (isArray(objects)) {
|
220
|
+
theArgs = objects;
|
221
|
+
} else {
|
222
|
+
theArgs.push(objects);
|
223
|
+
}
|
224
|
+
|
225
|
+
this._canvas.add(...theArgs);
|
226
|
+
}
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Removes the object or group
|
230
|
+
* @param {Object} target - graphics object or group
|
231
|
+
* @returns {boolean} true if contains or false
|
232
|
+
*/
|
233
|
+
contains(target) {
|
234
|
+
return this._canvas.contains(target);
|
235
|
+
}
|
236
|
+
|
237
|
+
/**
|
238
|
+
* Gets all objects or group
|
239
|
+
* @returns {Array} all objects, shallow copy
|
240
|
+
*/
|
241
|
+
getObjects() {
|
242
|
+
return this._canvas.getObjects().slice();
|
243
|
+
}
|
244
|
+
|
245
|
+
/**
|
246
|
+
* Get an object by id
|
247
|
+
* @param {number} id - object id
|
248
|
+
* @returns {fabric.Object} object corresponding id
|
249
|
+
*/
|
250
|
+
getObject(id) {
|
251
|
+
return this._objects[id];
|
252
|
+
}
|
253
|
+
|
254
|
+
/**
|
255
|
+
* Removes the object or group
|
256
|
+
* @param {Object} target - graphics object or group
|
257
|
+
*/
|
258
|
+
remove(target) {
|
259
|
+
this._canvas.remove(target);
|
260
|
+
}
|
261
|
+
|
262
|
+
/**
|
263
|
+
* Removes all object or group
|
264
|
+
* @param {boolean} includesBackground - remove the background image or not
|
265
|
+
* @returns {Array} all objects array which is removed
|
266
|
+
*/
|
267
|
+
removeAll(includesBackground) {
|
268
|
+
const canvas = this._canvas;
|
269
|
+
const objects = canvas.getObjects().slice();
|
270
|
+
canvas.remove(...this._canvas.getObjects());
|
271
|
+
|
272
|
+
if (includesBackground) {
|
273
|
+
canvas.clear();
|
274
|
+
}
|
275
|
+
|
276
|
+
return objects;
|
277
|
+
}
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Removes an object or group by id
|
281
|
+
* @param {number} id - object id
|
282
|
+
* @returns {Array} removed objects
|
283
|
+
*/
|
284
|
+
removeObjectById(id) {
|
285
|
+
const objects = [];
|
286
|
+
const canvas = this._canvas;
|
287
|
+
const target = this.getObject(id);
|
288
|
+
const isValidGroup = target && target.isType('group') && !target.isEmpty();
|
289
|
+
|
290
|
+
if (isValidGroup) {
|
291
|
+
canvas.discardActiveObject(); // restore states for each objects
|
292
|
+
target.forEachObject((obj) => {
|
293
|
+
objects.push(obj);
|
294
|
+
canvas.remove(obj);
|
295
|
+
});
|
296
|
+
} else if (canvas.contains(target)) {
|
297
|
+
objects.push(target);
|
298
|
+
canvas.remove(target);
|
299
|
+
}
|
300
|
+
|
301
|
+
return objects;
|
302
|
+
}
|
303
|
+
|
304
|
+
/**
|
305
|
+
* Get an id by object instance
|
306
|
+
* @param {fabric.Object} object object
|
307
|
+
* @returns {number} object id if it exists or null
|
308
|
+
*/
|
309
|
+
getObjectId(object) {
|
310
|
+
let key = null;
|
311
|
+
for (key in this._objects) {
|
312
|
+
if (this._objects.hasOwnProperty(key)) {
|
313
|
+
if (object === this._objects[key]) {
|
314
|
+
return key;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
return null;
|
320
|
+
}
|
321
|
+
|
322
|
+
/**
|
323
|
+
* Gets an active object or group
|
324
|
+
* @returns {Object} active object or group instance
|
325
|
+
*/
|
326
|
+
getActiveObject() {
|
327
|
+
return this._canvas._activeObject;
|
328
|
+
}
|
329
|
+
|
330
|
+
/**
|
331
|
+
* Returns the object ID to delete the object.
|
332
|
+
* @returns {number} object id for remove
|
333
|
+
*/
|
334
|
+
getActiveObjectIdForRemove() {
|
335
|
+
const activeObject = this.getActiveObject();
|
336
|
+
const { type, left, top } = activeObject;
|
337
|
+
const isSelection = type === 'activeSelection';
|
338
|
+
|
339
|
+
if (isSelection) {
|
340
|
+
const group = new fabric.Group([...activeObject.getObjects()], {
|
341
|
+
left,
|
342
|
+
top,
|
343
|
+
});
|
344
|
+
|
345
|
+
return this._addFabricObject(group);
|
346
|
+
}
|
347
|
+
|
348
|
+
return this.getObjectId(activeObject);
|
349
|
+
}
|
350
|
+
|
351
|
+
/**
|
352
|
+
* Verify that you are ready to erase the object.
|
353
|
+
* @returns {boolean} ready for object remove
|
354
|
+
*/
|
355
|
+
isReadyRemoveObject() {
|
356
|
+
const activeObject = this.getActiveObject();
|
357
|
+
|
358
|
+
return activeObject && !activeObject.isEditing;
|
359
|
+
}
|
360
|
+
|
361
|
+
/**
|
362
|
+
* Gets an active group object
|
363
|
+
* @returns {Object} active group object instance
|
364
|
+
*/
|
365
|
+
getActiveObjects() {
|
366
|
+
const activeObject = this._canvas._activeObject;
|
367
|
+
|
368
|
+
return activeObject && activeObject.type === 'activeSelection' ? activeObject : null;
|
369
|
+
}
|
370
|
+
|
371
|
+
/**
|
372
|
+
* Get Active object Selection from object ids
|
373
|
+
* @param {Array.<Object>} objects - fabric objects
|
374
|
+
* @returns {Object} target - target object group
|
375
|
+
*/
|
376
|
+
getActiveSelectionFromObjects(objects) {
|
377
|
+
const canvas = this.getCanvas();
|
378
|
+
|
379
|
+
return new fabric.ActiveSelection(objects, { canvas });
|
380
|
+
}
|
381
|
+
|
382
|
+
/**
|
383
|
+
* Activates an object or group
|
384
|
+
* @param {Object} target - target object or group
|
385
|
+
*/
|
386
|
+
setActiveObject(target) {
|
387
|
+
this._canvas.setActiveObject(target);
|
388
|
+
}
|
389
|
+
|
390
|
+
/**
|
391
|
+
* Set Crop selection style
|
392
|
+
* @param {Object} style - Selection styles
|
393
|
+
*/
|
394
|
+
setCropSelectionStyle(style) {
|
395
|
+
this.cropSelectionStyle = style;
|
396
|
+
}
|
397
|
+
|
398
|
+
/**
|
399
|
+
* Get component
|
400
|
+
* @param {string} name - Component name
|
401
|
+
* @returns {Component}
|
402
|
+
*/
|
403
|
+
getComponent(name) {
|
404
|
+
return this._componentMap[name];
|
405
|
+
}
|
406
|
+
|
407
|
+
/**
|
408
|
+
* Get current drawing mode
|
409
|
+
* @returns {string}
|
410
|
+
*/
|
411
|
+
getDrawingMode() {
|
412
|
+
return this._drawingMode;
|
413
|
+
}
|
414
|
+
|
415
|
+
/**
|
416
|
+
* Start a drawing mode. If the current mode is not 'NORMAL', 'stopDrawingMode()' will be called first.
|
417
|
+
* @param {String} mode Can be one of <I>'CROPPER', 'FREE_DRAWING', 'LINE', 'TEXT', 'SHAPE'</I>
|
418
|
+
* @param {Object} [option] parameters of drawing mode, it's available with 'FREE_DRAWING', 'LINE_DRAWING'
|
419
|
+
* @param {Number} [option.width] brush width
|
420
|
+
* @param {String} [option.color] brush color
|
421
|
+
* @returns {boolean} true if success or false
|
422
|
+
*/
|
423
|
+
startDrawingMode(mode, option) {
|
424
|
+
if (this._isSameDrawingMode(mode)) {
|
425
|
+
return true;
|
426
|
+
}
|
427
|
+
|
428
|
+
// If the current mode is not 'NORMAL', 'stopDrawingMode()' will be called first.
|
429
|
+
this.stopDrawingMode();
|
430
|
+
|
431
|
+
const drawingModeInstance = this._getDrawingModeInstance(mode);
|
432
|
+
if (drawingModeInstance && drawingModeInstance.start) {
|
433
|
+
drawingModeInstance.start(this, option);
|
434
|
+
|
435
|
+
this._drawingMode = mode;
|
436
|
+
}
|
437
|
+
|
438
|
+
return !!drawingModeInstance;
|
439
|
+
}
|
440
|
+
|
441
|
+
/**
|
442
|
+
* Stop the current drawing mode and back to the 'NORMAL' mode
|
443
|
+
*/
|
444
|
+
stopDrawingMode() {
|
445
|
+
if (this._isSameDrawingMode(drawingModes.NORMAL)) {
|
446
|
+
return;
|
447
|
+
}
|
448
|
+
|
449
|
+
const drawingModeInstance = this._getDrawingModeInstance(this.getDrawingMode());
|
450
|
+
if (drawingModeInstance && drawingModeInstance.end) {
|
451
|
+
drawingModeInstance.end(this);
|
452
|
+
}
|
453
|
+
this._drawingMode = drawingModes.NORMAL;
|
454
|
+
}
|
455
|
+
|
456
|
+
/**
|
457
|
+
* Change zoom of canvas
|
458
|
+
* @param {{x: number, y: number}} center - center of zoom
|
459
|
+
* @param {number} zoomLevel - zoom level
|
460
|
+
*/
|
461
|
+
zoom({ x, y }, zoomLevel) {
|
462
|
+
const zoom = this.getComponent(components.ZOOM);
|
463
|
+
|
464
|
+
zoom.zoom({ x, y }, zoomLevel);
|
465
|
+
}
|
466
|
+
|
467
|
+
/**
|
468
|
+
* Get zoom mode
|
469
|
+
* @returns {string}
|
470
|
+
*/
|
471
|
+
getZoomMode() {
|
472
|
+
const zoom = this.getComponent(components.ZOOM);
|
473
|
+
|
474
|
+
return zoom.mode;
|
475
|
+
}
|
476
|
+
|
477
|
+
/**
|
478
|
+
* Start zoom-in mode
|
479
|
+
*/
|
480
|
+
startZoomInMode() {
|
481
|
+
const zoom = this.getComponent(components.ZOOM);
|
482
|
+
|
483
|
+
zoom.startZoomInMode();
|
484
|
+
}
|
485
|
+
|
486
|
+
/**
|
487
|
+
* Stop zoom-in mode
|
488
|
+
*/
|
489
|
+
endZoomInMode() {
|
490
|
+
const zoom = this.getComponent(components.ZOOM);
|
491
|
+
|
492
|
+
zoom.endZoomInMode();
|
493
|
+
}
|
494
|
+
|
495
|
+
/**
|
496
|
+
* Zoom out one step
|
497
|
+
*/
|
498
|
+
zoomOut() {
|
499
|
+
const zoom = this.getComponent(components.ZOOM);
|
500
|
+
|
501
|
+
zoom.zoomOut();
|
502
|
+
}
|
503
|
+
|
504
|
+
/**
|
505
|
+
* Start hand mode
|
506
|
+
*/
|
507
|
+
startHandMode() {
|
508
|
+
const zoom = this.getComponent(components.ZOOM);
|
509
|
+
|
510
|
+
zoom.startHandMode();
|
511
|
+
}
|
512
|
+
|
513
|
+
/**
|
514
|
+
* Stop hand mode
|
515
|
+
*/
|
516
|
+
endHandMode() {
|
517
|
+
const zoom = this.getComponent(components.ZOOM);
|
518
|
+
|
519
|
+
zoom.endHandMode();
|
520
|
+
}
|
521
|
+
|
522
|
+
/**
|
523
|
+
* Zoom reset
|
524
|
+
*/
|
525
|
+
resetZoom() {
|
526
|
+
const zoom = this.getComponent(components.ZOOM);
|
527
|
+
|
528
|
+
zoom.resetZoom();
|
529
|
+
}
|
530
|
+
|
531
|
+
/**
|
532
|
+
* To data url from canvas
|
533
|
+
* @param {Object} options - options for toDataURL
|
534
|
+
* @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
|
535
|
+
* @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
|
536
|
+
* @param {Number} [options.multiplier=1] Multiplier to scale by
|
537
|
+
* @param {Number} [options.left] Cropping left offset. Introduced in fabric v1.2.14
|
538
|
+
* @param {Number} [options.top] Cropping top offset. Introduced in fabric v1.2.14
|
539
|
+
* @param {Number} [options.width] Cropping width. Introduced in fabric v1.2.14
|
540
|
+
* @param {Number} [options.height] Cropping height. Introduced in fabric v1.2.14
|
541
|
+
* @returns {string} A DOMString containing the requested data URI.
|
542
|
+
*/
|
543
|
+
toDataURL(options) {
|
544
|
+
const cropper = this.getComponent(components.CROPPER);
|
545
|
+
cropper.changeVisibility(false);
|
546
|
+
|
547
|
+
const dataUrl = this._canvas && this._canvas.toDataURL(options);
|
548
|
+
cropper.changeVisibility(true);
|
549
|
+
|
550
|
+
return dataUrl;
|
551
|
+
}
|
552
|
+
|
553
|
+
/**
|
554
|
+
* Save image(background) of canvas
|
555
|
+
* @param {string} name - Name of image
|
556
|
+
* @param {?fabric.Image} canvasImage - Fabric image instance
|
557
|
+
*/
|
558
|
+
setCanvasImage(name, canvasImage) {
|
559
|
+
if (canvasImage) {
|
560
|
+
stamp(canvasImage);
|
561
|
+
}
|
562
|
+
this.imageName = name;
|
563
|
+
this.canvasImage = canvasImage;
|
564
|
+
}
|
565
|
+
|
566
|
+
/**
|
567
|
+
* Set css max dimension
|
568
|
+
* @param {{width: number, height: number}} maxDimension - Max width & Max height
|
569
|
+
*/
|
570
|
+
setCssMaxDimension(maxDimension) {
|
571
|
+
this.cssMaxWidth = maxDimension.width || this.cssMaxWidth;
|
572
|
+
this.cssMaxHeight = maxDimension.height || this.cssMaxHeight;
|
573
|
+
}
|
574
|
+
|
575
|
+
/**
|
576
|
+
* Adjust canvas dimension with scaling image
|
577
|
+
*/
|
578
|
+
adjustCanvasDimension() {
|
579
|
+
this.adjustCanvasDimensionBase(this.canvasImage.scale(1));
|
580
|
+
}
|
581
|
+
|
582
|
+
adjustCanvasDimensionBase(canvasImage = null) {
|
583
|
+
if (!canvasImage) {
|
584
|
+
canvasImage = this.canvasImage;
|
585
|
+
}
|
586
|
+
|
587
|
+
const { width, height } = canvasImage.getBoundingRect();
|
588
|
+
const maxDimension = this._calcMaxDimension(width, height);
|
589
|
+
|
590
|
+
this.setCanvasCssDimension({
|
591
|
+
width: '100%',
|
592
|
+
height: '100%', // Set height '' for IE9
|
593
|
+
'max-width': `${maxDimension.width}px`,
|
594
|
+
'max-height': `${maxDimension.height}px`,
|
595
|
+
});
|
596
|
+
|
597
|
+
this.setCanvasBackstoreDimension({
|
598
|
+
width,
|
599
|
+
height,
|
600
|
+
});
|
601
|
+
this._canvas.centerObject(canvasImage);
|
602
|
+
}
|
603
|
+
|
604
|
+
/**
|
605
|
+
* Set canvas dimension - css only
|
606
|
+
* {@link http://fabricjs.com/docs/fabric.Canvas.html#setDimensions}
|
607
|
+
* @param {Object} dimension - Canvas css dimension
|
608
|
+
*/
|
609
|
+
setCanvasCssDimension(dimension) {
|
610
|
+
this._canvas.setDimensions(dimension, cssOnly);
|
611
|
+
}
|
612
|
+
|
613
|
+
/**
|
614
|
+
* Set canvas dimension - backstore only
|
615
|
+
* {@link http://fabricjs.com/docs/fabric.Canvas.html#setDimensions}
|
616
|
+
* @param {Object} dimension - Canvas backstore dimension
|
617
|
+
*/
|
618
|
+
setCanvasBackstoreDimension(dimension) {
|
619
|
+
this._canvas.setDimensions(dimension, backstoreOnly);
|
620
|
+
}
|
621
|
+
|
622
|
+
/**
|
623
|
+
* Set image properties
|
624
|
+
* {@link http://fabricjs.com/docs/fabric.Image.html#set}
|
625
|
+
* @param {Object} setting - Image properties
|
626
|
+
* @param {boolean} [withRendering] - If true, The changed image will be reflected in the canvas
|
627
|
+
*/
|
628
|
+
setImageProperties(setting, withRendering) {
|
629
|
+
const { canvasImage } = this;
|
630
|
+
|
631
|
+
if (!canvasImage) {
|
632
|
+
return;
|
633
|
+
}
|
634
|
+
|
635
|
+
canvasImage.set(setting).setCoords();
|
636
|
+
if (withRendering) {
|
637
|
+
this._canvas.renderAll();
|
638
|
+
}
|
639
|
+
}
|
640
|
+
|
641
|
+
/**
|
642
|
+
* Returns canvas element of fabric.Canvas[[lower-canvas]]
|
643
|
+
* @returns {HTMLCanvasElement}
|
644
|
+
*/
|
645
|
+
getCanvasElement() {
|
646
|
+
return this._canvas.getElement();
|
647
|
+
}
|
648
|
+
|
649
|
+
/**
|
650
|
+
* Get fabric.Canvas instance
|
651
|
+
* @returns {fabric.Canvas}
|
652
|
+
*/
|
653
|
+
getCanvas() {
|
654
|
+
return this._canvas;
|
655
|
+
}
|
656
|
+
|
657
|
+
/**
|
658
|
+
* Get canvasImage (fabric.Image instance)
|
659
|
+
* @returns {fabric.Image}
|
660
|
+
*/
|
661
|
+
getCanvasImage() {
|
662
|
+
return this.canvasImage;
|
663
|
+
}
|
664
|
+
|
665
|
+
/**
|
666
|
+
* Get image name
|
667
|
+
* @returns {string}
|
668
|
+
*/
|
669
|
+
getImageName() {
|
670
|
+
return this.imageName;
|
671
|
+
}
|
672
|
+
|
673
|
+
/**
|
674
|
+
* Add image object on canvas
|
675
|
+
* @param {string} imgUrl - Image url to make object
|
676
|
+
* @returns {Promise}
|
677
|
+
*/
|
678
|
+
addImageObject(imgUrl) {
|
679
|
+
const callback = this._callbackAfterLoadingImageObject.bind(this);
|
680
|
+
|
681
|
+
return new Promise((resolve) => {
|
682
|
+
fabric.Image.fromURL(
|
683
|
+
imgUrl,
|
684
|
+
(image) => {
|
685
|
+
callback(image);
|
686
|
+
resolve(this.createObjectProperties(image));
|
687
|
+
},
|
688
|
+
{
|
689
|
+
crossOrigin: 'Anonymous',
|
690
|
+
}
|
691
|
+
);
|
692
|
+
});
|
693
|
+
}
|
694
|
+
|
695
|
+
/**
|
696
|
+
* Get center position of canvas
|
697
|
+
* @returns {Object} {left, top}
|
698
|
+
*/
|
699
|
+
getCenter() {
|
700
|
+
return this._canvas.getCenter();
|
701
|
+
}
|
702
|
+
|
703
|
+
/**
|
704
|
+
* Get cropped rect
|
705
|
+
* @returns {Object} rect
|
706
|
+
*/
|
707
|
+
getCropzoneRect() {
|
708
|
+
return this.getComponent(components.CROPPER).getCropzoneRect();
|
709
|
+
}
|
710
|
+
|
711
|
+
/**
|
712
|
+
* Get cropped rect
|
713
|
+
* @param {number} [mode] cropzone rect mode
|
714
|
+
*/
|
715
|
+
setCropzoneRect(mode) {
|
716
|
+
this.getComponent(components.CROPPER).setCropzoneRect(mode);
|
717
|
+
}
|
718
|
+
|
719
|
+
/**
|
720
|
+
* Get cropped image data
|
721
|
+
* @param {Object} cropRect cropzone rect
|
722
|
+
* @param {Number} cropRect.left left position
|
723
|
+
* @param {Number} cropRect.top top position
|
724
|
+
* @param {Number} cropRect.width width
|
725
|
+
* @param {Number} cropRect.height height
|
726
|
+
* @returns {?{imageName: string, url: string}} cropped Image data
|
727
|
+
*/
|
728
|
+
getCroppedImageData(cropRect) {
|
729
|
+
return this.getComponent(components.CROPPER).getCroppedImageData(cropRect);
|
730
|
+
}
|
731
|
+
|
732
|
+
/**
|
733
|
+
* Set brush option
|
734
|
+
* @param {Object} option brush option
|
735
|
+
* @param {Number} option.width width
|
736
|
+
* @param {String} option.color color like 'FFFFFF', 'rgba(0, 0, 0, 0.5)'
|
737
|
+
*/
|
738
|
+
setBrush(option) {
|
739
|
+
const drawingMode = this._drawingMode;
|
740
|
+
let compName = components.FREE_DRAWING;
|
741
|
+
|
742
|
+
if (drawingMode === drawingModes.LINE_DRAWING) {
|
743
|
+
compName = components.LINE;
|
744
|
+
}
|
745
|
+
|
746
|
+
this.getComponent(compName).setBrush(option);
|
747
|
+
}
|
748
|
+
|
749
|
+
/**
|
750
|
+
* Set states of current drawing shape
|
751
|
+
* @param {string} type - Shape type (ex: 'rect', 'circle', 'triangle')
|
752
|
+
* @param {Object} [options] - Shape options
|
753
|
+
* @param {(ShapeFillOption | string)} [options.fill] - {@link ShapeFillOption} or
|
754
|
+
* Shape foreground color (ex: '#fff', 'transparent')
|
755
|
+
* @param {string} [options.stoke] - Shape outline color
|
756
|
+
* @param {number} [options.strokeWidth] - Shape outline width
|
757
|
+
* @param {number} [options.width] - Width value (When type option is 'rect', this options can use)
|
758
|
+
* @param {number} [options.height] - Height value (When type option is 'rect', this options can use)
|
759
|
+
* @param {number} [options.rx] - Radius x value (When type option is 'circle', this options can use)
|
760
|
+
* @param {number} [options.ry] - Radius y value (When type option is 'circle', this options can use)
|
761
|
+
* @param {number} [options.isRegular] - Whether resizing shape has 1:1 ratio or not
|
762
|
+
*/
|
763
|
+
setDrawingShape(type, options) {
|
764
|
+
this.getComponent(components.SHAPE).setStates(type, options);
|
765
|
+
}
|
766
|
+
|
767
|
+
/**
|
768
|
+
* Set style of current drawing icon
|
769
|
+
* @param {string} type - icon type (ex: 'icon-arrow', 'icon-star')
|
770
|
+
* @param {Object} [iconColor] - Icon color
|
771
|
+
*/
|
772
|
+
setIconStyle(type, iconColor) {
|
773
|
+
this.getComponent(components.ICON).setStates(type, iconColor);
|
774
|
+
}
|
775
|
+
|
776
|
+
/**
|
777
|
+
* Register icon paths
|
778
|
+
* @param {Object} pathInfos - Path infos
|
779
|
+
* @param {string} pathInfos.key - key
|
780
|
+
* @param {string} pathInfos.value - value
|
781
|
+
*/
|
782
|
+
registerPaths(pathInfos) {
|
783
|
+
this.getComponent(components.ICON).registerPaths(pathInfos);
|
784
|
+
}
|
785
|
+
|
786
|
+
/**
|
787
|
+
* Change cursor style
|
788
|
+
* @param {string} cursorType - cursor type
|
789
|
+
*/
|
790
|
+
changeCursor(cursorType) {
|
791
|
+
const canvas = this.getCanvas();
|
792
|
+
canvas.defaultCursor = cursorType;
|
793
|
+
canvas.renderAll();
|
794
|
+
}
|
795
|
+
|
796
|
+
/**
|
797
|
+
* Whether it has the filter or not
|
798
|
+
* @param {string} type - Filter type
|
799
|
+
* @returns {boolean} true if it has the filter
|
800
|
+
*/
|
801
|
+
hasFilter(type) {
|
802
|
+
return this.getComponent(components.FILTER).hasFilter(type);
|
803
|
+
}
|
804
|
+
|
805
|
+
/**
|
806
|
+
* Set selection style of fabric object by init option
|
807
|
+
* @param {Object} styles - Selection styles
|
808
|
+
*/
|
809
|
+
setSelectionStyle(styles) {
|
810
|
+
extend(fObjectOptions.SELECTION_STYLE, styles);
|
811
|
+
}
|
812
|
+
|
813
|
+
/**
|
814
|
+
* Set object properties
|
815
|
+
* @param {number} id - object id
|
816
|
+
* @param {Object} props - props
|
817
|
+
* @param {string} [props.fill] Color
|
818
|
+
* @param {string} [props.fontFamily] Font type for text
|
819
|
+
* @param {number} [props.fontSize] Size
|
820
|
+
* @param {string} [props.fontStyle] Type of inclination (normal / italic)
|
821
|
+
* @param {string} [props.fontWeight] Type of thicker or thinner looking (normal / bold)
|
822
|
+
* @param {string} [props.textAlign] Type of text align (left / center / right)
|
823
|
+
* @param {string} [props.textDecoration] Type of line (underline / line-through / overline)
|
824
|
+
* @returns {Object} applied properties
|
825
|
+
*/
|
826
|
+
setObjectProperties(id, props) {
|
827
|
+
const object = this.getObject(id);
|
828
|
+
const clone = extend({}, props);
|
829
|
+
|
830
|
+
object.set(clone);
|
831
|
+
|
832
|
+
object.setCoords();
|
833
|
+
|
834
|
+
this.getCanvas().renderAll();
|
835
|
+
|
836
|
+
return clone;
|
837
|
+
}
|
838
|
+
|
839
|
+
/**
|
840
|
+
* Get object properties corresponding key
|
841
|
+
* @param {number} id - object id
|
842
|
+
* @param {Array<string>|ObjectProps|string} keys - property's key
|
843
|
+
* @returns {Object} properties
|
844
|
+
*/
|
845
|
+
getObjectProperties(id, keys) {
|
846
|
+
const object = this.getObject(id);
|
847
|
+
const props = {};
|
848
|
+
|
849
|
+
if (isString(keys)) {
|
850
|
+
props[keys] = object[keys];
|
851
|
+
} else if (isArray(keys)) {
|
852
|
+
forEachArray(keys, (value) => {
|
853
|
+
props[value] = object[value];
|
854
|
+
});
|
855
|
+
} else {
|
856
|
+
forEachOwnProperties(keys, (value, key) => {
|
857
|
+
props[key] = object[key];
|
858
|
+
});
|
859
|
+
}
|
860
|
+
|
861
|
+
return props;
|
862
|
+
}
|
863
|
+
|
864
|
+
/**
|
865
|
+
* Get object position by originX, originY
|
866
|
+
* @param {number} id - object id
|
867
|
+
* @param {string} originX - can be 'left', 'center', 'right'
|
868
|
+
* @param {string} originY - can be 'top', 'center', 'bottom'
|
869
|
+
* @returns {Object} {{x:number, y: number}} position by origin if id is valid, or null
|
870
|
+
*/
|
871
|
+
getObjectPosition(id, originX, originY) {
|
872
|
+
const targetObj = this.getObject(id);
|
873
|
+
if (!targetObj) {
|
874
|
+
return null;
|
875
|
+
}
|
876
|
+
|
877
|
+
return targetObj.getPointByOrigin(originX, originY);
|
878
|
+
}
|
879
|
+
|
880
|
+
/**
|
881
|
+
* Set object position by originX, originY
|
882
|
+
* @param {number} id - object id
|
883
|
+
* @param {Object} posInfo - position object
|
884
|
+
* @param {number} posInfo.x - x position
|
885
|
+
* @param {number} posInfo.y - y position
|
886
|
+
* @param {string} posInfo.originX - can be 'left', 'center', 'right'
|
887
|
+
* @param {string} posInfo.originY - can be 'top', 'center', 'bottom'
|
888
|
+
* @returns {boolean} true if target id is valid or false
|
889
|
+
*/
|
890
|
+
setObjectPosition(id, posInfo) {
|
891
|
+
const targetObj = this.getObject(id);
|
892
|
+
const { x, y, originX, originY } = posInfo;
|
893
|
+
if (!targetObj) {
|
894
|
+
return false;
|
895
|
+
}
|
896
|
+
|
897
|
+
const targetOrigin = targetObj.getPointByOrigin(originX, originY);
|
898
|
+
const centerOrigin = targetObj.getPointByOrigin('center', 'center');
|
899
|
+
const diffX = centerOrigin.x - targetOrigin.x;
|
900
|
+
const diffY = centerOrigin.y - targetOrigin.y;
|
901
|
+
|
902
|
+
targetObj.set({
|
903
|
+
left: x + diffX,
|
904
|
+
top: y + diffY,
|
905
|
+
});
|
906
|
+
|
907
|
+
targetObj.setCoords();
|
908
|
+
|
909
|
+
return true;
|
910
|
+
}
|
911
|
+
|
912
|
+
/**
|
913
|
+
* Get the canvas size
|
914
|
+
* @returns {Object} {{width: number, height: number}} image size
|
915
|
+
*/
|
916
|
+
getCanvasSize() {
|
917
|
+
const image = this.getCanvasImage();
|
918
|
+
|
919
|
+
return {
|
920
|
+
width: image ? image.width : 0,
|
921
|
+
height: image ? image.height : 0,
|
922
|
+
};
|
923
|
+
}
|
924
|
+
|
925
|
+
/**
|
926
|
+
* Create fabric static canvas
|
927
|
+
* @returns {Object} {{width: number, height: number}} image size
|
928
|
+
*/
|
929
|
+
createStaticCanvas() {
|
930
|
+
const staticCanvas = new fabric.StaticCanvas();
|
931
|
+
|
932
|
+
staticCanvas.set({
|
933
|
+
enableRetinaScaling: false,
|
934
|
+
});
|
935
|
+
|
936
|
+
return staticCanvas;
|
937
|
+
}
|
938
|
+
|
939
|
+
/**
|
940
|
+
* Get a DrawingMode instance
|
941
|
+
* @param {string} modeName - DrawingMode Class Name
|
942
|
+
* @returns {DrawingMode} DrawingMode instance
|
943
|
+
* @private
|
944
|
+
*/
|
945
|
+
_getDrawingModeInstance(modeName) {
|
946
|
+
return this._drawingModeMap[modeName];
|
947
|
+
}
|
948
|
+
|
949
|
+
/**
|
950
|
+
* Set object caching to false. This brought many bugs when draw Shape & cropzone
|
951
|
+
* @see http://fabricjs.com/fabric-object-caching
|
952
|
+
* @private
|
953
|
+
*/
|
954
|
+
_setObjectCachingToFalse() {
|
955
|
+
fabric.Object.prototype.objectCaching = false;
|
956
|
+
}
|
957
|
+
|
958
|
+
/**
|
959
|
+
* Set canvas element to fabric.Canvas
|
960
|
+
* @param {Element|string} element - Wrapper or canvas element or selector
|
961
|
+
* @private
|
962
|
+
*/
|
963
|
+
_setCanvasElement(element) {
|
964
|
+
let selectedElement;
|
965
|
+
let canvasElement;
|
966
|
+
|
967
|
+
if (element.nodeType) {
|
968
|
+
selectedElement = element;
|
969
|
+
} else {
|
970
|
+
selectedElement = document.querySelector(element);
|
971
|
+
}
|
972
|
+
|
973
|
+
if (selectedElement.nodeName.toUpperCase() !== 'CANVAS') {
|
974
|
+
canvasElement = document.createElement('canvas');
|
975
|
+
selectedElement.appendChild(canvasElement);
|
976
|
+
}
|
977
|
+
|
978
|
+
this._canvas = new fabric.Canvas(canvasElement, {
|
979
|
+
containerClass: 'tui-image-editor-canvas-container',
|
980
|
+
enableRetinaScaling: false,
|
981
|
+
});
|
982
|
+
}
|
983
|
+
|
984
|
+
/**
|
985
|
+
* Creates DrawingMode instances
|
986
|
+
* @private
|
987
|
+
*/
|
988
|
+
_createDrawingModeInstances() {
|
989
|
+
this._register(this._drawingModeMap, new CropperDrawingMode());
|
990
|
+
this._register(this._drawingModeMap, new FreeDrawingMode());
|
991
|
+
this._register(this._drawingModeMap, new LineDrawingMode());
|
992
|
+
this._register(this._drawingModeMap, new ShapeDrawingMode());
|
993
|
+
this._register(this._drawingModeMap, new TextDrawingMode());
|
994
|
+
this._register(this._drawingModeMap, new IconDrawingMode());
|
995
|
+
this._register(this._drawingModeMap, new ZoomDrawingMode());
|
996
|
+
this._register(this._drawingModeMap, new ResizeDrawingMode());
|
997
|
+
}
|
998
|
+
|
999
|
+
/**
|
1000
|
+
* Create components
|
1001
|
+
* @private
|
1002
|
+
*/
|
1003
|
+
_createComponents() {
|
1004
|
+
this._register(this._componentMap, new ImageLoader(this));
|
1005
|
+
this._register(this._componentMap, new Cropper(this));
|
1006
|
+
this._register(this._componentMap, new Flip(this));
|
1007
|
+
this._register(this._componentMap, new Rotation(this));
|
1008
|
+
this._register(this._componentMap, new FreeDrawing(this));
|
1009
|
+
this._register(this._componentMap, new Line(this));
|
1010
|
+
this._register(this._componentMap, new Text(this));
|
1011
|
+
this._register(this._componentMap, new Icon(this));
|
1012
|
+
this._register(this._componentMap, new Filter(this));
|
1013
|
+
this._register(this._componentMap, new Shape(this));
|
1014
|
+
this._register(this._componentMap, new Zoom(this));
|
1015
|
+
this._register(this._componentMap, new Resize(this));
|
1016
|
+
}
|
1017
|
+
|
1018
|
+
/**
|
1019
|
+
* Register component
|
1020
|
+
* @param {Object} map - map object
|
1021
|
+
* @param {Object} module - module which has getName method
|
1022
|
+
* @private
|
1023
|
+
*/
|
1024
|
+
_register(map, module) {
|
1025
|
+
map[module.getName()] = module;
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
/**
|
1029
|
+
* Get the current drawing mode is same with given mode
|
1030
|
+
* @param {string} mode drawing mode
|
1031
|
+
* @returns {boolean} true if same or false
|
1032
|
+
*/
|
1033
|
+
_isSameDrawingMode(mode) {
|
1034
|
+
return this.getDrawingMode() === mode;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
/**
|
1038
|
+
* Calculate max dimension of canvas
|
1039
|
+
* The css-max dimension is dynamically decided with maintaining image ratio
|
1040
|
+
* The css-max dimension is lower than canvas dimension (attribute of canvas, not css)
|
1041
|
+
* @param {number} width - Canvas width
|
1042
|
+
* @param {number} height - Canvas height
|
1043
|
+
* @returns {{width: number, height: number}} - Max width & Max height
|
1044
|
+
* @private
|
1045
|
+
*/
|
1046
|
+
_calcMaxDimension(width, height) {
|
1047
|
+
const wScaleFactor = this.cssMaxWidth / width;
|
1048
|
+
const hScaleFactor = this.cssMaxHeight / height;
|
1049
|
+
let cssMaxWidth = Math.min(width, this.cssMaxWidth);
|
1050
|
+
let cssMaxHeight = Math.min(height, this.cssMaxHeight);
|
1051
|
+
|
1052
|
+
if (wScaleFactor < 1 && wScaleFactor < hScaleFactor) {
|
1053
|
+
cssMaxWidth = width * wScaleFactor;
|
1054
|
+
cssMaxHeight = height * wScaleFactor;
|
1055
|
+
} else if (hScaleFactor < 1 && hScaleFactor < wScaleFactor) {
|
1056
|
+
cssMaxWidth = width * hScaleFactor;
|
1057
|
+
cssMaxHeight = height * hScaleFactor;
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
return {
|
1061
|
+
width: Math.floor(cssMaxWidth),
|
1062
|
+
height: Math.floor(cssMaxHeight),
|
1063
|
+
};
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
/**
|
1067
|
+
* Callback function after loading image
|
1068
|
+
* @param {fabric.Image} obj - Fabric image object
|
1069
|
+
* @private
|
1070
|
+
*/
|
1071
|
+
_callbackAfterLoadingImageObject(obj) {
|
1072
|
+
const centerPos = this.getCanvasImage().getCenterPoint();
|
1073
|
+
|
1074
|
+
obj.set(fObjectOptions.SELECTION_STYLE);
|
1075
|
+
obj.set({
|
1076
|
+
left: centerPos.x,
|
1077
|
+
top: centerPos.y,
|
1078
|
+
crossOrigin: 'Anonymous',
|
1079
|
+
});
|
1080
|
+
|
1081
|
+
this.getCanvas().add(obj).setActiveObject(obj);
|
1082
|
+
}
|
1083
|
+
|
1084
|
+
/**
|
1085
|
+
* Attach canvas's events
|
1086
|
+
*/
|
1087
|
+
_attachCanvasEvents() {
|
1088
|
+
const canvas = this._canvas;
|
1089
|
+
const handler = this._handler;
|
1090
|
+
canvas.on({
|
1091
|
+
'mouse:down': handler.onMouseDown,
|
1092
|
+
'object:added': handler.onObjectAdded,
|
1093
|
+
'object:removed': handler.onObjectRemoved,
|
1094
|
+
'object:moving': handler.onObjectMoved,
|
1095
|
+
'object:scaling': handler.onObjectScaled,
|
1096
|
+
'object:modified': handler.onObjectModified,
|
1097
|
+
'object:rotating': handler.onObjectRotated,
|
1098
|
+
'path:created': handler.onPathCreated,
|
1099
|
+
'selection:cleared': handler.onSelectionCleared,
|
1100
|
+
'selection:created': handler.onSelectionCreated,
|
1101
|
+
'selection:updated': handler.onObjectSelected,
|
1102
|
+
});
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
/**
|
1106
|
+
* "mouse:down" canvas event handler
|
1107
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1108
|
+
* @private
|
1109
|
+
*/
|
1110
|
+
_onMouseDown(fEvent) {
|
1111
|
+
const { e: event, target } = fEvent;
|
1112
|
+
const originPointer = this._canvas.getPointer(event);
|
1113
|
+
|
1114
|
+
if (target) {
|
1115
|
+
const { type } = target;
|
1116
|
+
const undoData = makeSelectionUndoData(target, (item) =>
|
1117
|
+
makeSelectionUndoDatum(this.getObjectId(item), item, type === 'activeSelection')
|
1118
|
+
);
|
1119
|
+
|
1120
|
+
setCachedUndoDataForDimension(undoData);
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
this.fire(events.MOUSE_DOWN, event, originPointer);
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
/**
|
1127
|
+
* "object:added" canvas event handler
|
1128
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1129
|
+
* @private
|
1130
|
+
*/
|
1131
|
+
_onObjectAdded(fEvent) {
|
1132
|
+
const obj = fEvent.target;
|
1133
|
+
if (obj.isType('cropzone')) {
|
1134
|
+
return;
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
this._addFabricObject(obj);
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
/**
|
1141
|
+
* "object:removed" canvas event handler
|
1142
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1143
|
+
* @private
|
1144
|
+
*/
|
1145
|
+
_onObjectRemoved(fEvent) {
|
1146
|
+
const obj = fEvent.target;
|
1147
|
+
|
1148
|
+
this._removeFabricObject(stamp(obj));
|
1149
|
+
}
|
1150
|
+
|
1151
|
+
/**
|
1152
|
+
* "object:moving" canvas event handler
|
1153
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1154
|
+
* @private
|
1155
|
+
*/
|
1156
|
+
_onObjectMoved(fEvent) {
|
1157
|
+
this._lazyFire(
|
1158
|
+
events.OBJECT_MOVED,
|
1159
|
+
(object) => this.createObjectProperties(object),
|
1160
|
+
fEvent.target
|
1161
|
+
);
|
1162
|
+
}
|
1163
|
+
|
1164
|
+
/**
|
1165
|
+
* "object:scaling" canvas event handler
|
1166
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1167
|
+
* @private
|
1168
|
+
*/
|
1169
|
+
_onObjectScaled(fEvent) {
|
1170
|
+
this._lazyFire(
|
1171
|
+
events.OBJECT_SCALED,
|
1172
|
+
(object) => this.createObjectProperties(object),
|
1173
|
+
fEvent.target
|
1174
|
+
);
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
/**
|
1178
|
+
* "object:modified" canvas event handler
|
1179
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1180
|
+
* @private
|
1181
|
+
*/
|
1182
|
+
_onObjectModified(fEvent) {
|
1183
|
+
const { target } = fEvent;
|
1184
|
+
if (target.type === 'activeSelection') {
|
1185
|
+
const items = target.getObjects();
|
1186
|
+
|
1187
|
+
items.forEach((item) => item.fire('modifiedInGroup', target));
|
1188
|
+
}
|
1189
|
+
|
1190
|
+
this.fire(events.OBJECT_MODIFIED, target, this.getObjectId(target));
|
1191
|
+
}
|
1192
|
+
|
1193
|
+
/**
|
1194
|
+
* "object:rotating" canvas event handler
|
1195
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1196
|
+
* @private
|
1197
|
+
*/
|
1198
|
+
_onObjectRotated(fEvent) {
|
1199
|
+
this._lazyFire(
|
1200
|
+
events.OBJECT_ROTATED,
|
1201
|
+
(object) => this.createObjectProperties(object),
|
1202
|
+
fEvent.target
|
1203
|
+
);
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
/**
|
1207
|
+
* Lazy event emitter
|
1208
|
+
* @param {string} eventName - event name
|
1209
|
+
* @param {Function} paramsMaker - make param function
|
1210
|
+
* @param {Object} [target] - Object of the event owner.
|
1211
|
+
* @private
|
1212
|
+
*/
|
1213
|
+
_lazyFire(eventName, paramsMaker, target) {
|
1214
|
+
const existEventDelegation = target && target.canvasEventDelegation;
|
1215
|
+
const delegationState = existEventDelegation ? target.canvasEventDelegation(eventName) : 'none';
|
1216
|
+
|
1217
|
+
if (delegationState === 'unregistered') {
|
1218
|
+
target.canvasEventRegister(eventName, (object) => {
|
1219
|
+
this.fire(eventName, paramsMaker(object));
|
1220
|
+
});
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
if (delegationState === 'none') {
|
1224
|
+
this.fire(eventName, paramsMaker(target));
|
1225
|
+
}
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
/**
|
1229
|
+
* "object:selected" canvas event handler
|
1230
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1231
|
+
* @private
|
1232
|
+
*/
|
1233
|
+
_onObjectSelected(fEvent) {
|
1234
|
+
const { target } = fEvent;
|
1235
|
+
const params = this.createObjectProperties(target);
|
1236
|
+
|
1237
|
+
this.fire(events.OBJECT_ACTIVATED, params);
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
/**
|
1241
|
+
* "path:created" canvas event handler
|
1242
|
+
* @param {{path: fabric.Path}} obj - Path object
|
1243
|
+
* @private
|
1244
|
+
*/
|
1245
|
+
_onPathCreated(obj) {
|
1246
|
+
const { x: left, y: top } = obj.path.getCenterPoint();
|
1247
|
+
obj.path.set(
|
1248
|
+
extend(
|
1249
|
+
{
|
1250
|
+
left,
|
1251
|
+
top,
|
1252
|
+
},
|
1253
|
+
fObjectOptions.SELECTION_STYLE
|
1254
|
+
)
|
1255
|
+
);
|
1256
|
+
|
1257
|
+
const params = this.createObjectProperties(obj.path);
|
1258
|
+
|
1259
|
+
this.fire(events.ADD_OBJECT, params);
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
/**
|
1263
|
+
* "selction:cleared" canvas event handler
|
1264
|
+
* @private
|
1265
|
+
*/
|
1266
|
+
_onSelectionCleared() {
|
1267
|
+
this.fire(events.SELECTION_CLEARED);
|
1268
|
+
}
|
1269
|
+
|
1270
|
+
/**
|
1271
|
+
* "selction:created" canvas event handler
|
1272
|
+
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
|
1273
|
+
* @private
|
1274
|
+
*/
|
1275
|
+
_onSelectionCreated(fEvent) {
|
1276
|
+
const { target } = fEvent;
|
1277
|
+
const params = this.createObjectProperties(target);
|
1278
|
+
|
1279
|
+
this.fire(events.OBJECT_ACTIVATED, params);
|
1280
|
+
this.fire(events.SELECTION_CREATED, fEvent.target);
|
1281
|
+
}
|
1282
|
+
|
1283
|
+
/**
|
1284
|
+
* Canvas discard selection all
|
1285
|
+
*/
|
1286
|
+
discardSelection() {
|
1287
|
+
this._canvas.discardActiveObject();
|
1288
|
+
this._canvas.renderAll();
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
/**
|
1292
|
+
* Canvas Selectable status change
|
1293
|
+
* @param {boolean} selectable - expect status
|
1294
|
+
*/
|
1295
|
+
changeSelectableAll(selectable) {
|
1296
|
+
this._canvas.forEachObject((obj) => {
|
1297
|
+
obj.selectable = selectable;
|
1298
|
+
obj.hoverCursor = selectable ? 'move' : 'crosshair';
|
1299
|
+
});
|
1300
|
+
}
|
1301
|
+
|
1302
|
+
/**
|
1303
|
+
* Return object's properties
|
1304
|
+
* @param {fabric.Object} obj - fabric object
|
1305
|
+
* @returns {Object} properties object
|
1306
|
+
*/
|
1307
|
+
createObjectProperties(obj) {
|
1308
|
+
const predefinedKeys = [
|
1309
|
+
'left',
|
1310
|
+
'top',
|
1311
|
+
'width',
|
1312
|
+
'height',
|
1313
|
+
'fill',
|
1314
|
+
'stroke',
|
1315
|
+
'strokeWidth',
|
1316
|
+
'opacity',
|
1317
|
+
'angle',
|
1318
|
+
];
|
1319
|
+
const props = {
|
1320
|
+
id: stamp(obj),
|
1321
|
+
type: obj.type,
|
1322
|
+
};
|
1323
|
+
|
1324
|
+
extend(props, getProperties(obj, predefinedKeys));
|
1325
|
+
|
1326
|
+
if (includes(['i-text', 'text'], obj.type)) {
|
1327
|
+
extend(props, this._createTextProperties(obj, props));
|
1328
|
+
} else if (includes(['rect', 'triangle', 'circle'], obj.type)) {
|
1329
|
+
const shapeComp = this.getComponent(components.SHAPE);
|
1330
|
+
extend(props, {
|
1331
|
+
fill: shapeComp.makeFillPropertyForUserEvent(obj),
|
1332
|
+
});
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
return props;
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
/**
|
1339
|
+
* Get text object's properties
|
1340
|
+
* @param {fabric.Object} obj - fabric text object
|
1341
|
+
* @param {Object} props - properties
|
1342
|
+
* @returns {Object} properties object
|
1343
|
+
*/
|
1344
|
+
_createTextProperties(obj) {
|
1345
|
+
const predefinedKeys = [
|
1346
|
+
'text',
|
1347
|
+
'fontFamily',
|
1348
|
+
'fontSize',
|
1349
|
+
'fontStyle',
|
1350
|
+
'textAlign',
|
1351
|
+
'textDecoration',
|
1352
|
+
'fontWeight',
|
1353
|
+
];
|
1354
|
+
const props = {};
|
1355
|
+
extend(props, getProperties(obj, predefinedKeys));
|
1356
|
+
|
1357
|
+
return props;
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
/**
|
1361
|
+
* Add object array by id
|
1362
|
+
* @param {fabric.Object} obj - fabric object
|
1363
|
+
* @returns {number} object id
|
1364
|
+
*/
|
1365
|
+
_addFabricObject(obj) {
|
1366
|
+
const id = stamp(obj);
|
1367
|
+
this._objects[id] = obj;
|
1368
|
+
|
1369
|
+
return id;
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
/**
|
1373
|
+
* Remove an object in array yb id
|
1374
|
+
* @param {number} id - object id
|
1375
|
+
*/
|
1376
|
+
_removeFabricObject(id) {
|
1377
|
+
delete this._objects[id];
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
/**
|
1381
|
+
* Reset targetObjectForCopyPaste value from activeObject
|
1382
|
+
*/
|
1383
|
+
resetTargetObjectForCopyPaste() {
|
1384
|
+
const activeObject = this.getActiveObject();
|
1385
|
+
|
1386
|
+
if (activeObject) {
|
1387
|
+
this.targetObjectForCopyPaste = activeObject;
|
1388
|
+
}
|
1389
|
+
}
|
1390
|
+
|
1391
|
+
/**
|
1392
|
+
* Paste fabric object
|
1393
|
+
* @returns {Promise}
|
1394
|
+
*/
|
1395
|
+
pasteObject() {
|
1396
|
+
if (!this.targetObjectForCopyPaste) {
|
1397
|
+
return Promise.resolve([]);
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
const targetObject = this.targetObjectForCopyPaste;
|
1401
|
+
const isGroupSelect = targetObject.type === 'activeSelection';
|
1402
|
+
const targetObjects = isGroupSelect ? targetObject.getObjects() : [targetObject];
|
1403
|
+
let newTargetObject = null;
|
1404
|
+
|
1405
|
+
this.discardSelection();
|
1406
|
+
|
1407
|
+
return this._cloneObject(targetObjects).then((addedObjects) => {
|
1408
|
+
if (addedObjects.length > 1) {
|
1409
|
+
newTargetObject = this.getActiveSelectionFromObjects(addedObjects);
|
1410
|
+
} else {
|
1411
|
+
[newTargetObject] = addedObjects;
|
1412
|
+
}
|
1413
|
+
this.targetObjectForCopyPaste = newTargetObject;
|
1414
|
+
this.setActiveObject(newTargetObject);
|
1415
|
+
});
|
1416
|
+
}
|
1417
|
+
|
1418
|
+
/**
|
1419
|
+
* Clone object
|
1420
|
+
* @param {fabric.Object} targetObjects - fabric object
|
1421
|
+
* @returns {Promise}
|
1422
|
+
* @private
|
1423
|
+
*/
|
1424
|
+
_cloneObject(targetObjects) {
|
1425
|
+
const addedObjects = targetObjects.map((targetObject) => this._cloneObjectItem(targetObject));
|
1426
|
+
|
1427
|
+
return Promise.all(addedObjects);
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
/**
|
1431
|
+
* Clone object one item
|
1432
|
+
* @param {fabric.Object} targetObject - fabric object
|
1433
|
+
* @returns {Promise}
|
1434
|
+
* @private
|
1435
|
+
*/
|
1436
|
+
_cloneObjectItem(targetObject) {
|
1437
|
+
return this._copyFabricObjectForPaste(targetObject).then((clonedObject) => {
|
1438
|
+
const objectProperties = this.createObjectProperties(clonedObject);
|
1439
|
+
this.add(clonedObject);
|
1440
|
+
|
1441
|
+
this.fire(events.ADD_OBJECT, objectProperties);
|
1442
|
+
|
1443
|
+
return clonedObject;
|
1444
|
+
});
|
1445
|
+
}
|
1446
|
+
|
1447
|
+
/**
|
1448
|
+
* Copy fabric object with Changed position for copy and paste
|
1449
|
+
* @param {fabric.Object} targetObject - fabric object
|
1450
|
+
* @returns {Promise}
|
1451
|
+
* @private
|
1452
|
+
*/
|
1453
|
+
_copyFabricObjectForPaste(targetObject) {
|
1454
|
+
const addExtraPx = (value, isReverse) =>
|
1455
|
+
isReverse ? value - EXTRA_PX_FOR_PASTE : value + EXTRA_PX_FOR_PASTE;
|
1456
|
+
|
1457
|
+
return this._copyFabricObject(targetObject).then((clonedObject) => {
|
1458
|
+
const { left, top, width, height } = clonedObject;
|
1459
|
+
const { width: canvasWidth, height: canvasHeight } = this.getCanvasSize();
|
1460
|
+
const rightEdge = left + width / 2;
|
1461
|
+
const bottomEdge = top + height / 2;
|
1462
|
+
|
1463
|
+
clonedObject.set(
|
1464
|
+
extend(
|
1465
|
+
{
|
1466
|
+
left: addExtraPx(left, rightEdge + EXTRA_PX_FOR_PASTE > canvasWidth),
|
1467
|
+
top: addExtraPx(top, bottomEdge + EXTRA_PX_FOR_PASTE > canvasHeight),
|
1468
|
+
},
|
1469
|
+
fObjectOptions.SELECTION_STYLE
|
1470
|
+
)
|
1471
|
+
);
|
1472
|
+
|
1473
|
+
return clonedObject;
|
1474
|
+
});
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
/**
|
1478
|
+
* Copy fabric object
|
1479
|
+
* @param {fabric.Object} targetObject - fabric object
|
1480
|
+
* @returns {Promise}
|
1481
|
+
* @private
|
1482
|
+
*/
|
1483
|
+
_copyFabricObject(targetObject) {
|
1484
|
+
return new Promise((resolve) => {
|
1485
|
+
targetObject.clone((cloned) => {
|
1486
|
+
const shapeComp = this.getComponent(components.SHAPE);
|
1487
|
+
if (isShape(cloned)) {
|
1488
|
+
shapeComp.processForCopiedObject(cloned, targetObject);
|
1489
|
+
}
|
1490
|
+
|
1491
|
+
resolve(cloned);
|
1492
|
+
});
|
1493
|
+
});
|
1494
|
+
}
|
1495
|
+
|
1496
|
+
/**
|
1497
|
+
* Get current dimensions
|
1498
|
+
* @returns {object}
|
1499
|
+
*/
|
1500
|
+
getCurrentDimensions() {
|
1501
|
+
const resize = this.getComponent(components.RESIZE);
|
1502
|
+
|
1503
|
+
return resize.getCurrentDimensions();
|
1504
|
+
}
|
1505
|
+
|
1506
|
+
/**
|
1507
|
+
* Get original dimensions
|
1508
|
+
* @returns {object}
|
1509
|
+
*/
|
1510
|
+
getOriginalDimensions() {
|
1511
|
+
const resize = this.getComponent(components.RESIZE);
|
1512
|
+
|
1513
|
+
return resize.getOriginalDimensions();
|
1514
|
+
}
|
1515
|
+
|
1516
|
+
/**
|
1517
|
+
* Set original dimensions
|
1518
|
+
* @param {object} dimensions - Dimensions
|
1519
|
+
*/
|
1520
|
+
setOriginalDimensions(dimensions) {
|
1521
|
+
const resize = this.getComponent(components.RESIZE);
|
1522
|
+
resize.setOriginalDimensions(dimensions);
|
1523
|
+
}
|
1524
|
+
|
1525
|
+
/**
|
1526
|
+
* Resize Image
|
1527
|
+
* @param {Object} dimensions - Resize dimensions
|
1528
|
+
* @returns {Promise}
|
1529
|
+
*/
|
1530
|
+
resize(dimensions) {
|
1531
|
+
const resize = this.getComponent(components.RESIZE);
|
1532
|
+
|
1533
|
+
return resize.resize(dimensions);
|
1534
|
+
}
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
CustomEvents.mixin(Graphics);
|
1538
|
+
|
1539
|
+
export default Graphics;
|