jab-image-editor
Version:
JAB TOAST UI Component: ImageEditor
175 lines (154 loc) • 5.69 kB
JavaScript
/**
* @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;