UNPKG

jab-image-editor

Version:
175 lines (154 loc) 5.69 kB
/** * @author NHN. FE Development Team <dl_javascript@nhn.com> * @fileoverview Blur extending fabric.Image.filters.Convolute */ import fabric from 'fabric'; const ARROW_ANGLE = 30; const CHEVRON_SIZE_RATIO = 2.7; const TRIANGLE_SIZE_RATIO = 1.7; const RADIAN_CONVERSION_VALUE = 180; const ArrowLine = fabric.util.createClass(fabric.Line, /** @lends Convolute.prototype */{ /** * Line type * @param {String} type * @default */ type: 'line', /** * Constructor * @param {Array} [points] Array of points * @param {Object} [options] Options object * @override */ initialize(points, options = {}) { this.callSuper('initialize', points, options); this.arrowType = options.arrowType; }, /** * Render ArrowLine * @private * @override */ _render(ctx) { const {x1: fromX, y1: fromY, x2: toX, y2: toY} = this.calcLinePoints(); const linePosition = { fromX, fromY, toX, toY }; this.ctx = ctx; ctx.lineWidth = this.strokeWidth; this._renderBasicLinePath(linePosition); this._drawDecoratorPath(linePosition); this._renderStroke(ctx); }, /** * Render Basic line path * @param {Object} linePosition - line position * @param {number} option.fromX - line start position x * @param {number} option.fromY - line start position y * @param {number} option.toX - line end position x * @param {number} option.toY - line end position y * @private */ _renderBasicLinePath({fromX, fromY, toX, toY}) { this.ctx.beginPath(); this.ctx.moveTo(fromX, fromY); this.ctx.lineTo(toX, toY); }, /** * Render Arrow Head * @param {Object} linePosition - line position * @param {number} option.fromX - line start position x * @param {number} option.fromY - line start position y * @param {number} option.toX - line end position x * @param {number} option.toY - line end position y * @private */ _drawDecoratorPath(linePosition) { this._drawDecoratorPathType('head', linePosition); this._drawDecoratorPathType('tail', linePosition); }, /** * Render Arrow Head * @param {string} type - 'head' or 'tail' * @param {Object} linePosition - line position * @param {number} option.fromX - line start position x * @param {number} option.fromY - line start position y * @param {number} option.toX - line end position x * @param {number} option.toY - line end position y * @private */ _drawDecoratorPathType(type, linePosition) { switch (this.arrowType[type]) { case 'triangle': this._drawTrianglePath(type, linePosition); break; case 'chevron': this._drawChevronPath(type, linePosition); break; default: break; } }, /** * Render Triangle Head * @param {string} type - 'head' or 'tail' * @param {Object} linePosition - line position * @param {number} option.fromX - line start position x * @param {number} option.fromY - line start position y * @param {number} option.toX - line end position x * @param {number} option.toY - line end position y * @private */ _drawTrianglePath(type, linePosition) { const decorateSize = this.ctx.lineWidth * TRIANGLE_SIZE_RATIO; this._drawChevronPath(type, linePosition, decorateSize); this.ctx.closePath(); }, /** * Render Chevron Head * @param {string} type - 'head' or 'tail' * @param {Object} linePosition - line position * @param {number} option.fromX - line start position x * @param {number} option.fromY - line start position y * @param {number} option.toX - line end position x * @param {number} option.toY - line end position y * @param {number} decorateSize - decorate size * @private */ _drawChevronPath(type, {fromX, fromY, toX, toY}, decorateSize) { const {ctx} = this; if (!decorateSize) { decorateSize = this.ctx.lineWidth * CHEVRON_SIZE_RATIO; } const [standardX, standardY] = type === 'head' ? [fromX, fromY] : [toX, toY]; const [compareX, compareY] = type === 'head' ? [toX, toY] : [fromX, fromY]; const angle = Math.atan2(compareY - standardY, compareX - standardX) * RADIAN_CONVERSION_VALUE / Math.PI; const rotatedPosition = changeAngle => this.getRotatePosition(decorateSize, changeAngle, { x: standardX, y: standardY }); ctx.moveTo(...rotatedPosition(angle + ARROW_ANGLE)); ctx.lineTo(standardX, standardY); ctx.lineTo(...rotatedPosition(angle - ARROW_ANGLE)); }, /** * return position from change angle. * @param {number} distance - change distance * @param {number} angle - change angle * @param {Object} referencePosition - reference position * @returns {Array} * @private */ getRotatePosition(distance, angle, referencePosition) { const radian = angle * Math.PI / RADIAN_CONVERSION_VALUE; const {x, y} = referencePosition; return [ (distance * Math.cos(radian)) + x, (distance * Math.sin(radian)) + y ]; } }); export default ArrowLine;