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,1795 @@
|
|
1
|
+
import { fabric } from 'fabric';
|
2
|
+
import extend from 'tui-code-snippet/object/extend';
|
3
|
+
import isUndefined from 'tui-code-snippet/type/isUndefined';
|
4
|
+
import forEach from 'tui-code-snippet/collection/forEach';
|
5
|
+
import CustomEvents from 'tui-code-snippet/customEvents/customEvents';
|
6
|
+
import Invoker from '@/invoker';
|
7
|
+
import UI from '@/ui';
|
8
|
+
import action from '@/action';
|
9
|
+
import commandFactory from '@/factory/command';
|
10
|
+
import Graphics from '@/graphics';
|
11
|
+
import { makeSelectionUndoData, makeSelectionUndoDatum } from '@/helper/selectionModifyHelper';
|
12
|
+
import { sendHostName, getObjectType } from '@/util';
|
13
|
+
import {
|
14
|
+
eventNames as events,
|
15
|
+
commandNames as commands,
|
16
|
+
keyCodes,
|
17
|
+
rejectMessages,
|
18
|
+
OBJ_TYPE,
|
19
|
+
zoomModes,
|
20
|
+
} from '@/consts';
|
21
|
+
|
22
|
+
const {
|
23
|
+
MOUSE_DOWN,
|
24
|
+
OBJECT_MOVED,
|
25
|
+
OBJECT_SCALED,
|
26
|
+
OBJECT_ACTIVATED,
|
27
|
+
OBJECT_ROTATED,
|
28
|
+
OBJECT_ADDED,
|
29
|
+
OBJECT_MODIFIED,
|
30
|
+
ADD_TEXT,
|
31
|
+
ADD_OBJECT,
|
32
|
+
TEXT_EDITING,
|
33
|
+
TEXT_CHANGED,
|
34
|
+
ICON_CREATE_RESIZE,
|
35
|
+
ICON_CREATE_END,
|
36
|
+
SELECTION_CLEARED,
|
37
|
+
SELECTION_CREATED,
|
38
|
+
ADD_OBJECT_AFTER,
|
39
|
+
} = events;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Image filter result
|
43
|
+
* @typedef {object} FilterResult
|
44
|
+
* @property {string} type - filter type like 'mask', 'Grayscale' and so on
|
45
|
+
* @property {string} action - action type like 'add', 'remove'
|
46
|
+
*/
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Flip status
|
50
|
+
* @typedef {object} FlipStatus
|
51
|
+
* @property {boolean} flipX - x axis
|
52
|
+
* @property {boolean} flipY - y axis
|
53
|
+
* @property {Number} angle - angle
|
54
|
+
*/
|
55
|
+
/**
|
56
|
+
* Rotation status
|
57
|
+
* @typedef {Number} RotateStatus
|
58
|
+
* @property {Number} angle - angle
|
59
|
+
*/
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Old and new Size
|
63
|
+
* @typedef {object} SizeChange
|
64
|
+
* @property {Number} oldWidth - old width
|
65
|
+
* @property {Number} oldHeight - old height
|
66
|
+
* @property {Number} newWidth - new width
|
67
|
+
* @property {Number} newHeight - new height
|
68
|
+
*/
|
69
|
+
|
70
|
+
/**
|
71
|
+
* @typedef {string} ErrorMsg - {string} error message
|
72
|
+
*/
|
73
|
+
|
74
|
+
/**
|
75
|
+
* @typedef {object} ObjectProps - graphics object properties
|
76
|
+
* @property {number} id - object id
|
77
|
+
* @property {string} type - object type
|
78
|
+
* @property {string} text - text content
|
79
|
+
* @property {(string | number)} left - Left
|
80
|
+
* @property {(string | number)} top - Top
|
81
|
+
* @property {(string | number)} width - Width
|
82
|
+
* @property {(string | number)} height - Height
|
83
|
+
* @property {string} fill - Color
|
84
|
+
* @property {string} stroke - Stroke
|
85
|
+
* @property {(string | number)} strokeWidth - StrokeWidth
|
86
|
+
* @property {string} fontFamily - Font type for text
|
87
|
+
* @property {number} fontSize - Font Size
|
88
|
+
* @property {string} fontStyle - Type of inclination (normal / italic)
|
89
|
+
* @property {string} fontWeight - Type of thicker or thinner looking (normal / bold)
|
90
|
+
* @property {string} textAlign - Type of text align (left / center / right)
|
91
|
+
* @property {string} textDecoration - Type of line (underline / line-through / overline)
|
92
|
+
*/
|
93
|
+
|
94
|
+
/**
|
95
|
+
* Shape filter option
|
96
|
+
* @typedef {object.<string, number>} ShapeFilterOption
|
97
|
+
*/
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Shape filter option
|
101
|
+
* @typedef {object} ShapeFillOption - fill option of shape
|
102
|
+
* @property {string} type - fill type ('color' or 'filter')
|
103
|
+
* @property {Array.<ShapeFillFilterOption>} [filter] - {@link ShapeFilterOption} List.
|
104
|
+
* only applies to filter types
|
105
|
+
* (ex: \[\{pixelate: 20\}, \{blur: 0.3\}\])
|
106
|
+
* @property {string} [color] - Shape foreground color (ex: '#fff', 'transparent')
|
107
|
+
*/
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Image editor
|
111
|
+
* @class
|
112
|
+
* @param {string|HTMLElement} wrapper - Wrapper's element or selector
|
113
|
+
* @param {Object} [options] - Canvas max width & height of css
|
114
|
+
* @param {number} [options.includeUI] - Use the provided UI
|
115
|
+
* @param {Object} [options.includeUI.loadImage] - Basic editing image
|
116
|
+
* @param {string} options.includeUI.loadImage.path - image path
|
117
|
+
* @param {string} options.includeUI.loadImage.name - image name
|
118
|
+
* @param {Object} [options.includeUI.theme] - Theme object
|
119
|
+
* @param {Array} [options.includeUI.menu] - It can be selected when only specific menu is used, Default values are \['crop', 'flip', 'rotate', 'draw', 'shape', 'icon', 'text', 'mask', 'filter'\].
|
120
|
+
* @param {string} [options.includeUI.initMenu] - The first menu to be selected and started.
|
121
|
+
* @param {Object} [options.includeUI.uiSize] - ui size of editor
|
122
|
+
* @param {string} options.includeUI.uiSize.width - width of ui
|
123
|
+
* @param {string} options.includeUI.uiSize.height - height of ui
|
124
|
+
* @param {string} [options.includeUI.menuBarPosition=bottom] - Menu bar position('top', 'bottom', 'left', 'right')
|
125
|
+
* @param {number} options.cssMaxWidth - Canvas css-max-width
|
126
|
+
* @param {number} options.cssMaxHeight - Canvas css-max-height
|
127
|
+
* @param {Object} [options.selectionStyle] - selection style
|
128
|
+
* @param {string} [options.selectionStyle.cornerStyle] - selection corner style
|
129
|
+
* @param {number} [options.selectionStyle.cornerSize] - selection corner size
|
130
|
+
* @param {string} [options.selectionStyle.cornerColor] - selection corner color
|
131
|
+
* @param {string} [options.selectionStyle.cornerStrokeColor] = selection corner stroke color
|
132
|
+
* @param {boolean} [options.selectionStyle.transparentCorners] - selection corner transparent
|
133
|
+
* @param {number} [options.selectionStyle.lineWidth] - selection line width
|
134
|
+
* @param {string} [options.selectionStyle.borderColor] - selection border color
|
135
|
+
* @param {number} [options.selectionStyle.rotatingPointOffset] - selection rotating point length
|
136
|
+
* @param {Boolean} [options.usageStatistics=true] - Let us know the hostname. If you don't want to send the hostname, please set to false.
|
137
|
+
* @example
|
138
|
+
* var ImageEditor = require('tui-image-editor');
|
139
|
+
* var blackTheme = require('./js/theme/black-theme.js');
|
140
|
+
* var instance = new ImageEditor(document.querySelector('#tui-image-editor'), {
|
141
|
+
* includeUI: {
|
142
|
+
* loadImage: {
|
143
|
+
* path: 'img/sampleImage.jpg',
|
144
|
+
* name: 'SampleImage'
|
145
|
+
* },
|
146
|
+
* theme: blackTheme, // or whiteTheme
|
147
|
+
* menu: ['shape', 'filter'],
|
148
|
+
* initMenu: 'filter',
|
149
|
+
* uiSize: {
|
150
|
+
* width: '1000px',
|
151
|
+
* height: '700px'
|
152
|
+
* },
|
153
|
+
* menuBarPosition: 'bottom'
|
154
|
+
* },
|
155
|
+
* cssMaxWidth: 700,
|
156
|
+
* cssMaxHeight: 500,
|
157
|
+
* selectionStyle: {
|
158
|
+
* cornerSize: 20,
|
159
|
+
* rotatingPointOffset: 70
|
160
|
+
* }
|
161
|
+
* });
|
162
|
+
*/
|
163
|
+
class ImageEditor {
|
164
|
+
constructor(wrapper, options) {
|
165
|
+
options = extend(
|
166
|
+
{
|
167
|
+
includeUI: false,
|
168
|
+
usageStatistics: true,
|
169
|
+
},
|
170
|
+
options
|
171
|
+
);
|
172
|
+
|
173
|
+
this.mode = null;
|
174
|
+
|
175
|
+
this.activeObjectId = null;
|
176
|
+
|
177
|
+
/**
|
178
|
+
* UI instance
|
179
|
+
* @type {Ui}
|
180
|
+
*/
|
181
|
+
if (options.includeUI) {
|
182
|
+
const UIOption = options.includeUI;
|
183
|
+
UIOption.usageStatistics = options.usageStatistics;
|
184
|
+
|
185
|
+
this.ui = new UI(wrapper, UIOption, this.getActions());
|
186
|
+
options = this.ui.setUiDefaultSelectionStyle(options);
|
187
|
+
}
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Invoker
|
191
|
+
* @type {Invoker}
|
192
|
+
* @private
|
193
|
+
*/
|
194
|
+
this._invoker = new Invoker();
|
195
|
+
|
196
|
+
/**
|
197
|
+
* Graphics instance
|
198
|
+
* @type {Graphics}
|
199
|
+
* @private
|
200
|
+
*/
|
201
|
+
this._graphics = new Graphics(this.ui ? this.ui.getEditorArea() : wrapper, {
|
202
|
+
cssMaxWidth: options.cssMaxWidth,
|
203
|
+
cssMaxHeight: options.cssMaxHeight,
|
204
|
+
});
|
205
|
+
|
206
|
+
/**
|
207
|
+
* Event handler list
|
208
|
+
* @type {Object}
|
209
|
+
* @private
|
210
|
+
*/
|
211
|
+
this._handlers = {
|
212
|
+
keydown: this._onKeyDown.bind(this),
|
213
|
+
mousedown: this._onMouseDown.bind(this),
|
214
|
+
objectActivated: this._onObjectActivated.bind(this),
|
215
|
+
objectMoved: this._onObjectMoved.bind(this),
|
216
|
+
objectScaled: this._onObjectScaled.bind(this),
|
217
|
+
objectRotated: this._onObjectRotated.bind(this),
|
218
|
+
objectAdded: this._onObjectAdded.bind(this),
|
219
|
+
objectModified: this._onObjectModified.bind(this),
|
220
|
+
createdPath: this._onCreatedPath,
|
221
|
+
addText: this._onAddText.bind(this),
|
222
|
+
addObject: this._onAddObject.bind(this),
|
223
|
+
textEditing: this._onTextEditing.bind(this),
|
224
|
+
textChanged: this._onTextChanged.bind(this),
|
225
|
+
iconCreateResize: this._onIconCreateResize.bind(this),
|
226
|
+
iconCreateEnd: this._onIconCreateEnd.bind(this),
|
227
|
+
selectionCleared: this._selectionCleared.bind(this),
|
228
|
+
selectionCreated: this._selectionCreated.bind(this),
|
229
|
+
};
|
230
|
+
|
231
|
+
this._attachInvokerEvents();
|
232
|
+
this._attachGraphicsEvents();
|
233
|
+
this._attachDomEvents();
|
234
|
+
this._setSelectionStyle(options.selectionStyle, {
|
235
|
+
applyCropSelectionStyle: options.applyCropSelectionStyle,
|
236
|
+
applyGroupSelectionStyle: options.applyGroupSelectionStyle,
|
237
|
+
});
|
238
|
+
|
239
|
+
if (options.usageStatistics) {
|
240
|
+
sendHostName();
|
241
|
+
}
|
242
|
+
|
243
|
+
if (this.ui) {
|
244
|
+
this.ui.initCanvas();
|
245
|
+
this.setReAction();
|
246
|
+
this._attachColorPickerInputBoxEvents();
|
247
|
+
}
|
248
|
+
fabric.enableGLFiltering = false;
|
249
|
+
}
|
250
|
+
|
251
|
+
_attachColorPickerInputBoxEvents() {
|
252
|
+
this.ui.on(events.INPUT_BOX_EDITING_STARTED, () => {
|
253
|
+
this.isColorPickerInputBoxEditing = true;
|
254
|
+
});
|
255
|
+
this.ui.on(events.INPUT_BOX_EDITING_STOPPED, () => {
|
256
|
+
this.isColorPickerInputBoxEditing = false;
|
257
|
+
});
|
258
|
+
}
|
259
|
+
|
260
|
+
_detachColorPickerInputBoxEvents() {
|
261
|
+
this.ui.off(events.INPUT_BOX_EDITING_STARTED);
|
262
|
+
this.ui.off(events.INPUT_BOX_EDITING_STOPPED);
|
263
|
+
}
|
264
|
+
|
265
|
+
/**
|
266
|
+
* Set selection style by init option
|
267
|
+
* @param {Object} selectionStyle - Selection styles
|
268
|
+
* @param {Object} applyTargets - Selection apply targets
|
269
|
+
* @param {boolean} applyCropSelectionStyle - whether apply with crop selection style or not
|
270
|
+
* @param {boolean} applyGroupSelectionStyle - whether apply with group selection style or not
|
271
|
+
* @private
|
272
|
+
*/
|
273
|
+
_setSelectionStyle(selectionStyle, { applyCropSelectionStyle, applyGroupSelectionStyle }) {
|
274
|
+
if (selectionStyle) {
|
275
|
+
this._graphics.setSelectionStyle(selectionStyle);
|
276
|
+
}
|
277
|
+
|
278
|
+
if (applyCropSelectionStyle) {
|
279
|
+
this._graphics.setCropSelectionStyle(selectionStyle);
|
280
|
+
}
|
281
|
+
|
282
|
+
if (applyGroupSelectionStyle) {
|
283
|
+
this.on('selectionCreated', (eventTarget) => {
|
284
|
+
if (eventTarget.type === 'activeSelection') {
|
285
|
+
eventTarget.set(selectionStyle);
|
286
|
+
}
|
287
|
+
});
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
/**
|
292
|
+
* Attach invoker events
|
293
|
+
* @private
|
294
|
+
*/
|
295
|
+
_attachInvokerEvents() {
|
296
|
+
const {
|
297
|
+
UNDO_STACK_CHANGED,
|
298
|
+
REDO_STACK_CHANGED,
|
299
|
+
EXECUTE_COMMAND,
|
300
|
+
AFTER_UNDO,
|
301
|
+
AFTER_REDO,
|
302
|
+
HAND_STARTED,
|
303
|
+
HAND_STOPPED,
|
304
|
+
} = events;
|
305
|
+
|
306
|
+
/**
|
307
|
+
* Undo stack changed event
|
308
|
+
* @event ImageEditor#undoStackChanged
|
309
|
+
* @param {Number} length - undo stack length
|
310
|
+
* @example
|
311
|
+
* imageEditor.on('undoStackChanged', function(length) {
|
312
|
+
* console.log(length);
|
313
|
+
* });
|
314
|
+
*/
|
315
|
+
this._invoker.on(UNDO_STACK_CHANGED, this.fire.bind(this, UNDO_STACK_CHANGED));
|
316
|
+
/**
|
317
|
+
* Redo stack changed event
|
318
|
+
* @event ImageEditor#redoStackChanged
|
319
|
+
* @param {Number} length - redo stack length
|
320
|
+
* @example
|
321
|
+
* imageEditor.on('redoStackChanged', function(length) {
|
322
|
+
* console.log(length);
|
323
|
+
* });
|
324
|
+
*/
|
325
|
+
this._invoker.on(REDO_STACK_CHANGED, this.fire.bind(this, REDO_STACK_CHANGED));
|
326
|
+
|
327
|
+
if (this.ui) {
|
328
|
+
const canvas = this._graphics.getCanvas();
|
329
|
+
|
330
|
+
this._invoker.on(EXECUTE_COMMAND, (command) => this.ui.fire(EXECUTE_COMMAND, command));
|
331
|
+
this._invoker.on(AFTER_UNDO, (command) => this.ui.fire(AFTER_UNDO, command));
|
332
|
+
this._invoker.on(AFTER_REDO, (command) => this.ui.fire(AFTER_REDO, command));
|
333
|
+
|
334
|
+
canvas.on(HAND_STARTED, () => this.ui.fire(HAND_STARTED));
|
335
|
+
canvas.on(HAND_STOPPED, () => this.ui.fire(HAND_STOPPED));
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
/**
|
340
|
+
* Attach canvas events
|
341
|
+
* @private
|
342
|
+
*/
|
343
|
+
_attachGraphicsEvents() {
|
344
|
+
this._graphics.on({
|
345
|
+
[MOUSE_DOWN]: this._handlers.mousedown,
|
346
|
+
[OBJECT_MOVED]: this._handlers.objectMoved,
|
347
|
+
[OBJECT_SCALED]: this._handlers.objectScaled,
|
348
|
+
[OBJECT_ROTATED]: this._handlers.objectRotated,
|
349
|
+
[OBJECT_ACTIVATED]: this._handlers.objectActivated,
|
350
|
+
[OBJECT_ADDED]: this._handlers.objectAdded,
|
351
|
+
[OBJECT_MODIFIED]: this._handlers.objectModified,
|
352
|
+
[ADD_TEXT]: this._handlers.addText,
|
353
|
+
[ADD_OBJECT]: this._handlers.addObject,
|
354
|
+
[TEXT_EDITING]: this._handlers.textEditing,
|
355
|
+
[TEXT_CHANGED]: this._handlers.textChanged,
|
356
|
+
[ICON_CREATE_RESIZE]: this._handlers.iconCreateResize,
|
357
|
+
[ICON_CREATE_END]: this._handlers.iconCreateEnd,
|
358
|
+
[SELECTION_CLEARED]: this._handlers.selectionCleared,
|
359
|
+
[SELECTION_CREATED]: this._handlers.selectionCreated,
|
360
|
+
});
|
361
|
+
}
|
362
|
+
|
363
|
+
/**
|
364
|
+
* Attach dom events
|
365
|
+
* @private
|
366
|
+
*/
|
367
|
+
_attachDomEvents() {
|
368
|
+
// ImageEditor supports IE 9 higher
|
369
|
+
document.addEventListener('keydown', this._handlers.keydown);
|
370
|
+
}
|
371
|
+
|
372
|
+
/**
|
373
|
+
* Detach dom events
|
374
|
+
* @private
|
375
|
+
*/
|
376
|
+
_detachDomEvents() {
|
377
|
+
// ImageEditor supports IE 9 higher
|
378
|
+
document.removeEventListener('keydown', this._handlers.keydown);
|
379
|
+
}
|
380
|
+
|
381
|
+
/**
|
382
|
+
* Keydown event handler
|
383
|
+
* @param {KeyboardEvent} e - Event object
|
384
|
+
* @private
|
385
|
+
*/
|
386
|
+
/* eslint-disable complexity */
|
387
|
+
_onKeyDown(e) {
|
388
|
+
const { ctrlKey, keyCode, metaKey } = e;
|
389
|
+
const isModifierKey = ctrlKey || metaKey;
|
390
|
+
|
391
|
+
if (isModifierKey) {
|
392
|
+
if (keyCode === keyCodes.C) {
|
393
|
+
this._graphics.resetTargetObjectForCopyPaste();
|
394
|
+
} else if (keyCode === keyCodes.V) {
|
395
|
+
this._graphics.pasteObject();
|
396
|
+
this.clearRedoStack();
|
397
|
+
} else if (keyCode === keyCodes.Z) {
|
398
|
+
// There is no error message on shortcut when it's empty
|
399
|
+
this.undo()['catch'](() => {});
|
400
|
+
} else if (keyCode === keyCodes.Y) {
|
401
|
+
// There is no error message on shortcut when it's empty
|
402
|
+
this.redo()['catch'](() => {});
|
403
|
+
}
|
404
|
+
}
|
405
|
+
|
406
|
+
const isDeleteKey = keyCode === keyCodes.BACKSPACE || keyCode === keyCodes.DEL;
|
407
|
+
const isRemoveReady = this._graphics.isReadyRemoveObject();
|
408
|
+
|
409
|
+
if (!this.isColorPickerInputBoxEditing && isRemoveReady && isDeleteKey) {
|
410
|
+
e.preventDefault();
|
411
|
+
this.removeActiveObject();
|
412
|
+
}
|
413
|
+
}
|
414
|
+
|
415
|
+
/**
|
416
|
+
* Remove Active Object
|
417
|
+
*/
|
418
|
+
removeActiveObject() {
|
419
|
+
const activeObjectId = this._graphics.getActiveObjectIdForRemove();
|
420
|
+
|
421
|
+
this.removeObject(activeObjectId);
|
422
|
+
}
|
423
|
+
|
424
|
+
/**
|
425
|
+
* mouse down event handler
|
426
|
+
* @param {Event} event - mouse down event
|
427
|
+
* @param {Object} originPointer - origin pointer
|
428
|
+
* @param {Number} originPointer.x x position
|
429
|
+
* @param {Number} originPointer.y y position
|
430
|
+
* @private
|
431
|
+
*/
|
432
|
+
_onMouseDown(event, originPointer) {
|
433
|
+
/**
|
434
|
+
* The mouse down event with position x, y on canvas
|
435
|
+
* @event ImageEditor#mousedown
|
436
|
+
* @param {Object} event - browser mouse event object
|
437
|
+
* @param {Object} originPointer origin pointer
|
438
|
+
* @param {Number} originPointer.x x position
|
439
|
+
* @param {Number} originPointer.y y position
|
440
|
+
* @example
|
441
|
+
* imageEditor.on('mousedown', function(event, originPointer) {
|
442
|
+
* console.log(event);
|
443
|
+
* console.log(originPointer);
|
444
|
+
* if (imageEditor.hasFilter('colorFilter')) {
|
445
|
+
* imageEditor.applyFilter('colorFilter', {
|
446
|
+
* x: parseInt(originPointer.x, 10),
|
447
|
+
* y: parseInt(originPointer.y, 10)
|
448
|
+
* });
|
449
|
+
* }
|
450
|
+
* });
|
451
|
+
*/
|
452
|
+
|
453
|
+
this.fire(events.MOUSE_DOWN, event, originPointer);
|
454
|
+
}
|
455
|
+
|
456
|
+
/**
|
457
|
+
* Add a 'addObject' command
|
458
|
+
* @param {Object} obj - Fabric object
|
459
|
+
* @private
|
460
|
+
*/
|
461
|
+
_pushAddObjectCommand(obj) {
|
462
|
+
const command = commandFactory.create(commands.ADD_OBJECT, this._graphics, obj);
|
463
|
+
this._invoker.pushUndoStack(command);
|
464
|
+
}
|
465
|
+
|
466
|
+
/**
|
467
|
+
* Add a 'changeSelection' command
|
468
|
+
* @param {fabric.Object} obj - selection object
|
469
|
+
* @private
|
470
|
+
*/
|
471
|
+
_pushModifyObjectCommand(obj) {
|
472
|
+
const { type } = obj;
|
473
|
+
const props = makeSelectionUndoData(obj, (item) =>
|
474
|
+
makeSelectionUndoDatum(this._graphics.getObjectId(item), item, type === 'activeSelection')
|
475
|
+
);
|
476
|
+
const command = commandFactory.create(commands.CHANGE_SELECTION, this._graphics, props);
|
477
|
+
command.execute(this._graphics, props);
|
478
|
+
|
479
|
+
this._invoker.pushUndoStack(command);
|
480
|
+
}
|
481
|
+
|
482
|
+
/**
|
483
|
+
* 'objectActivated' event handler
|
484
|
+
* @param {ObjectProps} props - object properties
|
485
|
+
* @private
|
486
|
+
*/
|
487
|
+
_onObjectActivated(props) {
|
488
|
+
/**
|
489
|
+
* The event when object is selected(aka activated).
|
490
|
+
* @event ImageEditor#objectActivated
|
491
|
+
* @param {ObjectProps} objectProps - object properties
|
492
|
+
* @example
|
493
|
+
* imageEditor.on('objectActivated', function(props) {
|
494
|
+
* console.log(props);
|
495
|
+
* console.log(props.type);
|
496
|
+
* console.log(props.id);
|
497
|
+
* });
|
498
|
+
*/
|
499
|
+
this.fire(events.OBJECT_ACTIVATED, props);
|
500
|
+
}
|
501
|
+
|
502
|
+
/**
|
503
|
+
* 'objectMoved' event handler
|
504
|
+
* @param {ObjectProps} props - object properties
|
505
|
+
* @private
|
506
|
+
*/
|
507
|
+
_onObjectMoved(props) {
|
508
|
+
/**
|
509
|
+
* The event when object is moved
|
510
|
+
* @event ImageEditor#objectMoved
|
511
|
+
* @param {ObjectProps} props - object properties
|
512
|
+
* @example
|
513
|
+
* imageEditor.on('objectMoved', function(props) {
|
514
|
+
* console.log(props);
|
515
|
+
* console.log(props.type);
|
516
|
+
* });
|
517
|
+
*/
|
518
|
+
this.fire(events.OBJECT_MOVED, props);
|
519
|
+
}
|
520
|
+
|
521
|
+
/**
|
522
|
+
* 'objectScaled' event handler
|
523
|
+
* @param {ObjectProps} props - object properties
|
524
|
+
* @private
|
525
|
+
*/
|
526
|
+
_onObjectScaled(props) {
|
527
|
+
/**
|
528
|
+
* The event when scale factor is changed
|
529
|
+
* @event ImageEditor#objectScaled
|
530
|
+
* @param {ObjectProps} props - object properties
|
531
|
+
* @example
|
532
|
+
* imageEditor.on('objectScaled', function(props) {
|
533
|
+
* console.log(props);
|
534
|
+
* console.log(props.type);
|
535
|
+
* });
|
536
|
+
*/
|
537
|
+
this.fire(events.OBJECT_SCALED, props);
|
538
|
+
}
|
539
|
+
|
540
|
+
/**
|
541
|
+
* 'objectRotated' event handler
|
542
|
+
* @param {ObjectProps} props - object properties
|
543
|
+
* @private
|
544
|
+
*/
|
545
|
+
_onObjectRotated(props) {
|
546
|
+
/**
|
547
|
+
* The event when object angle is changed
|
548
|
+
* @event ImageEditor#objectRotated
|
549
|
+
* @param {ObjectProps} props - object properties
|
550
|
+
* @example
|
551
|
+
* imageEditor.on('objectRotated', function(props) {
|
552
|
+
* console.log(props);
|
553
|
+
* console.log(props.type);
|
554
|
+
* });
|
555
|
+
*/
|
556
|
+
this.fire(events.OBJECT_ROTATED, props);
|
557
|
+
}
|
558
|
+
|
559
|
+
/**
|
560
|
+
* Get current drawing mode
|
561
|
+
* @returns {string}
|
562
|
+
* @example
|
563
|
+
* // Image editor drawing mode
|
564
|
+
* //
|
565
|
+
* // NORMAL: 'NORMAL'
|
566
|
+
* // CROPPER: 'CROPPER'
|
567
|
+
* // FREE_DRAWING: 'FREE_DRAWING'
|
568
|
+
* // LINE_DRAWING: 'LINE_DRAWING'
|
569
|
+
* // TEXT: 'TEXT'
|
570
|
+
* //
|
571
|
+
* if (imageEditor.getDrawingMode() === 'FREE_DRAWING') {
|
572
|
+
* imageEditor.stopDrawingMode();
|
573
|
+
* }
|
574
|
+
*/
|
575
|
+
getDrawingMode() {
|
576
|
+
return this._graphics.getDrawingMode();
|
577
|
+
}
|
578
|
+
|
579
|
+
/**
|
580
|
+
* Clear all objects
|
581
|
+
* @returns {Promise}
|
582
|
+
* @example
|
583
|
+
* imageEditor.clearObjects();
|
584
|
+
*/
|
585
|
+
clearObjects() {
|
586
|
+
return this.execute(commands.CLEAR_OBJECTS);
|
587
|
+
}
|
588
|
+
|
589
|
+
/**
|
590
|
+
* Deactivate all objects
|
591
|
+
* @example
|
592
|
+
* imageEditor.deactivateAll();
|
593
|
+
*/
|
594
|
+
deactivateAll() {
|
595
|
+
this._graphics.deactivateAll();
|
596
|
+
this._graphics.renderAll();
|
597
|
+
}
|
598
|
+
|
599
|
+
/**
|
600
|
+
* discard selction
|
601
|
+
* @example
|
602
|
+
* imageEditor.discardSelection();
|
603
|
+
*/
|
604
|
+
discardSelection() {
|
605
|
+
this._graphics.discardSelection();
|
606
|
+
}
|
607
|
+
|
608
|
+
/**
|
609
|
+
* selectable status change
|
610
|
+
* @param {boolean} selectable - selectable status
|
611
|
+
* @example
|
612
|
+
* imageEditor.changeSelectableAll(false); // or true
|
613
|
+
*/
|
614
|
+
changeSelectableAll(selectable) {
|
615
|
+
this._graphics.changeSelectableAll(selectable);
|
616
|
+
}
|
617
|
+
|
618
|
+
/**
|
619
|
+
* Init history
|
620
|
+
*/
|
621
|
+
_initHistory() {
|
622
|
+
if (this.ui) {
|
623
|
+
this.ui.initHistory();
|
624
|
+
}
|
625
|
+
}
|
626
|
+
|
627
|
+
/**
|
628
|
+
* Clear history
|
629
|
+
*/
|
630
|
+
_clearHistory() {
|
631
|
+
if (this.ui) {
|
632
|
+
this.ui.clearHistory();
|
633
|
+
}
|
634
|
+
}
|
635
|
+
|
636
|
+
/**
|
637
|
+
* Invoke command
|
638
|
+
* @param {String} commandName - Command name
|
639
|
+
* @param {...*} args - Arguments for creating command
|
640
|
+
* @returns {Promise}
|
641
|
+
* @private
|
642
|
+
*/
|
643
|
+
execute(commandName, ...args) {
|
644
|
+
// Inject an Graphics instance as first parameter
|
645
|
+
const theArgs = [this._graphics].concat(args);
|
646
|
+
|
647
|
+
return this._invoker.execute(commandName, ...theArgs);
|
648
|
+
}
|
649
|
+
|
650
|
+
/**
|
651
|
+
* Invoke command
|
652
|
+
* @param {String} commandName - Command name
|
653
|
+
* @param {...*} args - Arguments for creating command
|
654
|
+
* @returns {Promise}
|
655
|
+
* @private
|
656
|
+
*/
|
657
|
+
executeSilent(commandName, ...args) {
|
658
|
+
// Inject an Graphics instance as first parameter
|
659
|
+
const theArgs = [this._graphics].concat(args);
|
660
|
+
|
661
|
+
return this._invoker.executeSilent(commandName, ...theArgs);
|
662
|
+
}
|
663
|
+
|
664
|
+
/**
|
665
|
+
* Undo
|
666
|
+
* @param {number} [iterationCount=1] - Iteration count of undo
|
667
|
+
* @returns {Promise}
|
668
|
+
* @example
|
669
|
+
* imageEditor.undo();
|
670
|
+
*/
|
671
|
+
undo(iterationCount = 1) {
|
672
|
+
let promise = Promise.resolve();
|
673
|
+
|
674
|
+
for (let i = 0; i < iterationCount; i += 1) {
|
675
|
+
promise = promise.then(() => this._invoker.undo());
|
676
|
+
}
|
677
|
+
|
678
|
+
return promise;
|
679
|
+
}
|
680
|
+
|
681
|
+
/**
|
682
|
+
* Redo
|
683
|
+
* @param {number} [iterationCount=1] - Iteration count of redo
|
684
|
+
* @returns {Promise}
|
685
|
+
* @example
|
686
|
+
* imageEditor.redo();
|
687
|
+
*/
|
688
|
+
redo(iterationCount = 1) {
|
689
|
+
let promise = Promise.resolve();
|
690
|
+
|
691
|
+
for (let i = 0; i < iterationCount; i += 1) {
|
692
|
+
promise = promise.then(() => this._invoker.redo());
|
693
|
+
}
|
694
|
+
|
695
|
+
return promise;
|
696
|
+
}
|
697
|
+
|
698
|
+
/**
|
699
|
+
* Zoom
|
700
|
+
* @param {number} x - x axis of center point for zoom
|
701
|
+
* @param {number} y - y axis of center point for zoom
|
702
|
+
* @param {number} zoomLevel - level of zoom(1.0 ~ 5.0)
|
703
|
+
*/
|
704
|
+
zoom({ x, y, zoomLevel }) {
|
705
|
+
this._graphics.zoom({ x, y }, zoomLevel);
|
706
|
+
}
|
707
|
+
|
708
|
+
/**
|
709
|
+
* Reset zoom. Change zoom level to 1.0
|
710
|
+
*/
|
711
|
+
resetZoom() {
|
712
|
+
this._graphics.resetZoom();
|
713
|
+
}
|
714
|
+
|
715
|
+
/**
|
716
|
+
* start hand mode
|
717
|
+
*/
|
718
|
+
startHandMode() {
|
719
|
+
const zoomMode = this._graphics.getZoomMode();
|
720
|
+
this.stopDrawingMode();
|
721
|
+
if (zoomMode !== zoomModes.HAND) {
|
722
|
+
this._graphics.startHandMode();
|
723
|
+
}
|
724
|
+
}
|
725
|
+
|
726
|
+
/**
|
727
|
+
* end hand mode
|
728
|
+
*/
|
729
|
+
endHandMode() {
|
730
|
+
const zoomMode = this._graphics.getZoomMode();
|
731
|
+
this.stopDrawingMode();
|
732
|
+
if (zoomMode === zoomModes.HAND) {
|
733
|
+
this._graphics.endHandMode();
|
734
|
+
}
|
735
|
+
}
|
736
|
+
|
737
|
+
/**
|
738
|
+
* Load image from file
|
739
|
+
* @param {File} imgFile - Image file
|
740
|
+
* @param {string} [imageName] - imageName
|
741
|
+
* @returns {Promise<SizeChange, ErrorMsg>}
|
742
|
+
* @example
|
743
|
+
* imageEditor.loadImageFromFile(file).then(result => {
|
744
|
+
* console.log('old : ' + result.oldWidth + ', ' + result.oldHeight);
|
745
|
+
* console.log('new : ' + result.newWidth + ', ' + result.newHeight);
|
746
|
+
* });
|
747
|
+
*/
|
748
|
+
loadImageFromFile(imgFile, imageName) {
|
749
|
+
if (!imgFile) {
|
750
|
+
return Promise.reject(rejectMessages.invalidParameters);
|
751
|
+
}
|
752
|
+
|
753
|
+
const imgUrl = URL.createObjectURL(imgFile);
|
754
|
+
imageName = imageName || imgFile.name;
|
755
|
+
|
756
|
+
return this.loadImageFromURL(imgUrl, imageName).then((value) => {
|
757
|
+
URL.revokeObjectURL(imgFile);
|
758
|
+
|
759
|
+
return value;
|
760
|
+
});
|
761
|
+
}
|
762
|
+
|
763
|
+
/**
|
764
|
+
* Load image from url
|
765
|
+
* @param {string} url - File url
|
766
|
+
* @param {string} imageName - imageName
|
767
|
+
* @returns {Promise<SizeChange, ErrorMsg>}
|
768
|
+
* @example
|
769
|
+
* imageEditor.loadImageFromURL('http://url/testImage.png', 'lena').then(result => {
|
770
|
+
* console.log('old : ' + result.oldWidth + ', ' + result.oldHeight);
|
771
|
+
* console.log('new : ' + result.newWidth + ', ' + result.newHeight);
|
772
|
+
* });
|
773
|
+
*/
|
774
|
+
loadImageFromURL(url, imageName) {
|
775
|
+
if (!imageName || !url) {
|
776
|
+
return Promise.reject(rejectMessages.invalidParameters);
|
777
|
+
}
|
778
|
+
|
779
|
+
return this.execute(commands.LOAD_IMAGE, imageName, url);
|
780
|
+
}
|
781
|
+
|
782
|
+
/**
|
783
|
+
* Add image object on canvas
|
784
|
+
* @param {string} imgUrl - Image url to make object
|
785
|
+
* @returns {Promise<ObjectProps, ErrorMsg>}
|
786
|
+
* @example
|
787
|
+
* imageEditor.addImageObject('path/fileName.jpg').then(objectProps => {
|
788
|
+
* console.log(ojectProps.id);
|
789
|
+
* });
|
790
|
+
*/
|
791
|
+
addImageObject(imgUrl) {
|
792
|
+
if (!imgUrl) {
|
793
|
+
return Promise.reject(rejectMessages.invalidParameters);
|
794
|
+
}
|
795
|
+
|
796
|
+
return this.execute(commands.ADD_IMAGE_OBJECT, imgUrl);
|
797
|
+
}
|
798
|
+
|
799
|
+
/**
|
800
|
+
* Start a drawing mode. If the current mode is not 'NORMAL', 'stopDrawingMode()' will be called first.
|
801
|
+
* @param {String} mode Can be one of <I>'CROPPER', 'FREE_DRAWING', 'LINE_DRAWING', 'TEXT', 'SHAPE'</I>
|
802
|
+
* @param {Object} [option] parameters of drawing mode, it's available with 'FREE_DRAWING', 'LINE_DRAWING'
|
803
|
+
* @param {Number} [option.width] brush width
|
804
|
+
* @param {String} [option.color] brush color
|
805
|
+
* @param {Object} [option.arrowType] arrow decorate
|
806
|
+
* @param {string} [option.arrowType.tail] arrow decorate for tail. 'chevron' or 'triangle'
|
807
|
+
* @param {string} [option.arrowType.head] arrow decorate for head. 'chevron' or 'triangle'
|
808
|
+
* @returns {boolean} true if success or false
|
809
|
+
* @example
|
810
|
+
* imageEditor.startDrawingMode('FREE_DRAWING', {
|
811
|
+
* width: 10,
|
812
|
+
* color: 'rgba(255,0,0,0.5)'
|
813
|
+
* });
|
814
|
+
* imageEditor.startDrawingMode('LINE_DRAWING', {
|
815
|
+
* width: 10,
|
816
|
+
* color: 'rgba(255,0,0,0.5)',
|
817
|
+
* arrowType: {
|
818
|
+
* tail: 'chevron' // triangle
|
819
|
+
* }
|
820
|
+
* });
|
821
|
+
*
|
822
|
+
*/
|
823
|
+
startDrawingMode(mode, option) {
|
824
|
+
return this._graphics.startDrawingMode(mode, option);
|
825
|
+
}
|
826
|
+
|
827
|
+
/**
|
828
|
+
* Stop the current drawing mode and back to the 'NORMAL' mode
|
829
|
+
* @example
|
830
|
+
* imageEditor.stopDrawingMode();
|
831
|
+
*/
|
832
|
+
stopDrawingMode() {
|
833
|
+
this._graphics.stopDrawingMode();
|
834
|
+
}
|
835
|
+
|
836
|
+
/**
|
837
|
+
* Crop this image with rect
|
838
|
+
* @param {Object} rect crop rect
|
839
|
+
* @param {Number} rect.left left position
|
840
|
+
* @param {Number} rect.top top position
|
841
|
+
* @param {Number} rect.width width
|
842
|
+
* @param {Number} rect.height height
|
843
|
+
* @returns {Promise}
|
844
|
+
* @example
|
845
|
+
* imageEditor.crop(imageEditor.getCropzoneRect());
|
846
|
+
*/
|
847
|
+
crop(rect) {
|
848
|
+
const data = this._graphics.getCroppedImageData(rect);
|
849
|
+
if (!data) {
|
850
|
+
return Promise.reject(rejectMessages.invalidParameters);
|
851
|
+
}
|
852
|
+
|
853
|
+
return this.loadImageFromURL(data.url, data.imageName);
|
854
|
+
}
|
855
|
+
|
856
|
+
/**
|
857
|
+
* Get the cropping rect
|
858
|
+
* @returns {Object} {{left: number, top: number, width: number, height: number}} rect
|
859
|
+
*/
|
860
|
+
getCropzoneRect() {
|
861
|
+
return this._graphics.getCropzoneRect();
|
862
|
+
}
|
863
|
+
|
864
|
+
/**
|
865
|
+
* Set the cropping rect
|
866
|
+
* @param {number} [mode] crop rect mode [1, 1.5, 1.3333333333333333, 1.25, 1.7777777777777777]
|
867
|
+
*/
|
868
|
+
setCropzoneRect(mode) {
|
869
|
+
this._graphics.setCropzoneRect(mode);
|
870
|
+
}
|
871
|
+
|
872
|
+
/**
|
873
|
+
* Flip
|
874
|
+
* @returns {Promise}
|
875
|
+
* @param {string} type - 'flipX' or 'flipY' or 'reset'
|
876
|
+
* @returns {Promise<FlipStatus, ErrorMsg>}
|
877
|
+
* @private
|
878
|
+
*/
|
879
|
+
_flip(type) {
|
880
|
+
return this.execute(commands.FLIP_IMAGE, type);
|
881
|
+
}
|
882
|
+
|
883
|
+
/**
|
884
|
+
* Flip x
|
885
|
+
* @returns {Promise<FlipStatus, ErrorMsg>}
|
886
|
+
* @example
|
887
|
+
* imageEditor.flipX().then((status => {
|
888
|
+
* console.log('flipX: ', status.flipX);
|
889
|
+
* console.log('flipY: ', status.flipY);
|
890
|
+
* console.log('angle: ', status.angle);
|
891
|
+
* }).catch(message => {
|
892
|
+
* console.log('error: ', message);
|
893
|
+
* });
|
894
|
+
*/
|
895
|
+
flipX() {
|
896
|
+
return this._flip('flipX');
|
897
|
+
}
|
898
|
+
|
899
|
+
/**
|
900
|
+
* Flip y
|
901
|
+
* @returns {Promise<FlipStatus, ErrorMsg>}
|
902
|
+
* @example
|
903
|
+
* imageEditor.flipY().then(status => {
|
904
|
+
* console.log('flipX: ', status.flipX);
|
905
|
+
* console.log('flipY: ', status.flipY);
|
906
|
+
* console.log('angle: ', status.angle);
|
907
|
+
* }).catch(message => {
|
908
|
+
* console.log('error: ', message);
|
909
|
+
* });
|
910
|
+
*/
|
911
|
+
flipY() {
|
912
|
+
return this._flip('flipY');
|
913
|
+
}
|
914
|
+
|
915
|
+
/**
|
916
|
+
* Reset flip
|
917
|
+
* @returns {Promise<FlipStatus, ErrorMsg>}
|
918
|
+
* @example
|
919
|
+
* imageEditor.resetFlip().then(status => {
|
920
|
+
* console.log('flipX: ', status.flipX);
|
921
|
+
* console.log('flipY: ', status.flipY);
|
922
|
+
* console.log('angle: ', status.angle);
|
923
|
+
* }).catch(message => {
|
924
|
+
* console.log('error: ', message);
|
925
|
+
* });;
|
926
|
+
*/
|
927
|
+
resetFlip() {
|
928
|
+
return this._flip('reset');
|
929
|
+
}
|
930
|
+
|
931
|
+
/**
|
932
|
+
* @param {string} type - 'rotate' or 'setAngle'
|
933
|
+
* @param {number} angle - angle value (degree)
|
934
|
+
* @param {boolean} isSilent - is silent execution or not
|
935
|
+
* @returns {Promise<RotateStatus, ErrorMsg>}
|
936
|
+
* @private
|
937
|
+
*/
|
938
|
+
_rotate(type, angle, isSilent) {
|
939
|
+
let result = null;
|
940
|
+
|
941
|
+
if (isSilent) {
|
942
|
+
result = this.executeSilent(commands.ROTATE_IMAGE, type, angle);
|
943
|
+
} else {
|
944
|
+
result = this.execute(commands.ROTATE_IMAGE, type, angle);
|
945
|
+
}
|
946
|
+
|
947
|
+
return result;
|
948
|
+
}
|
949
|
+
|
950
|
+
/**
|
951
|
+
* Rotate image
|
952
|
+
* @returns {Promise}
|
953
|
+
* @param {number} angle - Additional angle to rotate image
|
954
|
+
* @param {boolean} isSilent - is silent execution or not
|
955
|
+
* @returns {Promise<RotateStatus, ErrorMsg>}
|
956
|
+
* @example
|
957
|
+
* imageEditor.rotate(10); // angle = 10
|
958
|
+
* imageEditor.rotate(10); // angle = 20
|
959
|
+
* imageEditor.rotate(5); // angle = 5
|
960
|
+
* imageEditor.rotate(-95); // angle = -90
|
961
|
+
* imageEditor.rotate(10).then(status => {
|
962
|
+
* console.log('angle: ', status.angle);
|
963
|
+
* })).catch(message => {
|
964
|
+
* console.log('error: ', message);
|
965
|
+
* });
|
966
|
+
*/
|
967
|
+
rotate(angle, isSilent) {
|
968
|
+
return this._rotate('rotate', angle, isSilent);
|
969
|
+
}
|
970
|
+
|
971
|
+
/**
|
972
|
+
* Set angle
|
973
|
+
* @param {number} angle - Angle of image
|
974
|
+
* @param {boolean} isSilent - is silent execution or not
|
975
|
+
* @returns {Promise<RotateStatus, ErrorMsg>}
|
976
|
+
* @example
|
977
|
+
* imageEditor.setAngle(10); // angle = 10
|
978
|
+
* imageEditor.rotate(10); // angle = 20
|
979
|
+
* imageEditor.setAngle(5); // angle = 5
|
980
|
+
* imageEditor.rotate(50); // angle = 55
|
981
|
+
* imageEditor.setAngle(-40); // angle = -40
|
982
|
+
* imageEditor.setAngle(10).then(status => {
|
983
|
+
* console.log('angle: ', status.angle);
|
984
|
+
* })).catch(message => {
|
985
|
+
* console.log('error: ', message);
|
986
|
+
* });
|
987
|
+
*/
|
988
|
+
setAngle(angle, isSilent) {
|
989
|
+
return this._rotate('setAngle', angle, isSilent);
|
990
|
+
}
|
991
|
+
|
992
|
+
/**
|
993
|
+
* Set drawing brush
|
994
|
+
* @param {Object} option brush option
|
995
|
+
* @param {Number} option.width width
|
996
|
+
* @param {String} option.color color like 'FFFFFF', 'rgba(0, 0, 0, 0.5)'
|
997
|
+
* @example
|
998
|
+
* imageEditor.startDrawingMode('FREE_DRAWING');
|
999
|
+
* imageEditor.setBrush({
|
1000
|
+
* width: 12,
|
1001
|
+
* color: 'rgba(0, 0, 0, 0.5)'
|
1002
|
+
* });
|
1003
|
+
* imageEditor.setBrush({
|
1004
|
+
* width: 8,
|
1005
|
+
* color: 'FFFFFF'
|
1006
|
+
* });
|
1007
|
+
*/
|
1008
|
+
setBrush(option) {
|
1009
|
+
this._graphics.setBrush(option);
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
/**
|
1013
|
+
* Set states of current drawing shape
|
1014
|
+
* @param {string} type - Shape type (ex: 'rect', 'circle', 'triangle')
|
1015
|
+
* @param {Object} [options] - Shape options
|
1016
|
+
* @param {(ShapeFillOption | string)} [options.fill] - {@link ShapeFillOption} or
|
1017
|
+
* Shape foreground color (ex: '#fff', 'transparent')
|
1018
|
+
* @param {string} [options.stoke] - Shape outline color
|
1019
|
+
* @param {number} [options.strokeWidth] - Shape outline width
|
1020
|
+
* @param {number} [options.width] - Width value (When type option is 'rect', this options can use)
|
1021
|
+
* @param {number} [options.height] - Height value (When type option is 'rect', this options can use)
|
1022
|
+
* @param {number} [options.rx] - Radius x value (When type option is 'circle', this options can use)
|
1023
|
+
* @param {number} [options.ry] - Radius y value (When type option is 'circle', this options can use)
|
1024
|
+
* @param {number} [options.isRegular] - Whether resizing shape has 1:1 ratio or not
|
1025
|
+
* @example
|
1026
|
+
* imageEditor.setDrawingShape('rect', {
|
1027
|
+
* fill: 'red',
|
1028
|
+
* width: 100,
|
1029
|
+
* height: 200
|
1030
|
+
* });
|
1031
|
+
* @example
|
1032
|
+
* imageEditor.setDrawingShape('rect', {
|
1033
|
+
* fill: {
|
1034
|
+
* type: 'filter',
|
1035
|
+
* filter: [{blur: 0.3}, {pixelate: 20}]
|
1036
|
+
* },
|
1037
|
+
* width: 100,
|
1038
|
+
* height: 200
|
1039
|
+
* });
|
1040
|
+
* @example
|
1041
|
+
* imageEditor.setDrawingShape('circle', {
|
1042
|
+
* fill: 'transparent',
|
1043
|
+
* stroke: 'blue',
|
1044
|
+
* strokeWidth: 3,
|
1045
|
+
* rx: 10,
|
1046
|
+
* ry: 100
|
1047
|
+
* });
|
1048
|
+
* @example
|
1049
|
+
* imageEditor.setDrawingShape('triangle', { // When resizing, the shape keep the 1:1 ratio
|
1050
|
+
* width: 1,
|
1051
|
+
* height: 1,
|
1052
|
+
* isRegular: true
|
1053
|
+
* });
|
1054
|
+
* @example
|
1055
|
+
* imageEditor.setDrawingShape('circle', { // When resizing, the shape keep the 1:1 ratio
|
1056
|
+
* rx: 10,
|
1057
|
+
* ry: 10,
|
1058
|
+
* isRegular: true
|
1059
|
+
* });
|
1060
|
+
*/
|
1061
|
+
setDrawingShape(type, options) {
|
1062
|
+
this._graphics.setDrawingShape(type, options);
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
setDrawingIcon(type, iconColor) {
|
1066
|
+
this._graphics.setIconStyle(type, iconColor);
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
/**
|
1070
|
+
* Add shape
|
1071
|
+
* @param {string} type - Shape type (ex: 'rect', 'circle', 'triangle')
|
1072
|
+
* @param {Object} options - Shape options
|
1073
|
+
* @param {(ShapeFillOption | string)} [options.fill] - {@link ShapeFillOption} or
|
1074
|
+
* Shape foreground color (ex: '#fff', 'transparent')
|
1075
|
+
* @param {string} [options.stroke] - Shape outline color
|
1076
|
+
* @param {number} [options.strokeWidth] - Shape outline width
|
1077
|
+
* @param {number} [options.width] - Width value (When type option is 'rect', this options can use)
|
1078
|
+
* @param {number} [options.height] - Height value (When type option is 'rect', this options can use)
|
1079
|
+
* @param {number} [options.rx] - Radius x value (When type option is 'circle', this options can use)
|
1080
|
+
* @param {number} [options.ry] - Radius y value (When type option is 'circle', this options can use)
|
1081
|
+
* @param {number} [options.left] - Shape x position
|
1082
|
+
* @param {number} [options.top] - Shape y position
|
1083
|
+
* @param {boolean} [options.isRegular] - Whether resizing shape has 1:1 ratio or not
|
1084
|
+
* @returns {Promise<ObjectProps, ErrorMsg>}
|
1085
|
+
* @example
|
1086
|
+
* imageEditor.addShape('rect', {
|
1087
|
+
* fill: 'red',
|
1088
|
+
* stroke: 'blue',
|
1089
|
+
* strokeWidth: 3,
|
1090
|
+
* width: 100,
|
1091
|
+
* height: 200,
|
1092
|
+
* left: 10,
|
1093
|
+
* top: 10,
|
1094
|
+
* isRegular: true
|
1095
|
+
* });
|
1096
|
+
* @example
|
1097
|
+
* imageEditor.addShape('circle', {
|
1098
|
+
* fill: 'red',
|
1099
|
+
* stroke: 'blue',
|
1100
|
+
* strokeWidth: 3,
|
1101
|
+
* rx: 10,
|
1102
|
+
* ry: 100,
|
1103
|
+
* isRegular: false
|
1104
|
+
* }).then(objectProps => {
|
1105
|
+
* console.log(objectProps.id);
|
1106
|
+
* });
|
1107
|
+
* @example
|
1108
|
+
* imageEditor.addShape('rect', {
|
1109
|
+
* fill: {
|
1110
|
+
* type: 'filter',
|
1111
|
+
* filter: [{blur: 0.3}, {pixelate: 20}]
|
1112
|
+
* },
|
1113
|
+
* stroke: 'blue',
|
1114
|
+
* strokeWidth: 3,
|
1115
|
+
* rx: 10,
|
1116
|
+
* ry: 100,
|
1117
|
+
* isRegular: false
|
1118
|
+
* }).then(objectProps => {
|
1119
|
+
* console.log(objectProps.id);
|
1120
|
+
* });
|
1121
|
+
*/
|
1122
|
+
addShape(type, options) {
|
1123
|
+
options = options || {};
|
1124
|
+
|
1125
|
+
this._setPositions(options);
|
1126
|
+
|
1127
|
+
return this.execute(commands.ADD_SHAPE, type, options);
|
1128
|
+
}
|
1129
|
+
|
1130
|
+
/**
|
1131
|
+
* Change shape
|
1132
|
+
* @param {number} id - object id
|
1133
|
+
* @param {Object} options - Shape options
|
1134
|
+
* @param {(ShapeFillOption | string)} [options.fill] - {@link ShapeFillOption} or
|
1135
|
+
* Shape foreground color (ex: '#fff', 'transparent')
|
1136
|
+
* @param {string} [options.stroke] - Shape outline color
|
1137
|
+
* @param {number} [options.strokeWidth] - Shape outline width
|
1138
|
+
* @param {number} [options.width] - Width value (When type option is 'rect', this options can use)
|
1139
|
+
* @param {number} [options.height] - Height value (When type option is 'rect', this options can use)
|
1140
|
+
* @param {number} [options.rx] - Radius x value (When type option is 'circle', this options can use)
|
1141
|
+
* @param {number} [options.ry] - Radius y value (When type option is 'circle', this options can use)
|
1142
|
+
* @param {boolean} [options.isRegular] - Whether resizing shape has 1:1 ratio or not
|
1143
|
+
* @param {boolean} isSilent - is silent execution or not
|
1144
|
+
* @returns {Promise}
|
1145
|
+
* @example
|
1146
|
+
* // call after selecting shape object on canvas
|
1147
|
+
* imageEditor.changeShape(id, { // change rectagle or triangle
|
1148
|
+
* fill: 'red',
|
1149
|
+
* stroke: 'blue',
|
1150
|
+
* strokeWidth: 3,
|
1151
|
+
* width: 100,
|
1152
|
+
* height: 200
|
1153
|
+
* });
|
1154
|
+
* @example
|
1155
|
+
* // call after selecting shape object on canvas
|
1156
|
+
* imageEditor.changeShape(id, { // change circle
|
1157
|
+
* fill: 'red',
|
1158
|
+
* stroke: 'blue',
|
1159
|
+
* strokeWidth: 3,
|
1160
|
+
* rx: 10,
|
1161
|
+
* ry: 100
|
1162
|
+
* });
|
1163
|
+
*/
|
1164
|
+
changeShape(id, options, isSilent) {
|
1165
|
+
const executeMethodName = isSilent ? 'executeSilent' : 'execute';
|
1166
|
+
|
1167
|
+
return this[executeMethodName](commands.CHANGE_SHAPE, id, options);
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
/**
|
1171
|
+
* Add text on image
|
1172
|
+
* @param {string} text - Initial input text
|
1173
|
+
* @param {Object} [options] Options for generating text
|
1174
|
+
* @param {Object} [options.styles] Initial styles
|
1175
|
+
* @param {string} [options.styles.fill] Color
|
1176
|
+
* @param {string} [options.styles.fontFamily] Font type for text
|
1177
|
+
* @param {number} [options.styles.fontSize] Size
|
1178
|
+
* @param {string} [options.styles.fontStyle] Type of inclination (normal / italic)
|
1179
|
+
* @param {string} [options.styles.fontWeight] Type of thicker or thinner looking (normal / bold)
|
1180
|
+
* @param {string} [options.styles.textAlign] Type of text align (left / center / right)
|
1181
|
+
* @param {string} [options.styles.textDecoration] Type of line (underline / line-through / overline)
|
1182
|
+
* @param {{x: number, y: number}} [options.position] - Initial position
|
1183
|
+
* @param {boolean} [options.autofocus] - text autofocus, default is true
|
1184
|
+
* @returns {Promise}
|
1185
|
+
* @example
|
1186
|
+
* imageEditor.addText('init text');
|
1187
|
+
* @example
|
1188
|
+
* imageEditor.addText('init text', {
|
1189
|
+
* styles: {
|
1190
|
+
* fill: '#000',
|
1191
|
+
* fontSize: 20,
|
1192
|
+
* fontWeight: 'bold'
|
1193
|
+
* },
|
1194
|
+
* position: {
|
1195
|
+
* x: 10,
|
1196
|
+
* y: 10
|
1197
|
+
* }
|
1198
|
+
* }).then(objectProps => {
|
1199
|
+
* console.log(objectProps.id);
|
1200
|
+
* });
|
1201
|
+
*/
|
1202
|
+
addText(text, options) {
|
1203
|
+
text = text || '';
|
1204
|
+
options = options || {};
|
1205
|
+
|
1206
|
+
return this.execute(commands.ADD_TEXT, text, options);
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
/**
|
1210
|
+
* Change contents of selected text object on image
|
1211
|
+
* @param {number} id - object id
|
1212
|
+
* @param {string} text - Changing text
|
1213
|
+
* @returns {Promise<ObjectProps, ErrorMsg>}
|
1214
|
+
* @example
|
1215
|
+
* imageEditor.changeText(id, 'change text');
|
1216
|
+
*/
|
1217
|
+
changeText(id, text) {
|
1218
|
+
text = text || '';
|
1219
|
+
|
1220
|
+
return this.execute(commands.CHANGE_TEXT, id, text);
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
/**
|
1224
|
+
* Set style
|
1225
|
+
* @param {number} id - object id
|
1226
|
+
* @param {Object} styleObj - text styles
|
1227
|
+
* @param {string} [styleObj.fill] Color
|
1228
|
+
* @param {string} [styleObj.fontFamily] Font type for text
|
1229
|
+
* @param {number} [styleObj.fontSize] Size
|
1230
|
+
* @param {string} [styleObj.fontStyle] Type of inclination (normal / italic)
|
1231
|
+
* @param {string} [styleObj.fontWeight] Type of thicker or thinner looking (normal / bold)
|
1232
|
+
* @param {string} [styleObj.textAlign] Type of text align (left / center / right)
|
1233
|
+
* @param {string} [styleObj.textDecoration] Type of line (underline / line-through / overline)
|
1234
|
+
* @param {boolean} isSilent - is silent execution or not
|
1235
|
+
* @returns {Promise}
|
1236
|
+
* @example
|
1237
|
+
* imageEditor.changeTextStyle(id, {
|
1238
|
+
* fontStyle: 'italic'
|
1239
|
+
* });
|
1240
|
+
*/
|
1241
|
+
changeTextStyle(id, styleObj, isSilent) {
|
1242
|
+
const executeMethodName = isSilent ? 'executeSilent' : 'execute';
|
1243
|
+
|
1244
|
+
return this[executeMethodName](commands.CHANGE_TEXT_STYLE, id, styleObj);
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
/**
|
1248
|
+
* change text mode
|
1249
|
+
* @param {string} type - change type
|
1250
|
+
* @private
|
1251
|
+
*/
|
1252
|
+
_changeActivateMode(type) {
|
1253
|
+
if (type !== 'ICON' && this.getDrawingMode() !== type) {
|
1254
|
+
this.startDrawingMode(type);
|
1255
|
+
}
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
/**
|
1259
|
+
* 'textChanged' event handler
|
1260
|
+
* @param {Object} target - changed text object
|
1261
|
+
* @private
|
1262
|
+
*/
|
1263
|
+
_onTextChanged(target) {
|
1264
|
+
this.fire(events.TEXT_CHANGED, target);
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
/**
|
1268
|
+
* 'iconCreateResize' event handler
|
1269
|
+
* @param {Object} originPointer origin pointer
|
1270
|
+
* @param {Number} originPointer.x x position
|
1271
|
+
* @param {Number} originPointer.y y position
|
1272
|
+
* @private
|
1273
|
+
*/
|
1274
|
+
_onIconCreateResize(originPointer) {
|
1275
|
+
this.fire(events.ICON_CREATE_RESIZE, originPointer);
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
/**
|
1279
|
+
* 'iconCreateEnd' event handler
|
1280
|
+
* @param {Object} originPointer origin pointer
|
1281
|
+
* @param {Number} originPointer.x x position
|
1282
|
+
* @param {Number} originPointer.y y position
|
1283
|
+
* @private
|
1284
|
+
*/
|
1285
|
+
_onIconCreateEnd(originPointer) {
|
1286
|
+
this.fire(events.ICON_CREATE_END, originPointer);
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
/**
|
1290
|
+
* 'textEditing' event handler
|
1291
|
+
* @private
|
1292
|
+
*/
|
1293
|
+
_onTextEditing() {
|
1294
|
+
/**
|
1295
|
+
* The event which starts to edit text object
|
1296
|
+
* @event ImageEditor#textEditing
|
1297
|
+
* @example
|
1298
|
+
* imageEditor.on('textEditing', function() {
|
1299
|
+
* console.log('text editing');
|
1300
|
+
* });
|
1301
|
+
*/
|
1302
|
+
|
1303
|
+
this.fire(events.TEXT_EDITING);
|
1304
|
+
}
|
1305
|
+
|
1306
|
+
/**
|
1307
|
+
* Mousedown event handler in case of 'TEXT' drawing mode
|
1308
|
+
* @param {fabric.Event} event - Current mousedown event object
|
1309
|
+
* @private
|
1310
|
+
*/
|
1311
|
+
_onAddText(event) {
|
1312
|
+
/**
|
1313
|
+
* The event when 'TEXT' drawing mode is enabled and click non-object area.
|
1314
|
+
* @event ImageEditor#addText
|
1315
|
+
* @param {Object} pos
|
1316
|
+
* @param {Object} pos.originPosition - Current position on origin canvas
|
1317
|
+
* @param {Number} pos.originPosition.x - x
|
1318
|
+
* @param {Number} pos.originPosition.y - y
|
1319
|
+
* @param {Object} pos.clientPosition - Current position on client area
|
1320
|
+
* @param {Number} pos.clientPosition.x - x
|
1321
|
+
* @param {Number} pos.clientPosition.y - y
|
1322
|
+
* @example
|
1323
|
+
* imageEditor.on('addText', function(pos) {
|
1324
|
+
* console.log('text position on canvas: ' + pos.originPosition);
|
1325
|
+
* console.log('text position on brwoser: ' + pos.clientPosition);
|
1326
|
+
* });
|
1327
|
+
*/
|
1328
|
+
|
1329
|
+
this.fire(events.ADD_TEXT, {
|
1330
|
+
originPosition: event.originPosition,
|
1331
|
+
clientPosition: event.clientPosition,
|
1332
|
+
});
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
/**
|
1336
|
+
* 'addObject' event handler
|
1337
|
+
* @param {Object} objectProps added object properties
|
1338
|
+
* @private
|
1339
|
+
*/
|
1340
|
+
_onAddObject(objectProps) {
|
1341
|
+
const obj = this._graphics.getObject(objectProps.id);
|
1342
|
+
this._invoker.fire(events.EXECUTE_COMMAND, getObjectType(obj.type));
|
1343
|
+
this._pushAddObjectCommand(obj);
|
1344
|
+
}
|
1345
|
+
|
1346
|
+
/**
|
1347
|
+
* 'objectAdded' event handler
|
1348
|
+
* @param {Object} objectProps added object properties
|
1349
|
+
* @private
|
1350
|
+
*/
|
1351
|
+
_onObjectAdded(objectProps) {
|
1352
|
+
/**
|
1353
|
+
* The event when object added
|
1354
|
+
* @event ImageEditor#objectAdded
|
1355
|
+
* @param {ObjectProps} props - object properties
|
1356
|
+
* @example
|
1357
|
+
* imageEditor.on('objectAdded', function(props) {
|
1358
|
+
* console.log(props);
|
1359
|
+
* });
|
1360
|
+
*/
|
1361
|
+
this.fire(OBJECT_ADDED, objectProps);
|
1362
|
+
|
1363
|
+
/**
|
1364
|
+
* The event when object added (deprecated)
|
1365
|
+
* @event ImageEditor#addObjectAfter
|
1366
|
+
* @param {ObjectProps} props - object properties
|
1367
|
+
* @deprecated
|
1368
|
+
*/
|
1369
|
+
this.fire(ADD_OBJECT_AFTER, objectProps);
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
/**
|
1373
|
+
* 'objectModified' event handler
|
1374
|
+
* @param {fabric.Object} obj - selection object
|
1375
|
+
* @private
|
1376
|
+
*/
|
1377
|
+
_onObjectModified(obj) {
|
1378
|
+
if (obj.type !== OBJ_TYPE.CROPZONE) {
|
1379
|
+
this._invoker.fire(events.EXECUTE_COMMAND, getObjectType(obj.type));
|
1380
|
+
this._pushModifyObjectCommand(obj);
|
1381
|
+
}
|
1382
|
+
}
|
1383
|
+
|
1384
|
+
/**
|
1385
|
+
* 'selectionCleared' event handler
|
1386
|
+
* @private
|
1387
|
+
*/
|
1388
|
+
_selectionCleared() {
|
1389
|
+
this.fire(SELECTION_CLEARED);
|
1390
|
+
}
|
1391
|
+
|
1392
|
+
/**
|
1393
|
+
* 'selectionCreated' event handler
|
1394
|
+
* @param {Object} eventTarget - Fabric object
|
1395
|
+
* @private
|
1396
|
+
*/
|
1397
|
+
_selectionCreated(eventTarget) {
|
1398
|
+
this.fire(SELECTION_CREATED, eventTarget);
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
/**
|
1402
|
+
* Register custom icons
|
1403
|
+
* @param {{iconType: string, pathValue: string}} infos - Infos to register icons
|
1404
|
+
* @example
|
1405
|
+
* imageEditor.registerIcons({
|
1406
|
+
* customIcon: 'M 0 0 L 20 20 L 10 10 Z',
|
1407
|
+
* customArrow: 'M 60 0 L 120 60 H 90 L 75 45 V 180 H 45 V 45 L 30 60 H 0 Z'
|
1408
|
+
* });
|
1409
|
+
*/
|
1410
|
+
registerIcons(infos) {
|
1411
|
+
this._graphics.registerPaths(infos);
|
1412
|
+
}
|
1413
|
+
|
1414
|
+
/**
|
1415
|
+
* Change canvas cursor type
|
1416
|
+
* @param {string} cursorType - cursor type
|
1417
|
+
* @example
|
1418
|
+
* imageEditor.changeCursor('crosshair');
|
1419
|
+
*/
|
1420
|
+
changeCursor(cursorType) {
|
1421
|
+
this._graphics.changeCursor(cursorType);
|
1422
|
+
}
|
1423
|
+
|
1424
|
+
/**
|
1425
|
+
* Add icon on canvas
|
1426
|
+
* @param {string} type - Icon type ('arrow', 'cancel', custom icon name)
|
1427
|
+
* @param {Object} options - Icon options
|
1428
|
+
* @param {string} [options.fill] - Icon foreground color
|
1429
|
+
* @param {number} [options.left] - Icon x position
|
1430
|
+
* @param {number} [options.top] - Icon y position
|
1431
|
+
* @returns {Promise<ObjectProps, ErrorMsg>}
|
1432
|
+
* @example
|
1433
|
+
* imageEditor.addIcon('arrow'); // The position is center on canvas
|
1434
|
+
* @example
|
1435
|
+
* imageEditor.addIcon('arrow', {
|
1436
|
+
* left: 100,
|
1437
|
+
* top: 100
|
1438
|
+
* }).then(objectProps => {
|
1439
|
+
* console.log(objectProps.id);
|
1440
|
+
* });
|
1441
|
+
*/
|
1442
|
+
addIcon(type, options) {
|
1443
|
+
options = options || {};
|
1444
|
+
|
1445
|
+
this._setPositions(options);
|
1446
|
+
|
1447
|
+
return this.execute(commands.ADD_ICON, type, options);
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
/**
|
1451
|
+
* Change icon color
|
1452
|
+
* @param {number} id - object id
|
1453
|
+
* @param {string} color - Color for icon
|
1454
|
+
* @returns {Promise}
|
1455
|
+
* @example
|
1456
|
+
* imageEditor.changeIconColor(id, '#000000');
|
1457
|
+
*/
|
1458
|
+
changeIconColor(id, color) {
|
1459
|
+
return this.execute(commands.CHANGE_ICON_COLOR, id, color);
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
/**
|
1463
|
+
* Remove an object or group by id
|
1464
|
+
* @param {number} id - object id
|
1465
|
+
* @returns {Promise}
|
1466
|
+
* @example
|
1467
|
+
* imageEditor.removeObject(id);
|
1468
|
+
*/
|
1469
|
+
removeObject(id) {
|
1470
|
+
const { type } = this._graphics.getObject(id);
|
1471
|
+
|
1472
|
+
return this.execute(commands.REMOVE_OBJECT, id, getObjectType(type));
|
1473
|
+
}
|
1474
|
+
|
1475
|
+
/**
|
1476
|
+
* Whether it has the filter or not
|
1477
|
+
* @param {string} type - Filter type
|
1478
|
+
* @returns {boolean} true if it has the filter
|
1479
|
+
*/
|
1480
|
+
hasFilter(type) {
|
1481
|
+
return this._graphics.hasFilter(type);
|
1482
|
+
}
|
1483
|
+
|
1484
|
+
/**
|
1485
|
+
* Remove filter on canvas image
|
1486
|
+
* @param {string} type - Filter type
|
1487
|
+
* @returns {Promise<FilterResult, ErrorMsg>}
|
1488
|
+
* @example
|
1489
|
+
* imageEditor.removeFilter('Grayscale').then(obj => {
|
1490
|
+
* console.log('filterType: ', obj.type);
|
1491
|
+
* console.log('actType: ', obj.action);
|
1492
|
+
* }).catch(message => {
|
1493
|
+
* console.log('error: ', message);
|
1494
|
+
* });
|
1495
|
+
*/
|
1496
|
+
removeFilter(type) {
|
1497
|
+
return this.execute(commands.REMOVE_FILTER, type);
|
1498
|
+
}
|
1499
|
+
|
1500
|
+
/**
|
1501
|
+
* Apply filter on canvas image
|
1502
|
+
* @param {string} type - Filter type
|
1503
|
+
* @param {object} options - Options to apply filter
|
1504
|
+
* @param {boolean} isSilent - is silent execution or not
|
1505
|
+
* @returns {Promise<FilterResult, ErrorMsg>}
|
1506
|
+
* @example
|
1507
|
+
* imageEditor.applyFilter('Grayscale');
|
1508
|
+
* @example
|
1509
|
+
* imageEditor.applyFilter('mask', {maskObjId: id}).then(obj => {
|
1510
|
+
* console.log('filterType: ', obj.type);
|
1511
|
+
* console.log('actType: ', obj.action);
|
1512
|
+
* }).catch(message => {
|
1513
|
+
* console.log('error: ', message);
|
1514
|
+
* });;
|
1515
|
+
*/
|
1516
|
+
applyFilter(type, options, isSilent) {
|
1517
|
+
const executeMethodName = isSilent ? 'executeSilent' : 'execute';
|
1518
|
+
|
1519
|
+
return this[executeMethodName](commands.APPLY_FILTER, type, options);
|
1520
|
+
}
|
1521
|
+
|
1522
|
+
/**
|
1523
|
+
* Get data url
|
1524
|
+
* @param {Object} options - options for toDataURL
|
1525
|
+
* @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
|
1526
|
+
* @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
|
1527
|
+
* @param {Number} [options.multiplier=1] Multiplier to scale by
|
1528
|
+
* @param {Number} [options.left] Cropping left offset. Introduced in fabric v1.2.14
|
1529
|
+
* @param {Number} [options.top] Cropping top offset. Introduced in fabric v1.2.14
|
1530
|
+
* @param {Number} [options.width] Cropping width. Introduced in fabric v1.2.14
|
1531
|
+
* @param {Number} [options.height] Cropping height. Introduced in fabric v1.2.14
|
1532
|
+
* @returns {string} A DOMString containing the requested data URI
|
1533
|
+
* @example
|
1534
|
+
* imgEl.src = imageEditor.toDataURL();
|
1535
|
+
*
|
1536
|
+
* imageEditor.loadImageFromURL(imageEditor.toDataURL(), 'FilterImage').then(() => {
|
1537
|
+
* imageEditor.addImageObject(imgUrl);
|
1538
|
+
* });
|
1539
|
+
*/
|
1540
|
+
toDataURL(options) {
|
1541
|
+
return this._graphics.toDataURL(options);
|
1542
|
+
}
|
1543
|
+
|
1544
|
+
/**
|
1545
|
+
* Get image name
|
1546
|
+
* @returns {string} image name
|
1547
|
+
* @example
|
1548
|
+
* console.log(imageEditor.getImageName());
|
1549
|
+
*/
|
1550
|
+
getImageName() {
|
1551
|
+
return this._graphics.getImageName();
|
1552
|
+
}
|
1553
|
+
|
1554
|
+
/**
|
1555
|
+
* Clear undoStack
|
1556
|
+
* @example
|
1557
|
+
* imageEditor.clearUndoStack();
|
1558
|
+
*/
|
1559
|
+
clearUndoStack() {
|
1560
|
+
this._invoker.clearUndoStack();
|
1561
|
+
}
|
1562
|
+
|
1563
|
+
/**
|
1564
|
+
* Clear redoStack
|
1565
|
+
* @example
|
1566
|
+
* imageEditor.clearRedoStack();
|
1567
|
+
*/
|
1568
|
+
clearRedoStack() {
|
1569
|
+
this._invoker.clearRedoStack();
|
1570
|
+
}
|
1571
|
+
|
1572
|
+
/**
|
1573
|
+
* Whehter the undo stack is empty or not
|
1574
|
+
* @returns {boolean}
|
1575
|
+
* imageEditor.isEmptyUndoStack();
|
1576
|
+
*/
|
1577
|
+
isEmptyUndoStack() {
|
1578
|
+
return this._invoker.isEmptyUndoStack();
|
1579
|
+
}
|
1580
|
+
|
1581
|
+
/**
|
1582
|
+
* Whehter the redo stack is empty or not
|
1583
|
+
* @returns {boolean}
|
1584
|
+
* imageEditor.isEmptyRedoStack();
|
1585
|
+
*/
|
1586
|
+
isEmptyRedoStack() {
|
1587
|
+
return this._invoker.isEmptyRedoStack();
|
1588
|
+
}
|
1589
|
+
|
1590
|
+
/**
|
1591
|
+
* Resize canvas dimension
|
1592
|
+
* @param {{width: number, height: number}} dimension - Max width & height
|
1593
|
+
* @returns {Promise}
|
1594
|
+
*/
|
1595
|
+
resizeCanvasDimension(dimension) {
|
1596
|
+
if (!dimension) {
|
1597
|
+
return Promise.reject(rejectMessages.invalidParameters);
|
1598
|
+
}
|
1599
|
+
|
1600
|
+
return this.execute(commands.RESIZE_CANVAS_DIMENSION, dimension);
|
1601
|
+
}
|
1602
|
+
|
1603
|
+
/**
|
1604
|
+
* Destroy
|
1605
|
+
*/
|
1606
|
+
destroy() {
|
1607
|
+
this.stopDrawingMode();
|
1608
|
+
this._detachDomEvents();
|
1609
|
+
this._graphics.destroy();
|
1610
|
+
this._graphics = null;
|
1611
|
+
|
1612
|
+
if (this.ui) {
|
1613
|
+
this._detachColorPickerInputBoxEvents();
|
1614
|
+
this.ui.destroy();
|
1615
|
+
}
|
1616
|
+
|
1617
|
+
forEach(
|
1618
|
+
this,
|
1619
|
+
(value, key) => {
|
1620
|
+
this[key] = null;
|
1621
|
+
},
|
1622
|
+
this
|
1623
|
+
);
|
1624
|
+
}
|
1625
|
+
|
1626
|
+
/**
|
1627
|
+
* Set position
|
1628
|
+
* @param {Object} options - Position options (left or top)
|
1629
|
+
* @private
|
1630
|
+
*/
|
1631
|
+
_setPositions(options) {
|
1632
|
+
const centerPosition = this._graphics.getCenter();
|
1633
|
+
|
1634
|
+
if (isUndefined(options.left)) {
|
1635
|
+
options.left = centerPosition.left;
|
1636
|
+
}
|
1637
|
+
|
1638
|
+
if (isUndefined(options.top)) {
|
1639
|
+
options.top = centerPosition.top;
|
1640
|
+
}
|
1641
|
+
}
|
1642
|
+
|
1643
|
+
/**
|
1644
|
+
* Set properties of active object
|
1645
|
+
* @param {number} id - object id
|
1646
|
+
* @param {Object} keyValue - key & value
|
1647
|
+
* @returns {Promise}
|
1648
|
+
* @example
|
1649
|
+
* imageEditor.setObjectProperties(id, {
|
1650
|
+
* left:100,
|
1651
|
+
* top:100,
|
1652
|
+
* width: 200,
|
1653
|
+
* height: 200,
|
1654
|
+
* opacity: 0.5
|
1655
|
+
* });
|
1656
|
+
*/
|
1657
|
+
setObjectProperties(id, keyValue) {
|
1658
|
+
return this.execute(commands.SET_OBJECT_PROPERTIES, id, keyValue);
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
/**
|
1662
|
+
* Set properties of active object, Do not leave an invoke history.
|
1663
|
+
* @param {number} id - object id
|
1664
|
+
* @param {Object} keyValue - key & value
|
1665
|
+
* @example
|
1666
|
+
* imageEditor.setObjectPropertiesQuietly(id, {
|
1667
|
+
* left:100,
|
1668
|
+
* top:100,
|
1669
|
+
* width: 200,
|
1670
|
+
* height: 200,
|
1671
|
+
* opacity: 0.5
|
1672
|
+
* });
|
1673
|
+
*/
|
1674
|
+
setObjectPropertiesQuietly(id, keyValue) {
|
1675
|
+
this._graphics.setObjectProperties(id, keyValue);
|
1676
|
+
}
|
1677
|
+
|
1678
|
+
/**
|
1679
|
+
* Get properties of active object corresponding key
|
1680
|
+
* @param {number} id - object id
|
1681
|
+
* @param {Array<string>|ObjectProps|string} keys - property's key
|
1682
|
+
* @returns {ObjectProps} properties if id is valid or null
|
1683
|
+
* @example
|
1684
|
+
* var props = imageEditor.getObjectProperties(id, 'left');
|
1685
|
+
* console.log(props);
|
1686
|
+
* @example
|
1687
|
+
* var props = imageEditor.getObjectProperties(id, ['left', 'top', 'width', 'height']);
|
1688
|
+
* console.log(props);
|
1689
|
+
* @example
|
1690
|
+
* var props = imageEditor.getObjectProperties(id, {
|
1691
|
+
* left: null,
|
1692
|
+
* top: null,
|
1693
|
+
* width: null,
|
1694
|
+
* height: null,
|
1695
|
+
* opacity: null
|
1696
|
+
* });
|
1697
|
+
* console.log(props);
|
1698
|
+
*/
|
1699
|
+
getObjectProperties(id, keys) {
|
1700
|
+
const object = this._graphics.getObject(id);
|
1701
|
+
if (!object) {
|
1702
|
+
return null;
|
1703
|
+
}
|
1704
|
+
|
1705
|
+
return this._graphics.getObjectProperties(id, keys);
|
1706
|
+
}
|
1707
|
+
|
1708
|
+
/**
|
1709
|
+
* Get the canvas size
|
1710
|
+
* @returns {Object} {{width: number, height: number}} canvas size
|
1711
|
+
* @example
|
1712
|
+
* var canvasSize = imageEditor.getCanvasSize();
|
1713
|
+
* console.log(canvasSize.width);
|
1714
|
+
* console.height(canvasSize.height);
|
1715
|
+
*/
|
1716
|
+
getCanvasSize() {
|
1717
|
+
return this._graphics.getCanvasSize();
|
1718
|
+
}
|
1719
|
+
|
1720
|
+
/**
|
1721
|
+
* Get object position by originX, originY
|
1722
|
+
* @param {number} id - object id
|
1723
|
+
* @param {string} originX - can be 'left', 'center', 'right'
|
1724
|
+
* @param {string} originY - can be 'top', 'center', 'bottom'
|
1725
|
+
* @returns {Object} {{x:number, y: number}} position by origin if id is valid, or null
|
1726
|
+
* @example
|
1727
|
+
* var position = imageEditor.getObjectPosition(id, 'left', 'top');
|
1728
|
+
* console.log(position);
|
1729
|
+
*/
|
1730
|
+
getObjectPosition(id, originX, originY) {
|
1731
|
+
return this._graphics.getObjectPosition(id, originX, originY);
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
/**
|
1735
|
+
* Set object position by originX, originY
|
1736
|
+
* @param {number} id - object id
|
1737
|
+
* @param {Object} posInfo - position object
|
1738
|
+
* @param {number} posInfo.x - x position
|
1739
|
+
* @param {number} posInfo.y - y position
|
1740
|
+
* @param {string} posInfo.originX - can be 'left', 'center', 'right'
|
1741
|
+
* @param {string} posInfo.originY - can be 'top', 'center', 'bottom'
|
1742
|
+
* @returns {Promise}
|
1743
|
+
* @example
|
1744
|
+
* // align the object to 'left', 'top'
|
1745
|
+
* imageEditor.setObjectPosition(id, {
|
1746
|
+
* x: 0,
|
1747
|
+
* y: 0,
|
1748
|
+
* originX: 'left',
|
1749
|
+
* originY: 'top'
|
1750
|
+
* });
|
1751
|
+
* @example
|
1752
|
+
* // align the object to 'right', 'top'
|
1753
|
+
* var canvasSize = imageEditor.getCanvasSize();
|
1754
|
+
* imageEditor.setObjectPosition(id, {
|
1755
|
+
* x: canvasSize.width,
|
1756
|
+
* y: 0,
|
1757
|
+
* originX: 'right',
|
1758
|
+
* originY: 'top'
|
1759
|
+
* });
|
1760
|
+
* @example
|
1761
|
+
* // align the object to 'left', 'bottom'
|
1762
|
+
* var canvasSize = imageEditor.getCanvasSize();
|
1763
|
+
* imageEditor.setObjectPosition(id, {
|
1764
|
+
* x: 0,
|
1765
|
+
* y: canvasSize.height,
|
1766
|
+
* originX: 'left',
|
1767
|
+
* originY: 'bottom'
|
1768
|
+
* });
|
1769
|
+
* @example
|
1770
|
+
* // align the object to 'right', 'bottom'
|
1771
|
+
* var canvasSize = imageEditor.getCanvasSize();
|
1772
|
+
* imageEditor.setObjectPosition(id, {
|
1773
|
+
* x: canvasSize.width,
|
1774
|
+
* y: canvasSize.height,
|
1775
|
+
* originX: 'right',
|
1776
|
+
* originY: 'bottom'
|
1777
|
+
* });
|
1778
|
+
*/
|
1779
|
+
setObjectPosition(id, posInfo) {
|
1780
|
+
return this.execute(commands.SET_OBJECT_POSITION, id, posInfo);
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
/**
|
1784
|
+
* @param {object} dimensions - Image Dimensions
|
1785
|
+
* @returns {Promise<ErrorMsg>}
|
1786
|
+
*/
|
1787
|
+
resize(dimensions) {
|
1788
|
+
return this.execute(commands.RESIZE_IMAGE, dimensions);
|
1789
|
+
}
|
1790
|
+
}
|
1791
|
+
|
1792
|
+
action.mixin(ImageEditor);
|
1793
|
+
CustomEvents.mixin(ImageEditor);
|
1794
|
+
|
1795
|
+
export default ImageEditor;
|