diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ec5e05feb9..228c17d831c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [next] +- 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) - 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) diff --git a/src/shapes/rect.class.ts b/src/shapes/rect.class.ts index 4959c1da68c..9de777e0455 100644 --- a/src/shapes/rect.class.ts +++ b/src/shapes/rect.class.ts @@ -1,224 +1,209 @@ -//@ts-nocheck import { fabric } from '../../HEADER'; import { kRect } from '../constants'; -/** - * Rectangle class - * @class Rect - * @extends fabric.Object - * @return {Rect} thisArg - * @see {@link Rect#initialize} for constructor definition - */ -const Rect = fabric.util.createClass( - fabric.Object, - /** @lends Rect.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: fabric.Object.prototype.stateProperties.concat('rx', 'ry'), - - /** - * Type of an object - * @type String - * @default - */ - type: 'rect', - - /** - * Horizontal border radius - * @type Number - * @default - */ - rx: 0, - - /** - * Vertical border radius - * @type Number - * @default - */ - ry: 0, - - cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'), - - /** - * Constructor - * @param {Object} [options] Options object - * @return {Object} thisArg - */ - initialize: function (options) { - this.callSuper('initialize', options); - this._initRxRy(); - }, - - /** - * Initializes rx/ry attributes - * @private - */ - _initRxRy: function () { - const { rx, ry } = this; - if (rx && !ry) { - this.ry = rx; - } else if (ry && !rx) { - this.rx = ry; - } - }, - - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _render: function (ctx) { - // 1x1 case (used in spray brush) optimization was removed because - // with caching and higher zoom level this makes more damage than help - const { width: w, height: h } = this; - const x = -w / 2; - const y = -h / 2; - const rx = this.rx ? Math.min(this.rx, w / 2) : 0; - const ry = this.ry ? Math.min(this.ry, h / 2) : 0; - const isRounded = rx !== 0 || ry !== 0; - - ctx.beginPath(); - - ctx.moveTo(x + rx, y); - - ctx.lineTo(x + w - rx, y); - isRounded && - ctx.bezierCurveTo( - x + w - kRect * rx, - y, - x + w, - y + kRect * ry, - x + w, - y + ry - ); - - ctx.lineTo(x + w, y + h - ry); - isRounded && - ctx.bezierCurveTo( - x + w, - y + h - kRect * ry, - x + w - kRect * rx, - y + h, - x + w - rx, - y + h - ); - - ctx.lineTo(x + rx, y + h); - isRounded && - ctx.bezierCurveTo( - x + kRect * rx, - y + h, - x, - y + h - kRect * ry, - x, - y + h - ry - ); - - ctx.lineTo(x, y + ry); - isRounded && - ctx.bezierCurveTo(x, y + kRect * ry, x + kRect * rx, y, x + rx, y); - - ctx.closePath(); - - this._renderPaintInOrder(ctx); - }, - - /** - * 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', - ['rx', 'ry'].concat(propertiesToInclude) +import { SHARED_ATTRIBUTES } from '../parser/attributes'; +import { parseAttributes } from '../parser/parseAttributes'; +import { TClassProperties } from '../typedefs'; +import { FabricObject } from './fabricObject.class'; +import { fabricObjectDefaultValues } from './object.class'; + +export class Rect extends FabricObject { + /** + * Horizontal border radius + * @type Number + * @default + */ + rx: number; + + /** + * Vertical border radius + * @type Number + * @default + */ + ry: number; + + /** + * Constructor + * @param {Object} [options] Options object + * @return {Object} thisArg + */ + constructor(options: Record) { + super(options); + this._initRxRy(); + } + + /** + * Initializes rx/ry attributes + * @private + */ + _initRxRy() { + const { rx, ry } = this; + if (rx && !ry) { + this.ry = rx; + } else if (ry && !rx) { + this.rx = ry; + } + } + + /** + * @private + * @param {CanvasRenderingContext2D} ctx Context to render on + */ + _render(ctx: CanvasRenderingContext2D) { + const { width: w, height: h } = this; + const x = -w / 2; + const y = -h / 2; + const rx = this.rx ? Math.min(this.rx, w / 2) : 0; + const ry = this.ry ? Math.min(this.ry, h / 2) : 0; + const isRounded = rx !== 0 || ry !== 0; + + ctx.beginPath(); + + ctx.moveTo(x + rx, y); + + ctx.lineTo(x + w - rx, y); + isRounded && + ctx.bezierCurveTo( + x + w - kRect * rx, + y, + x + w, + y + kRect * ry, + x + w, + y + ry + ); + + ctx.lineTo(x + w, y + h - ry); + isRounded && + ctx.bezierCurveTo( + x + w, + y + h - kRect * ry, + x + w - kRect * rx, + y + h, + x + w - rx, + y + h + ); + + ctx.lineTo(x + rx, y + h); + isRounded && + ctx.bezierCurveTo( + x + kRect * rx, + y + h, + x, + y + h - kRect * ry, + x, + y + h - ry ); - }, - - /* _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 { width, height, rx, ry } = this; - return [ - '\n', - ]; - }, - /* _TO_SVG_END_ */ + + ctx.lineTo(x, y + ry); + isRounded && + ctx.bezierCurveTo(x, y + kRect * ry, x + kRect * rx, y, x + rx, y); + + ctx.closePath(); + + this._renderPaintInOrder(ctx); + } + + /** + * 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)[] = []) { + return super.toObject(['rx', 'ry', ...propertiesToInclude]); + } + + /** + * Returns svg representation of an instance + * @return {Array} an array of strings with the specific svg representation + * of the instance + */ + _toSVG() { + const { width, height, rx, ry } = this; + return [ + '\n`, + ]; } -); - -/* _FROM_SVG_START_ */ -/** - * List of attribute names to account for when parsing SVG element (used by `Rect.fromElement`) - * @static - * @memberOf Rect - * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement - */ -Rect.ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat( - 'x y rx ry width height'.split(' ') -); - -/** - * Returns {@link Rect} instance from an SVG element - * @static - * @memberOf Rect - * @param {SVGElement} element Element to parse - * @param {Function} callback callback function invoked after parsing - * @param {Object} [options] Options object - */ -Rect.fromElement = function (element, callback, options = {}) { - if (!element) { - return callback(null); + + /** + * List of attribute names to account for when parsing SVG element (used by `Rect.fromElement`) + * @static + * @memberOf Rect + * @see: http://www.w3.org/TR/SVG/shapes.html#RectElement + */ + static ATTRIBUTE_NAMES = [ + ...SHARED_ATTRIBUTES, + 'x', + 'y', + 'rx', + 'ry', + 'width', + 'height', + ]; + + /** + * Returns {@link Rect} instance from an object representation + * @static + * @memberOf Rect + * @param {Object} object Object to create an instance from + * @returns {Promise} + */ + static fromObject(object: any) { + return FabricObject._fromObject(Rect, object); + } + + /* _FROM_SVG_START_ */ + + /** + * Returns {@link Rect} instance from an SVG element + * @static + * @memberOf Rect + * @param {SVGElement} element Element to parse + * @param {Function} callback callback function invoked after parsing + * @param {Object} [options] Options object + */ + static fromElement( + element: SVGElement, + callback: (rect: Rect | null) => void, + options = {} + ) { + if (!element) { + return callback(null); + } + const { + left = 0, + top = 0, + width = 0, + height = 0, + visible = true, + ...restOfparsedAttributes + } = parseAttributes(element, Rect.ATTRIBUTE_NAMES); + + const rect = new Rect({ + ...options, + ...restOfparsedAttributes, + left, + top, + width, + height, + visible: Boolean(visible && width && height), + }); + callback(rect); } - const { - left = 0, - top = 0, - width = 0, - height = 0, - visible = true, - ...restOfparsedAttributes - } = fabric.parseAttributes(element, Rect.ATTRIBUTE_NAMES); - - const rect = new Rect({ - ...options, - ...restOfparsedAttributes, - left, - top, - width, - height, - visible: Boolean(visible && width && height), - }); - callback(rect); + + /* _FROM_SVG_END_ */ +} + +export const rectDefaultValues: Partial> = { + stateProperties: fabricObjectDefaultValues.stateProperties.concat('rx', 'ry'), + type: 'rect', + rx: 0, + ry: 0, + cacheProperties: fabricObjectDefaultValues.cacheProperties.concat('rx', 'ry'), }; -/* _FROM_SVG_END_ */ -/** - * Returns {@link Rect} instance from an object representation - * @static - * @memberOf Rect - * @param {Object} object Object to create an instance from - * @returns {Promise} - */ -Rect.fromObject = (object) => fabric.Object._fromObject(Rect, object); +Object.assign(Rect.prototype, rectDefaultValues); fabric.Rect = Rect; -export { Rect };