Spaces:
Running
Running
| import { fabric } from 'fabric'; | |
| import extend from 'tui-code-snippet/object/extend'; | |
| import forEach from 'tui-code-snippet/collection/forEach'; | |
| import Component from '@/interface/component'; | |
| import { eventNames as events, rejectMessages, componentNames, fObjectOptions } from '@/consts'; | |
| const pathMap = { | |
| arrow: 'M 0 90 H 105 V 120 L 160 60 L 105 0 V 30 H 0 Z', | |
| cancel: | |
| 'M 0 30 L 30 60 L 0 90 L 30 120 L 60 90 L 90 120 L 120 90 ' + | |
| 'L 90 60 L 120 30 L 90 0 L 60 30 L 30 0 Z', | |
| }; | |
| /** | |
| * Icon | |
| * @class Icon | |
| * @param {Graphics} graphics - Graphics instance | |
| * @extends {Component} | |
| * @ignore | |
| */ | |
| class Icon extends Component { | |
| constructor(graphics) { | |
| super(componentNames.ICON, graphics); | |
| /** | |
| * Default icon color | |
| * @type {string} | |
| */ | |
| this._oColor = '#000000'; | |
| /** | |
| * Path value of each icon type | |
| * @type {Object} | |
| */ | |
| this._pathMap = pathMap; | |
| /** | |
| * Type of the drawing icon | |
| * @type {string} | |
| * @private | |
| */ | |
| this._type = null; | |
| /** | |
| * Color of the drawing icon | |
| * @type {string} | |
| * @private | |
| */ | |
| this._iconColor = null; | |
| /** | |
| * Event handler list | |
| * @type {Object} | |
| * @private | |
| */ | |
| this._handlers = { | |
| mousedown: this._onFabricMouseDown.bind(this), | |
| mousemove: this._onFabricMouseMove.bind(this), | |
| mouseup: this._onFabricMouseUp.bind(this), | |
| }; | |
| } | |
| /** | |
| * Set states of the current drawing shape | |
| * @ignore | |
| * @param {string} type - Icon type ('arrow', 'cancel', custom icon name) | |
| * @param {string} iconColor - Icon foreground color | |
| */ | |
| setStates(type, iconColor) { | |
| this._type = type; | |
| this._iconColor = iconColor; | |
| } | |
| /** | |
| * Start to draw the icon on canvas | |
| * @ignore | |
| */ | |
| start() { | |
| const canvas = this.getCanvas(); | |
| canvas.selection = false; | |
| canvas.on('mouse:down', this._handlers.mousedown); | |
| } | |
| /** | |
| * End to draw the icon on canvas | |
| * @ignore | |
| */ | |
| end() { | |
| const canvas = this.getCanvas(); | |
| canvas.selection = true; | |
| canvas.off({ | |
| 'mouse:down': this._handlers.mousedown, | |
| }); | |
| } | |
| /** | |
| * Add icon | |
| * @param {string} type - Icon type | |
| * @param {Object} options - Icon options | |
| * @param {string} [options.fill] - Icon foreground color | |
| * @param {string} [options.left] - Icon x position | |
| * @param {string} [options.top] - Icon y position | |
| * @returns {Promise} | |
| */ | |
| add(type, options) { | |
| return new Promise((resolve, reject) => { | |
| const canvas = this.getCanvas(); | |
| const path = this._pathMap[type]; | |
| const selectionStyle = fObjectOptions.SELECTION_STYLE; | |
| const icon = path ? this._createIcon(path) : null; | |
| this._icon = icon; | |
| if (!icon) { | |
| reject(rejectMessages.invalidParameters); | |
| } | |
| icon.set( | |
| extend( | |
| { | |
| type: 'icon', | |
| fill: this._oColor, | |
| }, | |
| selectionStyle, | |
| options, | |
| this.graphics.controlStyle | |
| ) | |
| ); | |
| canvas.add(icon).setActiveObject(icon); | |
| resolve(this.graphics.createObjectProperties(icon)); | |
| }); | |
| } | |
| /** | |
| * Register icon paths | |
| * @param {{key: string, value: string}} pathInfos - Path infos | |
| */ | |
| registerPaths(pathInfos) { | |
| forEach( | |
| pathInfos, | |
| (path, type) => { | |
| this._pathMap[type] = path; | |
| }, | |
| this | |
| ); | |
| } | |
| /** | |
| * Set icon object color | |
| * @param {string} color - Color to set | |
| * @param {fabric.Path}[obj] - Current activated path object | |
| */ | |
| setColor(color, obj) { | |
| this._oColor = color; | |
| if (obj && obj.get('type') === 'icon') { | |
| obj.set({ fill: this._oColor }); | |
| this.getCanvas().renderAll(); | |
| } | |
| } | |
| /** | |
| * Get icon color | |
| * @param {fabric.Path}[obj] - Current activated path object | |
| * @returns {string} color | |
| */ | |
| getColor(obj) { | |
| return obj.fill; | |
| } | |
| /** | |
| * Create icon object | |
| * @param {string} path - Path value to create icon | |
| * @returns {fabric.Path} Path object | |
| */ | |
| _createIcon(path) { | |
| return new fabric.Path(path); | |
| } | |
| /** | |
| * MouseDown event handler on canvas | |
| * @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event object | |
| * @private | |
| */ | |
| _onFabricMouseDown(fEvent) { | |
| const canvas = this.getCanvas(); | |
| this._startPoint = canvas.getPointer(fEvent.e); | |
| const { x: left, y: top } = this._startPoint; | |
| this.add(this._type, { | |
| left, | |
| top, | |
| fill: this._iconColor, | |
| }).then(() => { | |
| this.fire(events.ADD_OBJECT, this.graphics.createObjectProperties(this._icon)); | |
| canvas.on('mouse:move', this._handlers.mousemove); | |
| canvas.on('mouse:up', this._handlers.mouseup); | |
| }); | |
| } | |
| /** | |
| * MouseMove event handler on canvas | |
| * @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event object | |
| * @private | |
| */ | |
| _onFabricMouseMove(fEvent) { | |
| const canvas = this.getCanvas(); | |
| if (!this._icon) { | |
| return; | |
| } | |
| const moveOriginPointer = canvas.getPointer(fEvent.e); | |
| const scaleX = (moveOriginPointer.x - this._startPoint.x) / this._icon.width; | |
| const scaleY = (moveOriginPointer.y - this._startPoint.y) / this._icon.height; | |
| this._icon.set({ | |
| scaleX: Math.abs(scaleX * 2), | |
| scaleY: Math.abs(scaleY * 2), | |
| }); | |
| this._icon.setCoords(); | |
| canvas.renderAll(); | |
| } | |
| /** | |
| * MouseUp event handler on canvas | |
| * @private | |
| */ | |
| _onFabricMouseUp() { | |
| const canvas = this.getCanvas(); | |
| this.fire(events.OBJECT_ADDED, this.graphics.createObjectProperties(this._icon)); | |
| this._icon = null; | |
| canvas.off('mouse:down', this._handlers.mousedown); | |
| canvas.off('mouse:move', this._handlers.mousemove); | |
| canvas.off('mouse:up', this._handlers.mouseup); | |
| } | |
| } | |
| export default Icon; | |