Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(layout): add Layout class and enums for canvas fit and align… #358

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions js/src/layout/Layout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { Fit, Alignment } from "./enums";
import type { LayoutParameters } from "./types";
import * as rc from "./../rive_advanced.mjs";

/**
* Represents the layout parameters for a Rive animation in a HTML canvas.
* The `Layout` class provides methods to manage the fit and alignment of the
* Rive animation within the canvas.
*/
export class Layout {
/**
* Caches the runtime fit value of the Rive animation to save computation cycles.
*
* Runtime fit and alignment are accessed every frame, so we cache their values to save cycles.
*/
private cachedRuntimeFit: rc.Fit;
private cachedRuntimeAlignment: rc.Alignment;

/**
* The fit mode for the Rive animation within the canvas. This determines how the animation is scaled to fit the canvas.
*/
public readonly fit: Fit;
/**
* The alignment mode for the Rive animation within the canvas. This determines how the animation is positioned within the canvas.
*/
public readonly alignment: Alignment;
/**
* The minimum x-coordinate of the layout.
*/
public readonly minX: number;
/**
* The minimum y-coordinate of the layout.
*/
public readonly minY: number;
/**
* The maximum x-coordinate of the layout.
*/
public readonly maxX: number;
/**
* The maximum y-coordinate of the layout.
*/
public readonly maxY: number;

/**
* Constructs a new `Layout` instance with the provided parameters.
*/
constructor(params?: LayoutParameters) {
this.fit = params?.fit ?? Fit.Contain;
this.alignment = params?.alignment ?? Alignment.Center;
this.minX = params?.minX ?? 0;
this.minY = params?.minY ?? 0;
this.maxX = params?.maxX ?? 0;
this.maxY = params?.maxY ?? 0;
}

/**
* Alternative constructor to build a Layout from an interface/object.
* @deprecated
*/
static new({
fit,
alignment,
minX,
minY,
maxX,
maxY,
}: LayoutParameters): Layout {
console.warn(
"This function is deprecated: please use `new Layout({})` instead"
);
return new Layout({ fit, alignment, minX, minY, maxX, maxY });
}

/**
* Makes a copy of the layout, replacing any specified parameters
*/
public copyWith({
fit,
alignment,
minX,
minY,
maxX,
maxY,
}: LayoutParameters): Layout {
return new Layout({
fit: fit ?? this.fit,
alignment: alignment ?? this.alignment,
minX: minX ?? this.minX,
minY: minY ?? this.minY,
maxX: maxX ?? this.maxX,
maxY: maxY ?? this.maxY,
});
}

/**
* Returns the appropriate Fit value for the Rive runtime based on the `fit` property of the Layout.
* The result is cached to avoid unnecessary conversions.
* @param rive - The RiveCanvas instance to use for the Rive runtime fit values.
* @returns The Fit value corresponding to the `fit` property of the Layout.
*/
public runtimeFit(rive: rc.RiveCanvas): rc.Fit {
if (this.cachedRuntimeFit) return this.cachedRuntimeFit;

let fit;
if (this.fit === Fit.Cover) fit = rive.Fit.cover;
else if (this.fit === Fit.Contain) fit = rive.Fit.contain;
else if (this.fit === Fit.Fill) fit = rive.Fit.fill;
else if (this.fit === Fit.FitWidth) fit = rive.Fit.fitWidth;
else if (this.fit === Fit.FitHeight) fit = rive.Fit.fitHeight;
else if (this.fit === Fit.ScaleDown) fit = rive.Fit.scaleDown;
else fit = rive.Fit.none;

this.cachedRuntimeFit = fit;
return fit;
}

/**
* Returns the appropriate Alignment value for the Rive runtime based on the `alignment` property of the Layout.
* The result is cached to avoid unnecessary conversions.
* @param rive - The RiveCanvas instance to use for the Rive runtime alignment values.
* @returns The Alignment value corresponding to the `alignment` property of the Layout.
*/
public runtimeAlignment(rive: rc.RiveCanvas): rc.Alignment {
if (this.cachedRuntimeAlignment) return this.cachedRuntimeAlignment;

let alignment;
if (this.alignment === Alignment.TopLeft)
alignment = rive.Alignment.topLeft;
else if (this.alignment === Alignment.TopCenter)
alignment = rive.Alignment.topCenter;
else if (this.alignment === Alignment.TopRight)
alignment = rive.Alignment.topRight;
else if (this.alignment === Alignment.CenterLeft)
alignment = rive.Alignment.centerLeft;
else if (this.alignment === Alignment.CenterRight)
alignment = rive.Alignment.centerRight;
else if (this.alignment === Alignment.BottomLeft)
alignment = rive.Alignment.bottomLeft;
else if (this.alignment === Alignment.BottomCenter)
alignment = rive.Alignment.bottomCenter;
else if (this.alignment === Alignment.BottomRight)
alignment = rive.Alignment.bottomRight;
else alignment = rive.Alignment.center;

this.cachedRuntimeAlignment = alignment;
return alignment;
}
}
41 changes: 41 additions & 0 deletions js/src/layout/enums/Alignment.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Enum representing the different alignment options for the canvas.
*/
export enum Alignment {
/**
* Aligns the canvas content to the center.
*/
Center = "center",
/**
* Aligns the canvas content to the top-left corner.
*/
TopLeft = "topLeft",
/**
* Aligns the canvas content to the top center.
*/
TopCenter = "topCenter",
/**
* Aligns the canvas content to the top-right corner.
*/
TopRight = "topRight",
/**
* Aligns the canvas content to the center-left.
*/
CenterLeft = "centerLeft",
/**
* Aligns the canvas content to the center-right.
*/
CenterRight = "centerRight",
/**
* Aligns the canvas content to the bottom-left corner.
*/
BottomLeft = "bottomLeft",
/**
* Aligns the canvas content to the bottom center.
*/
BottomCenter = "bottomCenter",
/**
* Aligns the canvas content to the bottom-right corner.
*/
BottomRight = "bottomRight",
}
33 changes: 33 additions & 0 deletions js/src/layout/enums/Fit.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Enum representing the different fit options for a canvas element.
*/
export enum Fit {
/**
* Scales the image to fill the entire canvas, maintaining aspect ratio.
*/
Cover = "cover",
/**
* Scales the image to fit within the canvas, maintaining aspect ratio.
*/
Contain = "contain",
/**
* Stretches the image to fill the entire canvas, ignoring aspect ratio.
*/
Fill = "fill",
/**
* Scales the image to fit the width of the canvas, maintaining aspect ratio.
*/
FitWidth = "fitWidth",
/**
* Scales the image to fit the height of the canvas, maintaining aspect ratio.
*/
FitHeight = "fitHeight",
/**
* Displays the image at its original size.
*/
None = "none",
/**
* Scales down the image if it's larger than the canvas, but never scales it up.
*/
ScaleDown = "scaleDown",
}
2 changes: 2 additions & 0 deletions js/src/layout/enums/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Alignment } from "./Alignment.enum";
export { Fit } from "./Fit.enum";
3 changes: 3 additions & 0 deletions js/src/layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./Layout";
export * from "./enums";
export * from "./types";
31 changes: 31 additions & 0 deletions js/src/layout/types/LayoutParameters.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Fit, Alignment } from "../enums";

/**
* Interface for the Layout static method contractor
*/
export interface LayoutParameters {
/**
* The fit mode for the layout.
*/
fit?: Fit;
/**
* The alignment mode for the layout.
*/
alignment?: Alignment;
/**
* The minimum X coordinate for the layout.
*/
minX?: number;
/**
* The minimum Y coordinate for the layout.
*/
minY?: number;
/**
* The maximum X coordinate for the layout.
*/
maxX?: number;
/**
* The maximum Y coordinate for the layout.
*/
maxY?: number;
}
1 change: 1 addition & 0 deletions js/src/layout/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type { LayoutParameters } from "./LayoutParameters.type";
Loading