diff --git a/CHANGELOG.md b/CHANGELOG.md index 0223f243489..fdf43405b00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- chore(TS): migrate Line [#8413](https://github.com/fabricjs/fabric.js/pull/8413) - chore(TS): migrate Polyline/Polygon [#8417](https://github.com/fabricjs/fabric.js/pull/8417) - chore(TS): migrate Rect [#8411](https://github.com/fabricjs/fabric.js/pull/8411) - chore(TS): migrate Ellipse [#8408](https://github.com/fabricjs/fabric.js/pull/8408) diff --git a/src/shapes/line.class.ts b/src/shapes/line.class.ts index f2eb40d4bc5..5cfe0e99a6f 100644 --- a/src/shapes/line.class.ts +++ b/src/shapes/line.class.ts @@ -1,340 +1,327 @@ -//@ts-nocheck +// @ts-nocheck + +import { fabric } from '../../HEADER'; +import { SHARED_ATTRIBUTES } from '../parser/attributes'; +import { parseAttributes } from '../parser/parseAttributes'; +import { TClassProperties } from '../typedefs'; +import { clone } from '../util/lang_object'; import { FabricObject } from './fabricObject.class'; +import { fabricObjectDefaultValues } from './object.class'; -(function (global) { - var fabric = global.fabric || (global.fabric = {}), - extend = fabric.util.object.extend, - clone = fabric.util.object.clone, - coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 }; +const coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 }; +export class Line extends FabricObject { /** - * Line class - * @class fabric.Line - * @extends fabric.Object - * @see {@link fabric.Line#initialize} for constructor definition + * x value or first line edge + * @type Number + * @default */ - fabric.Line = fabric.util.createClass( - fabric.Object, - /** @lends fabric.Line.prototype */ { - /** - * Type of an object - * @type String - * @default - */ - type: 'line', - - /** - * x value or first line edge - * @type Number - * @default - */ - x1: 0, - - /** - * y value or first line edge - * @type Number - * @default - */ - y1: 0, - - /** - * x value or second line edge - * @type Number - * @default - */ - x2: 0, - - /** - * y value or second line edge - * @type Number - * @default - */ - y2: 0, - - cacheProperties: FabricObject.prototype.cacheProperties.concat( - 'x1', - 'x2', - 'y1', - 'y2' - ), - - /** - * Constructor - * @param {Array} [points] Array of points - * @param {Object} [options] Options object - * @return {fabric.Line} thisArg - */ - initialize: function (points, options) { - if (!points) { - points = [0, 0, 0, 0]; - } - - this.callSuper('initialize', options); - - this.set('x1', points[0]); - this.set('y1', points[1]); - this.set('x2', points[2]); - this.set('y2', points[3]); - - this._setWidthHeight(options); - }, + x1: number; - /** - * @private - * @param {Object} [options] Options - */ - _setWidthHeight: function (options) { - options || (options = {}); + /** + * y value or first line edge + * @type Number + * @default + */ + y1: number; - this.width = Math.abs(this.x2 - this.x1); - this.height = Math.abs(this.y2 - this.y1); + /** + * x value or second line edge + * @type Number + * @default + */ + x2: number; - this.left = 'left' in options ? options.left : this._getLeftToOriginX(); + /** + * y value or second line edge + * @type Number + * @default + */ + y2: number; - this.top = 'top' in options ? options.top : this._getTopToOriginY(); - }, + /** + * Constructor + * @param {Array} [points] Array of points + * @param {Object} [options] Options object + * @return {Line} thisArg + */ + constructor(points, options) { + if (!points) { + points = [0, 0, 0, 0]; + } - /** - * @private - * @param {String} key - * @param {*} value - */ - _set: function (key, value) { - this.callSuper('_set', key, value); - if (typeof coordProps[key] !== 'undefined') { - this._setWidthHeight(); - } - return this; - }, + super(options); - /** - * @private - * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line. - */ - _getLeftToOriginX: makeEdgeToOriginGetter( - { - // property names - origin: 'originX', - axis1: 'x1', - axis2: 'x2', - dimension: 'width', - }, - { - // possible values of origin - nearest: 'left', - center: 'center', - farthest: 'right', - } - ), - - /** - * @private - * @return {Number} topToOriginY Distance from top edge of canvas to originY of Line. - */ - _getTopToOriginY: makeEdgeToOriginGetter( - { - // property names - origin: 'originY', - axis1: 'y1', - axis2: 'y2', - dimension: 'height', - }, - { - // possible values of origin - nearest: 'top', - center: 'center', - farthest: 'bottom', - } - ), - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _render: function (ctx) { - ctx.beginPath(); - - var p = this.calcLinePoints(); - ctx.moveTo(p.x1, p.y1); - ctx.lineTo(p.x2, p.y2); - - ctx.lineWidth = this.strokeWidth; - - // TODO: test this - // make sure setting "fill" changes color of a line - // (by copying fillStyle to strokeStyle, since line is stroked, not filled) - var origStrokeStyle = ctx.strokeStyle; - ctx.strokeStyle = this.stroke || ctx.fillStyle; - this.stroke && this._renderStroke(ctx); - ctx.strokeStyle = origStrokeStyle; - }, + this.set('x1', points[0]); + this.set('y1', points[1]); + this.set('x2', points[2]); + this.set('y2', points[3]); - /** - * This function is an helper for svg import. it returns the center of the object in the svg - * untransformed coordinates - * @private - * @return {Object} center point from element coordinates - */ - _findCenterFromElement: function () { - return { - x: (this.x1 + this.x2) / 2, - y: (this.y1 + this.y2) / 2, - }; - }, + this._setWidthHeight(options); + } + + /** + * @private + * @param {Object} [options] Options + */ + _setWidthHeight(options) { + options || (options = {}); + + this.width = Math.abs(this.x2 - this.x1); + this.height = Math.abs(this.y2 - this.y1); + + this.left = 'left' in options ? options.left : this._getLeftToOriginX(); + + this.top = 'top' in options ? options.top : this._getTopToOriginY(); + } + + /** + * @private + * @param {String} key + * @param {*} value + */ + _set(key, value) { + super._set(key, value); + if (typeof coordProps[key] !== 'undefined') { + this._setWidthHeight(); + } + return this; + } - /** - * Returns object representation of an instance - * @method toObject - * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output - * @return {Object} object representation of an instance - */ - toObject: function (propertiesToInclude) { - return extend( - this.callSuper('toObject', propertiesToInclude), - this.calcLinePoints() + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render(ctx) { + ctx.beginPath(); + + const p = this.calcLinePoints(); + ctx.moveTo(p.x1, p.y1); + ctx.lineTo(p.x2, p.y2); + + ctx.lineWidth = this.strokeWidth; + + // TODO: test this + // make sure setting "fill" changes color of a line + // (by copying fillStyle to strokeStyle, since line is stroked, not filled) + const origStrokeStyle = ctx.strokeStyle; + ctx.strokeStyle = this.stroke || ctx.fillStyle; + this.stroke && this._renderStroke(ctx); + ctx.strokeStyle = origStrokeStyle; + } + + /** + * This function is an helper for svg import. it returns the center of the object in the svg + * untransformed coordinates + * @private + * @return {Object} center point from element coordinates + */ + _findCenterFromElement() { + return { + x: (this.x1 + this.x2) / 2, + y: (this.y1 + this.y2) / 2, + }; + } + + /** + * Returns object representation of an instance + * @method toObject + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject(propertiesToInclude) { + return { ...super.toObject(propertiesToInclude), ...this.calcLinePoints() }; + } + + /* + * Calculate object dimensions from its properties + * @private + */ + _getNonTransformedDimensions() { + const dim = super._getNonTransformedDimensions(); + if (this.strokeLineCap === 'butt') { + if (this.width === 0) { + dim.y -= this.strokeWidth; + } + if (this.height === 0) { + dim.x -= this.strokeWidth; + } + } + return dim; + } + + /** + * Recalculates line points given width and height + * @private + */ + calcLinePoints() { + const xMult = this.x1 <= this.x2 ? -1 : 1, + yMult = this.y1 <= this.y2 ? -1 : 1, + x1 = xMult * this.width * 0.5, + y1 = yMult * this.height * 0.5, + x2 = xMult * this.width * -0.5, + y2 = yMult * this.height * -0.5; + + return { + x1: x1, + x2: x2, + y1: y1, + y2: y2, + }; + } + + private makeEdgeToOriginGetter(propertyNames, originValues) { + const origin = propertyNames.origin, + axis1 = propertyNames.axis1, + axis2 = propertyNames.axis2, + dimension = propertyNames.dimension, + nearest = originValues.nearest, + center = originValues.center, + farthest = originValues.farthest; + + switch (this.get(origin)) { + case nearest: + return Math.min(this.get(axis1), this.get(axis2)); + case center: + return ( + Math.min(this.get(axis1), this.get(axis2)) + 0.5 * this.get(dimension) ); - }, + case farthest: + return Math.max(this.get(axis1), this.get(axis2)); + } + } - /* - * Calculate object dimensions from its properties - * @private - */ - _getNonTransformedDimensions: function () { - var dim = this.callSuper('_getNonTransformedDimensions'); - if (this.strokeLineCap === 'butt') { - if (this.width === 0) { - dim.y -= this.strokeWidth; - } - if (this.height === 0) { - dim.x -= this.strokeWidth; - } - } - return dim; + /** + * @private + * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line. + */ + _getLeftToOriginX() { + return this.makeEdgeToOriginGetter( + { + // property names + origin: 'originX', + axis1: 'x1', + axis2: 'x2', + dimension: 'width', }, + { + // possible values of origin + nearest: 'left', + center: 'center', + farthest: 'right', + } + ); + } - /** - * Recalculates line points given width and height - * @private - */ - calcLinePoints: function () { - var xMult = this.x1 <= this.x2 ? -1 : 1, - yMult = this.y1 <= this.y2 ? -1 : 1, - x1 = xMult * this.width * 0.5, - y1 = yMult * this.height * 0.5, - x2 = xMult * this.width * -0.5, - y2 = yMult * this.height * -0.5; - - return { - x1: x1, - x2: x2, - y1: y1, - y2: y2, - }; + /** + * @private + * @return {Number} leftToOriginX Distance from left edge of canvas to originX of Line. + */ + _getTopToOriginY() { + return this.makeEdgeToOriginGetter( + { + // property names + origin: 'originY', + axis1: 'y1', + axis2: 'y2', + dimension: 'height', }, + { + // possible values of origin + nearest: 'top', + center: 'center', + farthest: 'bottom', + } + ); + } - /* _TO_SVG_START_ */ - /** - * Returns svg representation of an instance - * @return {Array} an array of strings with the specific svg representation - * of the instance - */ - _toSVG: function () { - var p = this.calcLinePoints(); - return [ - '\n', - ]; - }, - /* _TO_SVG_END_ */ - } - ); + /** + * Returns svg representation of an instance + * @return {Array} an array of strings with the specific svg representation + * of the instance + */ + _toSVG() { + const p = this.calcLinePoints(); + return [ + '\n', + ]; + } /* _FROM_SVG_START_ */ + /** - * List of attribute names to account for when parsing SVG element (used by {@link fabric.Line.fromElement}) + * List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement}) * @static - * @memberOf fabric.Line + * @memberOf Line * @see http://www.w3.org/TR/SVG/shapes.html#LineElement */ - fabric.Line.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( - 'x1 y1 x2 y2'.split(' ') - ); + static ATTRIBUTE_NAMES = SHARED_ATTRIBUTES.concat('x1 y1 x2 y2'.split(' ')); /** - * Returns fabric.Line instance from an SVG element + * Returns Line instance from an SVG element * @static - * @memberOf fabric.Line + * @memberOf Line * @param {SVGElement} element Element to parse * @param {Object} [options] Options object * @param {Function} [callback] callback function invoked after parsing */ - fabric.Line.fromElement = function (element, callback, options) { + static fromElement(element, callback, options) { options = options || {}; - var parsedAttributes = fabric.parseAttributes( - element, - fabric.Line.ATTRIBUTE_NAMES - ), + const parsedAttributes = parseAttributes(element, Line.ATTRIBUTE_NAMES), points = [ parsedAttributes.x1 || 0, parsedAttributes.y1 || 0, parsedAttributes.x2 || 0, parsedAttributes.y2 || 0, ]; - callback(new fabric.Line(points, extend(parsedAttributes, options))); - }; + callback(new Line(points, { ...parsedAttributes, ...options })); + } + /* _FROM_SVG_END_ */ /** - * Returns fabric.Line instance from an object representation + * Returns Line instance from an object representation * @static - * @memberOf fabric.Line + * @memberOf Line * @param {Object} object Object to create an instance from - * @returns {Promise} + * @returns {Promise} */ - fabric.Line.fromObject = function (object) { - var options = clone(object, true); + static fromObject(object) { + const options = clone(object, true); options.points = [object.x1, object.y1, object.x2, object.y2]; - return FabricObject._fromObject(fabric.Line, options, { + return FabricObject._fromObject(Line, options, { extraParam: 'points', }).then(function (fabricLine) { delete fabricLine.points; return fabricLine; }); - }; - - /** - * Produces a function that calculates distance from canvas edge to Line origin. - */ - function makeEdgeToOriginGetter(propertyNames, originValues) { - var origin = propertyNames.origin, - axis1 = propertyNames.axis1, - axis2 = propertyNames.axis2, - dimension = propertyNames.dimension, - nearest = originValues.nearest, - center = originValues.center, - farthest = originValues.farthest; - - return function () { - switch (this.get(origin)) { - case nearest: - return Math.min(this.get(axis1), this.get(axis2)); - case center: - return ( - Math.min(this.get(axis1), this.get(axis2)) + - 0.5 * this.get(dimension) - ); - case farthest: - return Math.max(this.get(axis1), this.get(axis2)); - } - }; } -})(typeof exports !== 'undefined' ? exports : window); +} + +export const lineDefaultValues: Partial> = { + type: 'line', + x1: 0, + y1: 0, + x2: 0, + y2: 0, + cacheProperties: fabricObjectDefaultValues.cacheProperties.concat( + 'x1', + 'x2', + 'y1', + 'y2' + ), +}; + +Object.assign(Line.prototype, lineDefaultValues); +/** @todo TODO_JS_MIGRATION remove next line after refactoring build */ +fabric.Line = Line;