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.
Files changed (374) hide show
  1. package/README.md +193 -0
  2. package/dist/svg/icon-a.svg +376 -0
  3. package/dist/svg/icon-b.svg +369 -0
  4. package/dist/svg/icon-c.svg +369 -0
  5. package/dist/svg/icon-d.svg +369 -0
  6. package/dist/tui-image-editor.css +6 -0
  7. package/dist/tui-image-editor.js +62329 -0
  8. package/dist/tui-image-editor.min.css +5 -0
  9. package/dist/tui-image-editor.min.js +15 -0
  10. package/index.d.ts +334 -0
  11. package/package.json +52 -0
  12. package/src/css/buttons.styl +102 -0
  13. package/src/css/checkbox.styl +86 -0
  14. package/src/css/colorpicker.styl +98 -0
  15. package/src/css/gridtable.styl +45 -0
  16. package/src/css/icon.styl +44 -0
  17. package/src/css/index.styl +17 -0
  18. package/src/css/main.styl +163 -0
  19. package/src/css/position.styl +309 -0
  20. package/src/css/range.styl +91 -0
  21. package/src/css/submenu.styl +168 -0
  22. package/src/index.js +29 -0
  23. package/src/js/action.js +686 -0
  24. package/src/js/command/addIcon.js +42 -0
  25. package/src/js/command/addImageObject.js +34 -0
  26. package/src/js/command/addObject.js +43 -0
  27. package/src/js/command/addShape.js +51 -0
  28. package/src/js/command/addText.js +73 -0
  29. package/src/js/command/applyFilter.js +95 -0
  30. package/src/js/command/changeIconColor.js +48 -0
  31. package/src/js/command/changeSelection.js +31 -0
  32. package/src/js/command/changeShape.js +84 -0
  33. package/src/js/command/changeText.js +44 -0
  34. package/src/js/command/changeTextStyle.js +80 -0
  35. package/src/js/command/clearObjects.js +33 -0
  36. package/src/js/command/flip.js +36 -0
  37. package/src/js/command/loadImage.js +58 -0
  38. package/src/js/command/removeFilter.js +38 -0
  39. package/src/js/command/removeObject.js +37 -0
  40. package/src/js/command/resize.js +41 -0
  41. package/src/js/command/resizeCanvasDimension.js +40 -0
  42. package/src/js/command/rotate.js +64 -0
  43. package/src/js/command/setObjectPosition.js +50 -0
  44. package/src/js/command/setObjectProperties.js +55 -0
  45. package/src/js/component/cropper.js +407 -0
  46. package/src/js/component/filter.js +229 -0
  47. package/src/js/component/flip.js +146 -0
  48. package/src/js/component/freeDrawing.js +144 -0
  49. package/src/js/component/icon.js +246 -0
  50. package/src/js/component/imageLoader.js +84 -0
  51. package/src/js/component/line.js +205 -0
  52. package/src/js/component/resize.js +103 -0
  53. package/src/js/component/rotation.js +91 -0
  54. package/src/js/component/shape.js +601 -0
  55. package/src/js/component/text.js +572 -0
  56. package/src/js/component/zoom.js +708 -0
  57. package/src/js/consts.js +404 -0
  58. package/src/js/drawingMode/cropper.js +35 -0
  59. package/src/js/drawingMode/freeDrawing.js +36 -0
  60. package/src/js/drawingMode/icon.js +35 -0
  61. package/src/js/drawingMode/lineDrawing.js +36 -0
  62. package/src/js/drawingMode/resize.js +35 -0
  63. package/src/js/drawingMode/shape.js +35 -0
  64. package/src/js/drawingMode/text.js +35 -0
  65. package/src/js/drawingMode/zoom.js +37 -0
  66. package/src/js/extension/arrowLine.js +172 -0
  67. package/src/js/extension/blur.js +29 -0
  68. package/src/js/extension/colorFilter.js +104 -0
  69. package/src/js/extension/cropzone.js +568 -0
  70. package/src/js/extension/emboss.js +29 -0
  71. package/src/js/extension/mask.js +90 -0
  72. package/src/js/extension/sharpen.js +29 -0
  73. package/src/js/factory/command.js +36 -0
  74. package/src/js/factory/errorMessage.js +27 -0
  75. package/src/js/graphics.js +1539 -0
  76. package/src/js/helper/imagetracer.js +1396 -0
  77. package/src/js/helper/selectionModifyHelper.js +86 -0
  78. package/src/js/helper/shapeFilterFillHelper.js +564 -0
  79. package/src/js/helper/shapeResizeHelper.js +237 -0
  80. package/src/js/imageEditor.js +1795 -0
  81. package/src/js/interface/command.js +131 -0
  82. package/src/js/interface/component.js +127 -0
  83. package/src/js/interface/drawingMode.js +47 -0
  84. package/src/js/invoker.js +292 -0
  85. package/src/js/polyfill.js +498 -0
  86. package/src/js/ui/crop.js +139 -0
  87. package/src/js/ui/draw.js +187 -0
  88. package/src/js/ui/filter.js +510 -0
  89. package/src/js/ui/flip.js +87 -0
  90. package/src/js/ui/history.js +171 -0
  91. package/src/js/ui/icon.js +191 -0
  92. package/src/js/ui/locale/locale.js +19 -0
  93. package/src/js/ui/mask.js +96 -0
  94. package/src/js/ui/panelMenu.js +130 -0
  95. package/src/js/ui/resize.js +241 -0
  96. package/src/js/ui/rotate.js +123 -0
  97. package/src/js/ui/shape.js +265 -0
  98. package/src/js/ui/submenuBase.js +122 -0
  99. package/src/js/ui/template/controls.js +21 -0
  100. package/src/js/ui/template/mainContainer.js +38 -0
  101. package/src/js/ui/template/style.js +146 -0
  102. package/src/js/ui/template/submenu/crop.js +73 -0
  103. package/src/js/ui/template/submenu/draw.js +42 -0
  104. package/src/js/ui/template/submenu/filter.js +157 -0
  105. package/src/js/ui/template/submenu/flip.js +41 -0
  106. package/src/js/ui/template/submenu/history.js +22 -0
  107. package/src/js/ui/template/submenu/icon.js +108 -0
  108. package/src/js/ui/template/submenu/mask.js +30 -0
  109. package/src/js/ui/template/submenu/resize.js +54 -0
  110. package/src/js/ui/template/submenu/rotate.js +32 -0
  111. package/src/js/ui/template/submenu/shape.js +45 -0
  112. package/src/js/ui/template/submenu/text.js +67 -0
  113. package/src/js/ui/template/submenu/zoom.js +41 -0
  114. package/src/js/ui/text.js +279 -0
  115. package/src/js/ui/theme/standard.js +220 -0
  116. package/src/js/ui/theme/theme.js +249 -0
  117. package/src/js/ui/tools/colorpicker.js +250 -0
  118. package/src/js/ui/tools/range.js +390 -0
  119. package/src/js/ui.js +858 -0
  120. package/src/js/util.js +551 -0
  121. package/src/svg/default.svg +335 -0
  122. package/src/svg/icon-a/ic-apply.svg +6 -0
  123. package/src/svg/icon-a/ic-cancel.svg +6 -0
  124. package/src/svg/icon-a/ic-color-transparent-w.svg +12 -0
  125. package/src/svg/icon-a/ic-crop.svg +7 -0
  126. package/src/svg/icon-a/ic-delete-all.svg +6 -0
  127. package/src/svg/icon-a/ic-delete.svg +6 -0
  128. package/src/svg/icon-a/ic-draw-free.svg +5 -0
  129. package/src/svg/icon-a/ic-draw-line.svg +5 -0
  130. package/src/svg/icon-a/ic-draw.svg +6 -0
  131. package/src/svg/icon-a/ic-filter.svg +7 -0
  132. package/src/svg/icon-a/ic-flip-reset.svg +7 -0
  133. package/src/svg/icon-a/ic-flip-x.svg +6 -0
  134. package/src/svg/icon-a/ic-flip-y.svg +6 -0
  135. package/src/svg/icon-a/ic-flip.svg +6 -0
  136. package/src/svg/icon-a/ic-history-check.svg +5 -0
  137. package/src/svg/icon-a/ic-history-crop.svg +7 -0
  138. package/src/svg/icon-a/ic-history-delete.svg +9 -0
  139. package/src/svg/icon-a/ic-history-draw.svg +7 -0
  140. package/src/svg/icon-a/ic-history-filter.svg +8 -0
  141. package/src/svg/icon-a/ic-history-flip.svg +6 -0
  142. package/src/svg/icon-a/ic-history-group.svg +9 -0
  143. package/src/svg/icon-a/ic-history-icon.svg +6 -0
  144. package/src/svg/icon-a/ic-history-load.svg +7 -0
  145. package/src/svg/icon-a/ic-history-mask.svg +9 -0
  146. package/src/svg/icon-a/ic-history-resize.svg +12 -0
  147. package/src/svg/icon-a/ic-history-rotate.svg +16 -0
  148. package/src/svg/icon-a/ic-history-shape.svg +7 -0
  149. package/src/svg/icon-a/ic-history-text.svg +8 -0
  150. package/src/svg/icon-a/ic-history.svg +6 -0
  151. package/src/svg/icon-a/ic-icon-arrow-2.svg +5 -0
  152. package/src/svg/icon-a/ic-icon-arrow-3.svg +5 -0
  153. package/src/svg/icon-a/ic-icon-arrow.svg +5 -0
  154. package/src/svg/icon-a/ic-icon-bubble.svg +5 -0
  155. package/src/svg/icon-a/ic-icon-heart.svg +5 -0
  156. package/src/svg/icon-a/ic-icon-load.svg +8 -0
  157. package/src/svg/icon-a/ic-icon-location.svg +8 -0
  158. package/src/svg/icon-a/ic-icon-polygon.svg +5 -0
  159. package/src/svg/icon-a/ic-icon-star-2.svg +5 -0
  160. package/src/svg/icon-a/ic-icon-star.svg +5 -0
  161. package/src/svg/icon-a/ic-icon.svg +5 -0
  162. package/src/svg/icon-a/ic-mask-load.svg +8 -0
  163. package/src/svg/icon-a/ic-mask.svg +6 -0
  164. package/src/svg/icon-a/ic-redo.svg +7 -0
  165. package/src/svg/icon-a/ic-reset.svg +7 -0
  166. package/src/svg/icon-a/ic-resize.svg +13 -0
  167. package/src/svg/icon-a/ic-rotate-clockwise.svg +7 -0
  168. package/src/svg/icon-a/ic-rotate-counterclockwise.svg +7 -0
  169. package/src/svg/icon-a/ic-rotate.svg +7 -0
  170. package/src/svg/icon-a/ic-shape-circle.svg +5 -0
  171. package/src/svg/icon-a/ic-shape-rectangle.svg +5 -0
  172. package/src/svg/icon-a/ic-shape-triangle.svg +5 -0
  173. package/src/svg/icon-a/ic-shape.svg +6 -0
  174. package/src/svg/icon-a/ic-text-align-center.svg +6 -0
  175. package/src/svg/icon-a/ic-text-align-left.svg +6 -0
  176. package/src/svg/icon-a/ic-text-align-right.svg +6 -0
  177. package/src/svg/icon-a/ic-text-bold.svg +7 -0
  178. package/src/svg/icon-a/ic-text-italic.svg +6 -0
  179. package/src/svg/icon-a/ic-text-underline.svg +7 -0
  180. package/src/svg/icon-a/ic-text.svg +7 -0
  181. package/src/svg/icon-a/ic-undo.svg +7 -0
  182. package/src/svg/icon-a/ic-zoom-hand.svg +8 -0
  183. package/src/svg/icon-a/ic-zoom-zoom-in.svg +10 -0
  184. package/src/svg/icon-a/ic-zoom-zoom-out.svg +9 -0
  185. package/src/svg/icon-a/img-bi.svg +5 -0
  186. package/src/svg/icon-b/ic-apply.svg +6 -0
  187. package/src/svg/icon-b/ic-cancel.svg +6 -0
  188. package/src/svg/icon-b/ic-crop.svg +7 -0
  189. package/src/svg/icon-b/ic-delete-all.svg +6 -0
  190. package/src/svg/icon-b/ic-delete.svg +6 -0
  191. package/src/svg/icon-b/ic-draw-free.svg +5 -0
  192. package/src/svg/icon-b/ic-draw-line.svg +5 -0
  193. package/src/svg/icon-b/ic-draw.svg +6 -0
  194. package/src/svg/icon-b/ic-filter.svg +7 -0
  195. package/src/svg/icon-b/ic-flip-reset.svg +7 -0
  196. package/src/svg/icon-b/ic-flip-x.svg +6 -0
  197. package/src/svg/icon-b/ic-flip-y.svg +6 -0
  198. package/src/svg/icon-b/ic-flip.svg +6 -0
  199. package/src/svg/icon-b/ic-history-check.svg +5 -0
  200. package/src/svg/icon-b/ic-history-crop.svg +7 -0
  201. package/src/svg/icon-b/ic-history-delete.svg +9 -0
  202. package/src/svg/icon-b/ic-history-draw.svg +7 -0
  203. package/src/svg/icon-b/ic-history-filter.svg +8 -0
  204. package/src/svg/icon-b/ic-history-flip.svg +6 -0
  205. package/src/svg/icon-b/ic-history-group.svg +9 -0
  206. package/src/svg/icon-b/ic-history-icon.svg +6 -0
  207. package/src/svg/icon-b/ic-history-load.svg +7 -0
  208. package/src/svg/icon-b/ic-history-mask.svg +9 -0
  209. package/src/svg/icon-b/ic-history-resize.svg +12 -0
  210. package/src/svg/icon-b/ic-history-rotate.svg +16 -0
  211. package/src/svg/icon-b/ic-history-shape.svg +7 -0
  212. package/src/svg/icon-b/ic-history-text.svg +8 -0
  213. package/src/svg/icon-b/ic-history.svg +6 -0
  214. package/src/svg/icon-b/ic-icon-arrow-2.svg +5 -0
  215. package/src/svg/icon-b/ic-icon-arrow-3.svg +5 -0
  216. package/src/svg/icon-b/ic-icon-arrow.svg +5 -0
  217. package/src/svg/icon-b/ic-icon-bubble.svg +5 -0
  218. package/src/svg/icon-b/ic-icon-heart.svg +5 -0
  219. package/src/svg/icon-b/ic-icon-load.svg +8 -0
  220. package/src/svg/icon-b/ic-icon-location.svg +8 -0
  221. package/src/svg/icon-b/ic-icon-polygon.svg +5 -0
  222. package/src/svg/icon-b/ic-icon-star-2.svg +5 -0
  223. package/src/svg/icon-b/ic-icon-star.svg +5 -0
  224. package/src/svg/icon-b/ic-icon.svg +5 -0
  225. package/src/svg/icon-b/ic-mask-load.svg +8 -0
  226. package/src/svg/icon-b/ic-mask.svg +6 -0
  227. package/src/svg/icon-b/ic-redo.svg +7 -0
  228. package/src/svg/icon-b/ic-reset.svg +7 -0
  229. package/src/svg/icon-b/ic-resize.svg +13 -0
  230. package/src/svg/icon-b/ic-rotate-clockwise.svg +7 -0
  231. package/src/svg/icon-b/ic-rotate-counterclockwise.svg +7 -0
  232. package/src/svg/icon-b/ic-rotate.svg +7 -0
  233. package/src/svg/icon-b/ic-shape-circle.svg +5 -0
  234. package/src/svg/icon-b/ic-shape-rectangle.svg +5 -0
  235. package/src/svg/icon-b/ic-shape-triangle.svg +5 -0
  236. package/src/svg/icon-b/ic-shape.svg +6 -0
  237. package/src/svg/icon-b/ic-text-align-center.svg +6 -0
  238. package/src/svg/icon-b/ic-text-align-left.svg +6 -0
  239. package/src/svg/icon-b/ic-text-align-right.svg +6 -0
  240. package/src/svg/icon-b/ic-text-bold.svg +7 -0
  241. package/src/svg/icon-b/ic-text-italic.svg +6 -0
  242. package/src/svg/icon-b/ic-text-underline.svg +7 -0
  243. package/src/svg/icon-b/ic-text.svg +7 -0
  244. package/src/svg/icon-b/ic-undo.svg +7 -0
  245. package/src/svg/icon-b/ic-zoom-hand.svg +8 -0
  246. package/src/svg/icon-b/ic-zoom-zoom-in.svg +12 -0
  247. package/src/svg/icon-b/ic-zoom-zoom-out.svg +11 -0
  248. package/src/svg/icon-b/img-bi.svg +5 -0
  249. package/src/svg/icon-c/ic-apply.svg +6 -0
  250. package/src/svg/icon-c/ic-cancel.svg +6 -0
  251. package/src/svg/icon-c/ic-crop.svg +7 -0
  252. package/src/svg/icon-c/ic-delete-all.svg +6 -0
  253. package/src/svg/icon-c/ic-delete.svg +6 -0
  254. package/src/svg/icon-c/ic-draw-free.svg +5 -0
  255. package/src/svg/icon-c/ic-draw-line.svg +5 -0
  256. package/src/svg/icon-c/ic-draw.svg +6 -0
  257. package/src/svg/icon-c/ic-filter.svg +7 -0
  258. package/src/svg/icon-c/ic-flip-reset.svg +7 -0
  259. package/src/svg/icon-c/ic-flip-x.svg +6 -0
  260. package/src/svg/icon-c/ic-flip-y.svg +6 -0
  261. package/src/svg/icon-c/ic-flip.svg +6 -0
  262. package/src/svg/icon-c/ic-history-check.svg +5 -0
  263. package/src/svg/icon-c/ic-history-crop.svg +7 -0
  264. package/src/svg/icon-c/ic-history-delete.svg +9 -0
  265. package/src/svg/icon-c/ic-history-draw.svg +7 -0
  266. package/src/svg/icon-c/ic-history-filter.svg +8 -0
  267. package/src/svg/icon-c/ic-history-flip.svg +6 -0
  268. package/src/svg/icon-c/ic-history-group.svg +9 -0
  269. package/src/svg/icon-c/ic-history-icon.svg +6 -0
  270. package/src/svg/icon-c/ic-history-load.svg +7 -0
  271. package/src/svg/icon-c/ic-history-mask.svg +9 -0
  272. package/src/svg/icon-c/ic-history-resize.svg +12 -0
  273. package/src/svg/icon-c/ic-history-rotate.svg +16 -0
  274. package/src/svg/icon-c/ic-history-shape.svg +7 -0
  275. package/src/svg/icon-c/ic-history-text.svg +8 -0
  276. package/src/svg/icon-c/ic-history.svg +6 -0
  277. package/src/svg/icon-c/ic-icon-arrow-2.svg +5 -0
  278. package/src/svg/icon-c/ic-icon-arrow-3.svg +5 -0
  279. package/src/svg/icon-c/ic-icon-arrow.svg +5 -0
  280. package/src/svg/icon-c/ic-icon-bubble.svg +5 -0
  281. package/src/svg/icon-c/ic-icon-heart.svg +5 -0
  282. package/src/svg/icon-c/ic-icon-load.svg +8 -0
  283. package/src/svg/icon-c/ic-icon-location.svg +8 -0
  284. package/src/svg/icon-c/ic-icon-polygon.svg +5 -0
  285. package/src/svg/icon-c/ic-icon-star-2.svg +5 -0
  286. package/src/svg/icon-c/ic-icon-star.svg +5 -0
  287. package/src/svg/icon-c/ic-icon.svg +5 -0
  288. package/src/svg/icon-c/ic-mask-load.svg +8 -0
  289. package/src/svg/icon-c/ic-mask.svg +6 -0
  290. package/src/svg/icon-c/ic-redo.svg +7 -0
  291. package/src/svg/icon-c/ic-reset.svg +7 -0
  292. package/src/svg/icon-c/ic-resize.svg +13 -0
  293. package/src/svg/icon-c/ic-rotate-clockwise.svg +7 -0
  294. package/src/svg/icon-c/ic-rotate-counterclockwise.svg +7 -0
  295. package/src/svg/icon-c/ic-rotate.svg +7 -0
  296. package/src/svg/icon-c/ic-shape-circle.svg +5 -0
  297. package/src/svg/icon-c/ic-shape-rectangle.svg +5 -0
  298. package/src/svg/icon-c/ic-shape-triangle.svg +5 -0
  299. package/src/svg/icon-c/ic-shape.svg +6 -0
  300. package/src/svg/icon-c/ic-text-align-center.svg +6 -0
  301. package/src/svg/icon-c/ic-text-align-left.svg +6 -0
  302. package/src/svg/icon-c/ic-text-align-right.svg +6 -0
  303. package/src/svg/icon-c/ic-text-bold.svg +7 -0
  304. package/src/svg/icon-c/ic-text-italic.svg +6 -0
  305. package/src/svg/icon-c/ic-text-underline.svg +7 -0
  306. package/src/svg/icon-c/ic-text.svg +7 -0
  307. package/src/svg/icon-c/ic-undo.svg +7 -0
  308. package/src/svg/icon-c/ic-zoom-hand.svg +8 -0
  309. package/src/svg/icon-c/ic-zoom-zoom-in.svg +12 -0
  310. package/src/svg/icon-c/ic-zoom-zoom-out.svg +11 -0
  311. package/src/svg/icon-c/img-bi.svg +5 -0
  312. package/src/svg/icon-d/ic-apply.svg +6 -0
  313. package/src/svg/icon-d/ic-cancel.svg +6 -0
  314. package/src/svg/icon-d/ic-crop.svg +7 -0
  315. package/src/svg/icon-d/ic-delete-all.svg +6 -0
  316. package/src/svg/icon-d/ic-delete.svg +6 -0
  317. package/src/svg/icon-d/ic-draw-free.svg +5 -0
  318. package/src/svg/icon-d/ic-draw-line.svg +5 -0
  319. package/src/svg/icon-d/ic-draw.svg +6 -0
  320. package/src/svg/icon-d/ic-filter.svg +7 -0
  321. package/src/svg/icon-d/ic-flip-reset.svg +7 -0
  322. package/src/svg/icon-d/ic-flip-x.svg +6 -0
  323. package/src/svg/icon-d/ic-flip-y.svg +6 -0
  324. package/src/svg/icon-d/ic-flip.svg +6 -0
  325. package/src/svg/icon-d/ic-history-check.svg +5 -0
  326. package/src/svg/icon-d/ic-history-crop.svg +7 -0
  327. package/src/svg/icon-d/ic-history-delete.svg +9 -0
  328. package/src/svg/icon-d/ic-history-draw.svg +7 -0
  329. package/src/svg/icon-d/ic-history-filter.svg +8 -0
  330. package/src/svg/icon-d/ic-history-flip.svg +6 -0
  331. package/src/svg/icon-d/ic-history-group.svg +9 -0
  332. package/src/svg/icon-d/ic-history-icon.svg +6 -0
  333. package/src/svg/icon-d/ic-history-load.svg +7 -0
  334. package/src/svg/icon-d/ic-history-mask.svg +9 -0
  335. package/src/svg/icon-d/ic-history-resize.svg +12 -0
  336. package/src/svg/icon-d/ic-history-rotate.svg +16 -0
  337. package/src/svg/icon-d/ic-history-shape.svg +7 -0
  338. package/src/svg/icon-d/ic-history-text.svg +8 -0
  339. package/src/svg/icon-d/ic-history.svg +6 -0
  340. package/src/svg/icon-d/ic-icon-arrow-2.svg +5 -0
  341. package/src/svg/icon-d/ic-icon-arrow-3.svg +5 -0
  342. package/src/svg/icon-d/ic-icon-arrow.svg +5 -0
  343. package/src/svg/icon-d/ic-icon-bubble.svg +5 -0
  344. package/src/svg/icon-d/ic-icon-heart.svg +5 -0
  345. package/src/svg/icon-d/ic-icon-load.svg +8 -0
  346. package/src/svg/icon-d/ic-icon-location.svg +8 -0
  347. package/src/svg/icon-d/ic-icon-polygon.svg +5 -0
  348. package/src/svg/icon-d/ic-icon-star-2.svg +5 -0
  349. package/src/svg/icon-d/ic-icon-star.svg +5 -0
  350. package/src/svg/icon-d/ic-icon.svg +5 -0
  351. package/src/svg/icon-d/ic-mask-load.svg +8 -0
  352. package/src/svg/icon-d/ic-mask.svg +6 -0
  353. package/src/svg/icon-d/ic-redo.svg +7 -0
  354. package/src/svg/icon-d/ic-reset.svg +7 -0
  355. package/src/svg/icon-d/ic-resize.svg +13 -0
  356. package/src/svg/icon-d/ic-rotate-clockwise.svg +7 -0
  357. package/src/svg/icon-d/ic-rotate-counterclockwise.svg +7 -0
  358. package/src/svg/icon-d/ic-rotate.svg +7 -0
  359. package/src/svg/icon-d/ic-shape-circle.svg +5 -0
  360. package/src/svg/icon-d/ic-shape-rectangle.svg +5 -0
  361. package/src/svg/icon-d/ic-shape-triangle.svg +5 -0
  362. package/src/svg/icon-d/ic-shape.svg +6 -0
  363. package/src/svg/icon-d/ic-text-align-center.svg +6 -0
  364. package/src/svg/icon-d/ic-text-align-left.svg +6 -0
  365. package/src/svg/icon-d/ic-text-align-right.svg +6 -0
  366. package/src/svg/icon-d/ic-text-bold.svg +7 -0
  367. package/src/svg/icon-d/ic-text-italic.svg +6 -0
  368. package/src/svg/icon-d/ic-text-underline.svg +7 -0
  369. package/src/svg/icon-d/ic-text.svg +7 -0
  370. package/src/svg/icon-d/ic-undo.svg +7 -0
  371. package/src/svg/icon-d/ic-zoom-hand.svg +8 -0
  372. package/src/svg/icon-d/ic-zoom-zoom-in.svg +12 -0
  373. package/src/svg/icon-d/ic-zoom-zoom-out.svg +11 -0
  374. 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;