155 lines
3.4 KiB
TypeScript
155 lines
3.4 KiB
TypeScript
import { Point } from './types';
|
|
|
|
interface DOMTransformInit {
|
|
x?: number;
|
|
y?: number;
|
|
rotationX?: number;
|
|
rotationY?: number;
|
|
rotationZ?: number;
|
|
}
|
|
|
|
/**
|
|
* Represents a 2D transform with position and rotation,
|
|
* capable of transforming points between local and parent coordinate spaces.
|
|
*/
|
|
export class DOMTransform {
|
|
// Private properties for position and rotation
|
|
#x: number;
|
|
#y: number;
|
|
#rotationX: number;
|
|
#rotationY: number;
|
|
#rotationZ: number;
|
|
|
|
// Internal transformation matrices
|
|
#transformMatrix: DOMMatrix;
|
|
#inverseMatrix: DOMMatrix;
|
|
|
|
constructor(init: DOMTransformInit = {}) {
|
|
this.#x = init.x ?? 0;
|
|
this.#y = init.y ?? 0;
|
|
this.#rotationX = init.rotationX ?? 0;
|
|
this.#rotationY = init.rotationY ?? 0;
|
|
this.#rotationZ = init.rotationZ ?? 0;
|
|
|
|
// Initialize with identity matrices
|
|
this.#transformMatrix = new DOMMatrix();
|
|
this.#inverseMatrix = new DOMMatrix();
|
|
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
get x(): number {
|
|
return this.#x;
|
|
}
|
|
set x(value: number) {
|
|
this.#x = value;
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
get y(): number {
|
|
return this.#y;
|
|
}
|
|
set y(value: number) {
|
|
this.#y = value;
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
get rotationX(): number {
|
|
return this.#rotationX;
|
|
}
|
|
set rotationX(value: number) {
|
|
this.#rotationX = value;
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
get rotationY(): number {
|
|
return this.#rotationY;
|
|
}
|
|
set rotationY(value: number) {
|
|
this.#rotationY = value;
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
get rotationZ(): number {
|
|
return this.#rotationZ;
|
|
}
|
|
set rotationZ(value: number) {
|
|
this.#rotationZ = value;
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
get rotation(): number {
|
|
return this.#rotationZ;
|
|
}
|
|
set rotation(value: number) {
|
|
this.#rotationZ = value;
|
|
this.#updateMatrices();
|
|
}
|
|
|
|
// Matrix accessors
|
|
get matrix(): DOMMatrix {
|
|
return this.#transformMatrix;
|
|
}
|
|
get inverse(): DOMMatrix {
|
|
return this.#inverseMatrix;
|
|
}
|
|
|
|
/**
|
|
* Converts a point from parent space to local space.
|
|
*/
|
|
toPoint(point: Point): Point {
|
|
// Transform using DOMMatrix directly without DOMPoint
|
|
const { a, b, c, d, e, f } = this.#inverseMatrix;
|
|
return {
|
|
x: point.x * a + point.y * c + e,
|
|
y: point.x * b + point.y * d + f,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Converts a point from local space to parent space.
|
|
*/
|
|
toInversePoint(point: Point): Point {
|
|
const { a, b, c, d, e, f } = this.#transformMatrix;
|
|
return {
|
|
x: point.x * a + point.y * c + e,
|
|
y: point.x * b + point.y * d + f,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Generates a CSS transform string representing the transformation.
|
|
*/
|
|
toCssString(): string {
|
|
return this.#transformMatrix.toString();
|
|
}
|
|
|
|
/**
|
|
* Converts the transform's properties to a JSON serializable object.
|
|
*/
|
|
toJSON() {
|
|
return {
|
|
x: this.x,
|
|
y: this.y,
|
|
rotationX: this.rotationX,
|
|
rotationY: this.rotationY,
|
|
rotationZ: this.rotationZ,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Updates the transformation matrices based on the current position and rotation.
|
|
*/
|
|
#updateMatrices() {
|
|
// Create a fresh identity matrix
|
|
this.#transformMatrix = new DOMMatrix()
|
|
.translate(this.#x, this.#y)
|
|
.rotate(0, 0, this.#rotationZ)
|
|
.rotate(0, this.#rotationY, 0)
|
|
.rotate(this.#rotationX, 0, 0);
|
|
|
|
// DOMMatrix has built-in inverse calculation
|
|
this.#inverseMatrix = this.#transformMatrix.inverse();
|
|
}
|
|
}
|