diff --git a/CHANGELOG.md b/CHANGELOG.md index 69c628d..fa12f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [3.11.1] - 2025-01-01 + +- Created a utility to build animation properties and refactored the classes to make use of this utility to avoid code repetition + ## [3.11.0] - 2024-12-22 - Added a new option to set a CSS class to `IsometricCircle`, `IsometricPath`, `IsometricPentagram`, `IsometricRectangle`, `IsometricStarPolygon` and `IsometricText` diff --git a/src/@classes/abstract/IsometricGraphicAbstract/IsometricGraphicAbstract.ts b/src/@classes/abstract/IsometricGraphicAbstract/IsometricGraphicAbstract.ts index 10df040..e30e172 100644 --- a/src/@classes/abstract/IsometricGraphicAbstract/IsometricGraphicAbstract.ts +++ b/src/@classes/abstract/IsometricGraphicAbstract/IsometricGraphicAbstract.ts @@ -19,7 +19,8 @@ import { addSVGProperties, getSVGProperty, getPatternTransform, - isSVGProperty + isSVGProperty, + getAnimationProperties } from '@utils/svg'; import { uuid, round, getPointFromIsometricPoint } from '@utils/math'; import { IsometricElementAbstract } from '../IsometricElementAbstract'; @@ -162,23 +163,15 @@ export abstract class IsometricGraphicAbstract extends IsometricElementAbstract this.addAnimationBasicProperties(property, animation); - if (animation.values) { - addSVGProperties( - animation.element, - { - values: Array.isArray(animation.values) - ? animation.values.map((value: string | number): string => `${value}`).join(';') - : `${animation.values}` - } - ); - } else { - addSVGProperties( - animation.element, { - from: `${animation.from}`, - to: `${animation.to}` - } - ); - } + const properties = getAnimationProperties( + (value: string | number) => `${value}`, + animation + ); + + addSVGProperties( + animation.element, + properties + ); } }); diff --git a/src/@classes/abstract/IsometricStarPolygonAbstract/IsometricStarPolygonAbstract.ts b/src/@classes/abstract/IsometricStarPolygonAbstract/IsometricStarPolygonAbstract.ts index 59d5fcb..ebb1c26 100644 --- a/src/@classes/abstract/IsometricStarPolygonAbstract/IsometricStarPolygonAbstract.ts +++ b/src/@classes/abstract/IsometricStarPolygonAbstract/IsometricStarPolygonAbstract.ts @@ -8,8 +8,6 @@ import { IsometricPoint, LinePoint, CommandPoint, - SVGPositionableProperties, - SVGPentagramProperties, SVGPentagramAnimation, SVGAnimationObject } from '@types'; @@ -17,7 +15,8 @@ import { getSVGPath, translateCommandPoints, addSVGProperties, - isSVGProperty + isSVGProperty, + getAnimationProperties } from '@utils/svg'; import { IsometricShapeAbstract } from '@classes/abstract/IsometricShapeAbstract'; import { @@ -175,7 +174,7 @@ export abstract class IsometricStarPolygonAbstract extends IsometricShapeAbstrac if (!isNativeSVGProperty) { - const props = { + const props: GetStarPolygonAbstractPathArguments = { right: this.right, left: this.left, top: this.top, @@ -187,37 +186,11 @@ export abstract class IsometricStarPolygonAbstract extends IsometricShapeAbstrac if (Object.prototype.hasOwnProperty.call(props, animation.property)) { - const property = animation.property as SVGPositionableProperties | SVGPentagramProperties; - let properties: Record; - - if (animation.values) { - - if (Array.isArray(animation.values)) { - properties = { - values: animation.values.map((value: string | number): string => { - const modifiedArgs = { ...props }; - modifiedArgs[property] = +value; - return this.getPentagramPath(modifiedArgs); - }).join(';') - }; - } else { - const modifiedArgs = { ...props }; - modifiedArgs[property] = +animation.values; - properties = { - values: this.getPentagramPath(modifiedArgs) - }; - } - - } else { - const fromArgs = { ...props }; - const toArgs = { ...props }; - fromArgs[property] = +animation.from; - toArgs[property] = +animation.to; - properties = { - from: this.getPentagramPath(fromArgs), - to: this.getPentagramPath(toArgs) - }; - } + const properties: Record = getAnimationProperties( + this.getPentagramPath.bind(this), + animation, + props + ); if (!animation.element) { animation.element = document.createElementNS(SVG_NAMESPACE, SVG_ELEMENTS.animate) as SVGAnimateElement; diff --git a/src/@classes/public/IsometricCircle/IsometricCircle.ts b/src/@classes/public/IsometricCircle/IsometricCircle.ts index fc02a7a..d7bfee7 100644 --- a/src/@classes/public/IsometricCircle/IsometricCircle.ts +++ b/src/@classes/public/IsometricCircle/IsometricCircle.ts @@ -7,15 +7,14 @@ import { import { CommandPoint, SVGCircleAnimation, - SVGPositionableProperties, - SVGCircleProperties, SVGAnimationObject } from '@types'; import { getSVGPath, translateCommandPoints, addSVGProperties, - isSVGProperty + isSVGProperty, + getAnimationProperties } from '@utils/svg'; import { IsometricShapeAbstract } from '@classes/abstract/IsometricShapeAbstract'; import { @@ -121,7 +120,7 @@ export class IsometricCircle extends IsometricShapeAbstract { if (!isNativeSVGProperty) { - const props = { + const props: GetCirclePathArguments = { right: this.right, left: this.left, top: this.top, @@ -130,37 +129,11 @@ export class IsometricCircle extends IsometricShapeAbstract { if (Object.prototype.hasOwnProperty.call(props, animation.property)) { - const property = animation.property as SVGPositionableProperties | SVGCircleProperties; - let properties: Record; - - if (animation.values) { - - if (Array.isArray(animation.values)) { - properties = { - values: animation.values.map((value: string | number): string => { - const modifiedArgs = { ...props }; - modifiedArgs[property] = +value; - return this.getCirclePath(modifiedArgs); - }).join(';') - }; - } else { - const modifiedArgs = { ...props }; - modifiedArgs[property] = +animation.values; - properties = { - values: this.getCirclePath(modifiedArgs) - }; - } - - } else { - const fromArgs = { ...props }; - const toArgs = { ...props }; - fromArgs[property] = +animation.from; - toArgs[property] = +animation.to; - properties = { - from: this.getCirclePath(fromArgs), - to: this.getCirclePath(toArgs) - }; - } + const properties: Record = getAnimationProperties( + this.getCirclePath.bind(this), + animation, + props + ); if (!animation.element) { animation.element = document.createElementNS(SVG_NAMESPACE, SVG_ELEMENTS.animate) as SVGAnimateElement; diff --git a/src/@classes/public/IsometricPath/IsometricPath.ts b/src/@classes/public/IsometricPath/IsometricPath.ts index 761276d..607ef47 100644 --- a/src/@classes/public/IsometricPath/IsometricPath.ts +++ b/src/@classes/public/IsometricPath/IsometricPath.ts @@ -11,7 +11,8 @@ import { import { addSVGProperties, parseDrawCommands, - getSVGPath + getSVGPath, + getAnimationProperties } from '@utils/svg'; import { IsometricPathAbstract } from '@classes/abstract/IsometricPathAbstract'; import { IsometricPathProps } from './types'; @@ -31,8 +32,8 @@ export class IsometricPath extends IsometricPathAbstract { private commands: CommandPoint[]; private _autoclose: boolean; - private getPathFromCommands = (commands: string): string => getSVGPath( - parseDrawCommands(commands), + private getPathFromCommands = (commands: string | number): string => getSVGPath( + parseDrawCommands(`${commands}`), this.data.centerX, this.data.centerY, this.data.scale, @@ -45,22 +46,10 @@ export class IsometricPath extends IsometricPathAbstract { if (animation.property === 'path') { - let properties: Record; - - if (animation.values) { - properties = { - values: Array.isArray(animation.values) - ? animation.values.map((value: string | number): string => { - return this.getPathFromCommands(`${value}`); - }).join(';') - : this.getPathFromCommands(`${animation.values}`) - }; - } else { - properties = { - from: this.getPathFromCommands(`${animation.from}`), - to: this.getPathFromCommands(`${animation.to}`) - }; - } + const properties: Record = getAnimationProperties( + this.getPathFromCommands.bind(this), + animation + ); if (!animation.element) { animation.element = document.createElementNS(SVG_NAMESPACE, SVG_ELEMENTS.animate) as SVGAnimateElement; diff --git a/src/@classes/public/IsometricRectangle/IsometricRectangle.ts b/src/@classes/public/IsometricRectangle/IsometricRectangle.ts index caec1ab..dec922e 100644 --- a/src/@classes/public/IsometricRectangle/IsometricRectangle.ts +++ b/src/@classes/public/IsometricRectangle/IsometricRectangle.ts @@ -7,8 +7,6 @@ import { import { LinePoint, CommandPoint, - SVGPositionableProperties, - SVGRectangleProperties, SVGRectangleAnimation, SVGAnimationObject } from '@types'; @@ -16,7 +14,8 @@ import { getSVGPath, translateCommandPoints, addSVGProperties, - isSVGProperty + isSVGProperty, + getAnimationProperties } from '@utils/svg'; import { IsometricShapeAbstract } from '@classes/abstract/IsometricShapeAbstract'; import { @@ -92,7 +91,7 @@ export class IsometricRectangle extends IsometricShapeAbstract { if (!isNativeSVGProperty) { - const props = { + const props: GetRectanglePathArguments = { right: this.right, left: this.left, top: this.top, @@ -102,37 +101,11 @@ export class IsometricRectangle extends IsometricShapeAbstract { if (Object.prototype.hasOwnProperty.call(props, animation.property)) { - const property = animation.property as SVGPositionableProperties | SVGRectangleProperties; - let properties: Record; - - if (animation.values) { - - if (Array.isArray(animation.values)) { - properties = { - values: animation.values.map((value: string | number): string => { - const modifiedArgs = { ...props }; - modifiedArgs[property] = +value; - return this.getRectanglePath(modifiedArgs); - }).join(';') - }; - } else { - const modifiedArgs = { ...props }; - modifiedArgs[property] = +animation.values; - properties = { - values: this.getRectanglePath(modifiedArgs) - }; - } - - } else { - const fromArgs = { ...props }; - const toArgs = { ...props }; - fromArgs[property] = +animation.from; - toArgs[property] = +animation.to; - properties = { - from: this.getRectanglePath(fromArgs), - to: this.getRectanglePath(toArgs) - }; - } + const properties: Record = getAnimationProperties( + this.getRectanglePath.bind(this), + animation, + props, + ); if (!animation.element) { animation.element = document.createElementNS(SVG_NAMESPACE, SVG_ELEMENTS.animate) as SVGAnimateElement; diff --git a/src/@utils/svg.ts b/src/@utils/svg.ts index 1f82178..5f5219e 100644 --- a/src/@utils/svg.ts +++ b/src/@utils/svg.ts @@ -7,6 +7,7 @@ import { SVGProperties, SVGNativeProperties, SVGProps, + SVGAnimationObject, AddEventListenerCallback } from '@types'; import { @@ -239,4 +240,45 @@ export const elementHasSVGParent = (element: Node): boolean => { return elementHasSVGParent(element.parentNode); } return false; +}; + +export const getAnimationProperties =

( + getPath: (...args: unknown[]) => string, + animation: SVGAnimationObject, + props?: P +): Record => { + + let properties: Record; + + const localGetPath = (value: string | number): string => { + if (props) { + return getPath({ + ...props, + [animation.property]: +value + }); + } + return getPath(value); + }; + + if (animation.values) { + if (Array.isArray(animation.values)) { + properties = { + values: animation.values.map((value: string | number): string => { + return localGetPath(value); + }).join(';') + }; + } else { + properties = { + values: localGetPath(animation.values) + }; + } + } else { + properties = { + from: localGetPath(animation.from), + to: localGetPath(animation.to) + }; + } + + return properties; + }; \ No newline at end of file