From 653946c50c1d6d04c953decfd0873fd873bb04bf Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:14:31 +0200 Subject: [PATCH 01/11] svg --- src/parser/parseAttributes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/parseAttributes.ts b/src/parser/parseAttributes.ts index ae02a0e27ea..d17d4b60650 100644 --- a/src/parser/parseAttributes.ts +++ b/src/parser/parseAttributes.ts @@ -16,7 +16,7 @@ import { setStrokeFillOpacity } from './setStrokeFillOpacity'; * @param {Array} attributes Array of attributes to parse * @return {Object} object containing parsed attributes' names/values */ -export function parseAttributes(element, attributes, svgUid) { +export function parseAttributes(element, attributes, svgUid?: string) { if (!element) { return; } From b371499a478ce41e1ac60d1ce17c3e3c1bb571c4 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:14:40 +0200 Subject: [PATCH 02/11] SHARED_ATTRIBUTES --- HEADER.js | 28 ---------------------------- src/parser/attributes.ts | 25 +++++++++++++++++++++++++ src/parser/index.ts | 3 ++- 3 files changed, 27 insertions(+), 29 deletions(-) create mode 100644 src/parser/attributes.ts diff --git a/HEADER.js b/HEADER.js index 6aef6023249..8a59a9b5e1b 100644 --- a/HEADER.js +++ b/HEADER.js @@ -69,34 +69,6 @@ fabric.isTouchSupported = fabric.isLikelyNode = typeof Buffer !== 'undefined' && typeof window === 'undefined'; -/* _FROM_SVG_START_ */ -/** - * Attributes parsed from all SVG elements - * @type array - */ -fabric.SHARED_ATTRIBUTES = [ - 'display', - 'transform', - 'fill', - 'fill-opacity', - 'fill-rule', - 'opacity', - 'stroke', - 'stroke-dasharray', - 'stroke-linecap', - 'stroke-dashoffset', - 'stroke-linejoin', - 'stroke-miterlimit', - 'stroke-opacity', - 'stroke-width', - 'id', - 'paint-order', - 'vector-effect', - 'instantiated_by_use', - 'clip-path', -]; -/* _FROM_SVG_END_ */ - /** * @todo move to config when window is exported */ diff --git a/src/parser/attributes.ts b/src/parser/attributes.ts new file mode 100644 index 00000000000..f16412dcd5a --- /dev/null +++ b/src/parser/attributes.ts @@ -0,0 +1,25 @@ +/** + * Attributes parsed from all SVG elements + * @type array + */ +export const SHARED_ATTRIBUTES = [ + 'display', + 'transform', + 'fill', + 'fill-opacity', + 'fill-rule', + 'opacity', + 'stroke', + 'stroke-dasharray', + 'stroke-linecap', + 'stroke-dashoffset', + 'stroke-linejoin', + 'stroke-miterlimit', + 'stroke-opacity', + 'stroke-width', + 'id', + 'paint-order', + 'vector-effect', + 'instantiated_by_use', + 'clip-path', +]; diff --git a/src/parser/index.ts b/src/parser/index.ts index 18dffc9314f..02646cbfe65 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -1,5 +1,5 @@ -//@ts-nocheck import { fabric } from '../../HEADER'; +import { SHARED_ATTRIBUTES } from './attributes'; import { clipPaths, cssRules, gradientDefs } from './constants'; import { ElementsParser } from './elements_parser'; import { getCSSRules } from './getCSSRules'; @@ -15,6 +15,7 @@ import { parseSVGDocument } from './parseSVGDocument'; import { parseTransformAttribute } from './parseTransformAttribute'; Object.assign(fabric, { + SHARED_ATTRIBUTES, cssRules, gradientDefs, clipPaths, From a71cfc23d6d028600e490a13f20e8f335f9cc427 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:20:37 +0200 Subject: [PATCH 03/11] migrate --- src/shapes/circle.class.ts | 424 ++++++++++++++++++------------------- test/unit/circle.js | 2 +- 2 files changed, 211 insertions(+), 215 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index 690b98db097..a65300c8099 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -1,232 +1,228 @@ -//@ts-nocheck import { fabric } from '../../HEADER'; +import { SHARED_ATTRIBUTES } from '../parser/attributes'; +import { parseAttributes } from '../parser/parseAttributes'; +import { cos } from '../util/misc/cos'; +import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; +import { sin } from '../util/misc/sin'; import { FabricObject } from './fabricObject.class'; -const degreesToRadians = fabric.util.degreesToRadians; - /** * Circle class * @class Circle * @extends fabric.Object * @see {@link Circle#initialize} for constructor definition */ -const Circle = fabric.util.createClass( - FabricObject, - /** @lends Circle.prototype */ { - /** - * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged}) - * as well as for history (undo/redo) purposes - * @type Array - */ - stateProperties: FabricObject.prototype.stateProperties.concat( - 'radius', - 'startAngle', - 'endAngle' - ), - - /** - * Type of an object - * @type String - * @default - */ - type: 'circle', - - /** - * Radius of this circle - * @type Number - * @default - */ - radius: 0, - - /** - * degrees of start of the circle. - * probably will change to degrees in next major version - * @type Number 0 - 359 - * @default 0 - */ - startAngle: 0, - - /** - * End angle of the circle - * probably will change to degrees in next major version - * @type Number 1 - 360 - * @default 360 - */ - endAngle: 360, - - cacheProperties: FabricObject.prototype.cacheProperties.concat( - 'radius', - 'startAngle', - 'endAngle' - ), - - /** - * @private - * @param {String} key - * @param {*} value - * @return {Circle} thisArg - */ - _set: function (key, value) { - this.callSuper('_set', key, value); - - if (key === 'radius') { - this.setRadius(value); - } - - return this; - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx context to render on - */ - _render: function (ctx) { - ctx.beginPath(); - ctx.arc( - 0, - 0, - this.radius, - degreesToRadians(this.startAngle), - degreesToRadians(this.endAngle), - false - ); - this._renderPaintInOrder(ctx); - }, - - /** - * Returns horizontal radius of an object (according to how an object is scaled) - * @return {Number} - */ - getRadiusX: function () { - return this.get('radius') * this.get('scaleX'); - }, - - /** - * Returns vertical radius of an object (according to how an object is scaled) - * @return {Number} - */ - getRadiusY: function () { - return this.get('radius') * this.get('scaleY'); - }, - - /** - * Sets radius of an object (and updates width accordingly) - * @return {Circle} thisArg - */ - setRadius: function (value) { - this.radius = value; - return this.set('width', value * 2).set('height', value * 2); - }, - - /** - * Returns object representation of an instance - * @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 this.callSuper( - 'toObject', - ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude) - ); - }, - - /* _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 () { - const angle = (this.endAngle - this.startAngle) % 360; - - if (angle === 0) { - return [ - '\n', - ]; - } else { - const { radius } = this; - const start = degreesToRadians(this.startAngle), - end = degreesToRadians(this.endAngle), - startX = fabric.util.cos(start) * radius, - startY = fabric.util.sin(start) * radius, - endX = fabric.util.cos(end) * radius, - endY = fabric.util.sin(end) * radius, - largeFlag = angle > 180 ? '1' : '0'; - return [ - '\n', - ]; - } - }, - /* _TO_SVG_END_ */ +export class Circle extends FabricObject { + /** + * Radius of this circle + * @type Number + * @default + */ + radius: number; + + /** + * degrees of start of the circle. + * probably will change to degrees in next major version + * @type Number 0 - 359 + * @default 0 + */ + startAngle: number; + + /** + * End angle of the circle + * probably will change to degrees in next major version + * @type Number 1 - 360 + * @default 360 + */ + endAngle: number; + + /** + * @private + * @param {String} key + * @param {*} value + * @return {Circle} thisArg + */ + _set(key: string, value: any) { + super._set(key, value); + + if (key === 'radius') { + this.setRadius(value); + } + + return this; } -); -/* _FROM_SVG_START_ */ -/** - * List of attribute names to account for when parsing SVG element (used by {@link Circle.fromElement}) - * @static - * @memberOf Circle - * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement - */ -Circle.ATTRIBUTE_NAMES = ['cx', 'cy', 'r', ...fabric.SHARED_ATTRIBUTES]; - -/** - * Returns {@link Circle} instance from an SVG element - * @static - * @memberOf Circle - * @param {SVGElement} element Element to parse - * @param {Function} [callback] Options callback invoked after parsing is finished - * @param {Object} [options] Partial Circle object to default missing properties on the element. - * @throws {Error} If value of `r` attribute is missing or invalid - */ -Circle.fromElement = function (element, callback) { - const { - left = 0, - top = 0, - radius, - ...otherParsedAttributes - } = fabric.parseAttributes(element, Circle.ATTRIBUTE_NAMES); - - if (!radius || radius < 0) { - throw new Error( - 'value of `r` attribute is required and can not be negative' + /** + * @private + * @param {CanvasRenderingContext2D} ctx context to render on + */ + _render(ctx: CanvasRenderingContext2D) { + ctx.beginPath(); + ctx.arc( + 0, + 0, + this.radius, + degreesToRadians(this.startAngle), + degreesToRadians(this.endAngle), + false ); + this._renderPaintInOrder(ctx); } - // this probably requires to be fixed for default origins not being top/left. - callback( - new fabric.Circle({ - ...otherParsedAttributes, - radius, - left: left - radius, - top: top - radius, - }) - ); -}; + /** + * Returns horizontal radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusX(): number { + return this.get('radius') * this.get('scaleX'); + } -/* _FROM_SVG_END_ */ + /** + * Returns vertical radius of an object (according to how an object is scaled) + * @return {Number} + */ + getRadiusY(): number { + return this.get('radius') * this.get('scaleY'); + } -/** - * Returns {@link Circle} instance from an object representation - * @static - * @memberOf Circle - * @param {Object} object Object to create an instance from - * @returns {Promise} - */ -Circle.fromObject = (object) => FabricObject._fromObject(fabric.Circle, object); + /** + * Sets radius of an object (and updates width accordingly) + */ + setRadius(value: number) { + this.radius = value; + this.set({ width: value * 2, height: value * 2 }); + } + + /** + * Returns object representation of an instance + * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output + * @return {Object} object representation of an instance + */ + toObject(propertiesToInclude: (keyof this)[] = []): object { + return super.toObject([ + 'radius', + 'startAngle', + 'endAngle', + ...propertiesToInclude, + ]); + } + + /* _TO_SVG_START_ */ + + /** + * Returns svg representation of an instance + * @return {Array} an array of strings with the specific svg representation + * of the instance + */ + _toSVG(): (string | number)[] { + const angle = (this.endAngle - this.startAngle) % 360; + + if (angle === 0) { + return [ + '\n', + ]; + } else { + const { radius } = this; + const start = degreesToRadians(this.startAngle), + end = degreesToRadians(this.endAngle), + startX = cos(start) * radius, + startY = sin(start) * radius, + endX = cos(end) * radius, + endY = sin(end) * radius, + largeFlag = angle > 180 ? '1' : '0'; + return [ + '\n', + ]; + } + } + /* _TO_SVG_END_ */ + + /* _FROM_SVG_START_ */ + /** + * List of attribute names to account for when parsing SVG element (used by {@link Circle.fromElement}) + * @static + * @memberOf Circle + * @see: http://www.w3.org/TR/SVG/shapes.html#CircleElement + */ + static ATTRIBUTE_NAMES = ['cx', 'cy', 'r', ...SHARED_ATTRIBUTES]; + + /** + * Returns {@link Circle} instance from an SVG element + * @static + * @memberOf Circle + * @param {SVGElement} element Element to parse + * @param {Function} [callback] Options callback invoked after parsing is finished + * @param {Object} [options] Partial Circle object to default missing properties on the element. + * @throws {Error} If value of `r` attribute is missing or invalid + */ + static fromElement = function ( + element: SVGElement, + callback: (circle: Circle) => any + ) { + const { + left = 0, + top = 0, + radius, + ...otherParsedAttributes + } = parseAttributes(element, Circle.ATTRIBUTE_NAMES); + + if (!radius || radius < 0) { + throw new Error( + 'value of `r` attribute is required and can not be negative' + ); + } + + // this probably requires to be fixed for default origins not being top/left. + callback( + new Circle({ + ...otherParsedAttributes, + radius, + left: left - radius, + top: top - radius, + }) + ); + }; + + /* _FROM_SVG_END_ */ + + /** + * Returns {@link Circle} instance from an object representation + * @static + * @memberOf Circle + * @param {Object} object Object to create an instance from + * @returns {Promise} + */ + static fromObject = (object: object): Promise => + FabricObject._fromObject(Circle, object); +} + +Object.assign(Circle.prototype, { + type: 'circle', + radius: 0, + startAngle: 0, + endAngle: 360, + stateProperties: FabricObject.prototype.stateProperties.concat( + 'radius', + 'startAngle', + 'endAngle' + ), + cacheProperties: FabricObject.prototype.cacheProperties.concat( + 'radius', + 'startAngle', + 'endAngle' + ), +}); fabric.Circle = Circle; -export { Circle }; diff --git a/test/unit/circle.js b/test/unit/circle.js index b12575139dd..789a81ec506 100644 --- a/test/unit/circle.js +++ b/test/unit/circle.js @@ -56,7 +56,7 @@ assert.equal(circle.width, 20); assert.equal(circle.height, 20); - assert.equal(circle, circle.setRadius(20)); + circle.setRadius(20); assert.equal(circle.getRadiusX(), 20); assert.equal(circle.getRadiusY(), 20); From e169232e46d194729cfc95ee57a45eb1d3317fe2 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:24:04 +0200 Subject: [PATCH 04/11] Update circle.class.ts --- src/shapes/circle.class.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index a65300c8099..f474820c6ae 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -6,12 +6,6 @@ import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { sin } from '../util/misc/sin'; import { FabricObject } from './fabricObject.class'; -/** - * Circle class - * @class Circle - * @extends fabric.Object - * @see {@link Circle#initialize} for constructor definition - */ export class Circle extends FabricObject { /** * Radius of this circle @@ -40,7 +34,6 @@ export class Circle extends FabricObject { * @private * @param {String} key * @param {*} value - * @return {Circle} thisArg */ _set(key: string, value: any) { super._set(key, value); From b0d03793c19361006dfde7bc1ebd0eb66187391a Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:26:36 +0200 Subject: [PATCH 05/11] Update circle.class.ts --- src/shapes/circle.class.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index f474820c6ae..dcef31c82ef 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -1,6 +1,7 @@ import { fabric } from '../../HEADER'; import { SHARED_ATTRIBUTES } from '../parser/attributes'; import { parseAttributes } from '../parser/parseAttributes'; +import { TClassProperties } from '../typedefs'; import { cos } from '../util/misc/cos'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { sin } from '../util/misc/sin'; @@ -201,7 +202,7 @@ export class Circle extends FabricObject { FabricObject._fromObject(Circle, object); } -Object.assign(Circle.prototype, { +export const defaultValues: Partial> = { type: 'circle', radius: 0, startAngle: 0, @@ -216,6 +217,8 @@ Object.assign(Circle.prototype, { 'startAngle', 'endAngle' ), -}); +}; + +Object.assign(Circle.prototype, defaultValues); fabric.Circle = Circle; From 4e7e4985b8765791d5753313d4e3cfa903806b85 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:29:49 +0200 Subject: [PATCH 06/11] defaults --- src/shapes/circle.class.ts | 9 +++++---- src/shapes/object.class.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index dcef31c82ef..254cf359ccf 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -6,6 +6,7 @@ import { cos } from '../util/misc/cos'; import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; import { sin } from '../util/misc/sin'; import { FabricObject } from './fabricObject.class'; +import { fabricObjectDefaultValues } from './object.class'; export class Circle extends FabricObject { /** @@ -202,23 +203,23 @@ export class Circle extends FabricObject { FabricObject._fromObject(Circle, object); } -export const defaultValues: Partial> = { +export const circleDefaultValues: Partial> = { type: 'circle', radius: 0, startAngle: 0, endAngle: 360, - stateProperties: FabricObject.prototype.stateProperties.concat( + stateProperties: fabricObjectDefaultValues.stateProperties.concat( 'radius', 'startAngle', 'endAngle' ), - cacheProperties: FabricObject.prototype.cacheProperties.concat( + cacheProperties: fabricObjectDefaultValues.cacheProperties.concat( 'radius', 'startAngle', 'endAngle' ), }; -Object.assign(Circle.prototype, defaultValues); +Object.assign(Circle.prototype, circleDefaultValues); fabric.Circle = Circle; diff --git a/src/shapes/object.class.ts b/src/shapes/object.class.ts index ceeee9e14a7..2be5a720649 100644 --- a/src/shapes/object.class.ts +++ b/src/shapes/object.class.ts @@ -1991,7 +1991,7 @@ export class FabricObject extends ObjectGeometry { } } -const fabricObjectDefaultValues: TClassProperties = { +export const fabricObjectDefaultValues: TClassProperties = { type: 'object', originX: 'left', originY: 'top', From 403d791c9e07bfa387c4205fd2e4af17c8d63656 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:31:13 +0200 Subject: [PATCH 07/11] static --- src/shapes/circle.class.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/shapes/circle.class.ts b/src/shapes/circle.class.ts index 254cf359ccf..dfbb9c83cc1 100644 --- a/src/shapes/circle.class.ts +++ b/src/shapes/circle.class.ts @@ -162,10 +162,7 @@ export class Circle extends FabricObject { * @param {Object} [options] Partial Circle object to default missing properties on the element. * @throws {Error} If value of `r` attribute is missing or invalid */ - static fromElement = function ( - element: SVGElement, - callback: (circle: Circle) => any - ) { + static fromElement(element: SVGElement, callback: (circle: Circle) => any) { const { left = 0, top = 0, @@ -188,7 +185,7 @@ export class Circle extends FabricObject { top: top - radius, }) ); - }; + } /* _FROM_SVG_END_ */ @@ -199,8 +196,9 @@ export class Circle extends FabricObject { * @param {Object} object Object to create an instance from * @returns {Promise} */ - static fromObject = (object: object): Promise => - FabricObject._fromObject(Circle, object); + static fromObject(object: object): Promise { + return FabricObject._fromObject(Circle, object); + } } export const circleDefaultValues: Partial> = { From 575af883da4a1c5e4ac25645fb92cbd7a6a19966 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 10:33:05 +0200 Subject: [PATCH 08/11] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92517990158..d1d38a56c6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- chore(TS): migrate Circle [#8406](https://github.com/fabricjs/fabric.js/pull/8406) - chore(TS): convert Object interactivity mixin to its own class [#8401](https://github.com/fabricjs/fabric.js/pull/8401) - chore(TS): Convert controls e6/ts [#8400](https://github.com/fabricjs/fabric.js/pull/8400) - ci(): remove buggy changelog action in favor of `git diff` bash script + direct git how to merge `CHANGELOG.md` [#8309](https://github.com/fabricjs/fabric.js/pull/8346) From bf4981dae0ab20d01d7294f7fc5b3ffeacc01111 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 21:44:38 +0200 Subject: [PATCH 09/11] Update line.class.ts --- src/shapes/line.class.ts | 567 +++++++++++++++++++-------------------- 1 file changed, 277 insertions(+), 290 deletions(-) diff --git a/src/shapes/line.class.ts b/src/shapes/line.class.ts index f2eb40d4bc5..305ba4d7176 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); + } - /** - * 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 {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; + } + + /** + * @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))); - }; - /* _FROM_SVG_END_ */ + callback(new Line(points, { ...parsedAttributes, ...options })); + } /** - * 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; + +/* _FROM_SVG_START_ */ + +/* _FROM_SVG_END_ */ From bc592034c7b7ee07ce932aa9175d8559c752f6d7 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Mon, 31 Oct 2022 21:45:17 +0200 Subject: [PATCH 10/11] Update line.class.ts --- src/shapes/line.class.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shapes/line.class.ts b/src/shapes/line.class.ts index 305ba4d7176..5cfe0e99a6f 100644 --- a/src/shapes/line.class.ts +++ b/src/shapes/line.class.ts @@ -257,6 +257,8 @@ export class Line extends FabricObject { ]; } + /* _FROM_SVG_START_ */ + /** * List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement}) * @static @@ -285,6 +287,8 @@ export class Line extends FabricObject { callback(new Line(points, { ...parsedAttributes, ...options })); } + /* _FROM_SVG_END_ */ + /** * Returns Line instance from an object representation * @static @@ -321,7 +325,3 @@ export const lineDefaultValues: Partial> = { Object.assign(Line.prototype, lineDefaultValues); /** @todo TODO_JS_MIGRATION remove next line after refactoring build */ fabric.Line = Line; - -/* _FROM_SVG_START_ */ - -/* _FROM_SVG_END_ */ From d329bcb7910cb3dda06931bd5303fd18285b1743 Mon Sep 17 00:00:00 2001 From: ShaMan123 Date: Tue, 1 Nov 2022 00:23:55 +0200 Subject: [PATCH 11/11] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77fa33d7b28..80e0652aa97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [next] -- chore(TS): migrate Circle [#8406](https://github.com/fabricjs/fabric.js/pull/8406) +- chore(TS): migrate Line [#8413](https://github.com/fabricjs/fabric.js/pull/8413) - chore(TS): migrate Ellipse [#8408](https://github.com/fabricjs/fabric.js/pull/8408) - chore(TS): migrate Triangle to TS [#8410](https://github.com/fabricjs/fabric.js/pull/8410) - chore(TS): migrate Circle to TS [#8406](https://github.com/fabricjs/fabric.js/pull/8406)