123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- import { Point } from "./objects/point";
- const PI_2 = Math.PI * 2;
- /**
- * | a | c | tx|
- * | b | d | ty|
- * | 0 | 0 | 1 |
- * ```
- */
- export class Matrix {
- a = 1;
- b = 0;
- c = 0;
- d = 1;
- tx = 0;
- ty = 0;
- constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
- this.a = a;
- this.b = b;
- this.c = c;
- this.d = d;
- this.tx = tx;
- this.ty = ty;
- }
- static createFromDiv(div: HTMLElement) {
- const out = new Matrix();
- out.setFormDiv(div);
- return out;
- }
- //matrix(1,0,0,1,0,0)
- static createFromMatrixStr(str: string) {
- const out = new Matrix();
- out.setMatrixStr(str);
- return out;
- }
- setMatrixStr(transformMatrix:string) {
- const values = transformMatrix.split("(")[1].split(")")[0].split(",");
- this.a = +values[0];
- this.b = +values[1];
- this.c = +values[2];
- this.d = +values[3];
- this.tx = +values[4];
- this.ty = +values[5];
- }
- setFormDiv(div: HTMLElement) {
- let transformMatrix = window
- .getComputedStyle(div)
- .getPropertyValue("transform");
- if (!transformMatrix || transformMatrix === "none") {
- transformMatrix = "matrix(1,0,0,1,0,0)";
- }
- this.setMatrixStr(transformMatrix);
- }
- applyDiv(div: HTMLElement) {
- div.style.transform = this.getMatrixStr();
- div.style.transformOrigin = "0 0";
- return this;
- }
- getMatrixStr() {
- return `matrix(${this.a},${this.b},${this.c},${this.d},${this.tx},${this.ty})`;
- }
-
- fromArray(array: number[]) {
- this.a = array[0];
- this.b = array[1];
- this.c = array[3];
- this.d = array[4];
- this.tx = array[2];
- this.ty = array[5];
- }
- set(a: number, b: number, c: number, d: number, tx: number, ty: number) {
- this.a = a;
- this.b = b;
- this.c = c;
- this.d = d;
- this.tx = tx;
- this.ty = ty;
- return this;
- }
- array = new Float32Array(9);
- toArray(transpose: boolean, out: any) {
- if (!this.array) {
- this.array = new Float32Array(9);
- }
- const array = out || this.array;
- if (transpose) {
- array[0] = this.a;
- array[1] = this.b;
- array[2] = 0;
- array[3] = this.c;
- array[4] = this.d;
- array[5] = 0;
- array[6] = this.tx;
- array[7] = this.ty;
- array[8] = 1;
- } else {
- array[0] = this.a;
- array[1] = this.c;
- array[2] = this.tx;
- array[3] = this.b;
- array[4] = this.d;
- array[5] = this.ty;
- array[6] = 0;
- array[7] = 0;
- array[8] = 1;
- }
- return array;
- }
- apply(pos: Point, newPos?: Point) {
- newPos = newPos || new Point();
- const x = pos.x;
- const y = pos.y;
- newPos.x = this.a * x + this.c * y + this.tx;
- newPos.y = this.b * x + this.d * y + this.ty;
- return newPos;
- }
- applyInverse(pos: Point, newPos?: Point) {
- newPos = newPos || new Point();
- const id = 1 / (this.a * this.d + this.c * -this.b);
- const x = pos.x;
- const y = pos.y;
- newPos.x =
- this.d * id * x +
- -this.c * id * y +
- (this.ty * this.c - this.tx * this.d) * id;
- newPos.y =
- this.a * id * y +
- -this.b * id * x +
- (-this.ty * this.a + this.tx * this.b) * id;
- return newPos;
- }
- translate(x: number, y: number) {
- this.tx += x;
- this.ty += y;
- return this;
- }
- scale(x: number, y: number) {
- this.a *= x;
- this.d *= y;
- this.c *= x;
- this.b *= y;
- this.tx *= x;
- this.ty *= y;
- return this;
- }
- getScale() {
- const a = this.a, b = this.b, c = this.c, d = this.d;
- const x = Math.sqrt((a * a) + (b * b));
- const y = Math.sqrt((c * c) + (d * d));
- return {x, y};
- }
-
- rotate(angle: number) {
- const cos = Math.cos(angle);
- const sin = Math.sin(angle);
- const a1 = this.a;
- const c1 = this.c;
- const tx1 = this.tx;
- this.a = a1 * cos - this.b * sin;
- this.b = a1 * sin + this.b * cos;
- this.c = c1 * cos - this.d * sin;
- this.d = c1 * sin + this.d * cos;
- this.tx = tx1 * cos - this.ty * sin;
- this.ty = tx1 * sin + this.ty * cos;
- return this;
- }
- append(matrix: Matrix) {
- const a1 = this.a;
- const b1 = this.b;
- const c1 = this.c;
- const d1 = this.d;
- this.a = matrix.a * a1 + matrix.b * c1;
- this.b = matrix.a * b1 + matrix.b * d1;
- this.c = matrix.c * a1 + matrix.d * c1;
- this.d = matrix.c * b1 + matrix.d * d1;
- this.tx = matrix.tx * a1 + matrix.ty * c1 + this.tx;
- this.ty = matrix.tx * b1 + matrix.ty * d1 + this.ty;
- return this;
- }
- setTransform(
- x: number,
- y: number,
- pivotX: number,
- pivotY: number,
- scaleX: number,
- scaleY: number,
- rotation: number,
- skewX: number,
- skewY: number
- ) {
- this.a = Math.cos(rotation + skewY) * scaleX;
- this.b = Math.sin(rotation + skewY) * scaleX;
- this.c = -Math.sin(rotation - skewX) * scaleY;
- this.d = Math.cos(rotation - skewX) * scaleY;
- this.tx = x - (pivotX * this.a + pivotY * this.c);
- this.ty = y - (pivotX * this.b + pivotY * this.d);
- return this;
- }
- prepend(matrix: Matrix) {
- const tx1 = this.tx;
- if (matrix.a !== 1 || matrix.b !== 0 || matrix.c !== 0 || matrix.d !== 1) {
- const a1 = this.a;
- const c1 = this.c;
- this.a = a1 * matrix.a + this.b * matrix.c;
- this.b = a1 * matrix.b + this.b * matrix.d;
- this.c = c1 * matrix.a + this.d * matrix.c;
- this.d = c1 * matrix.b + this.d * matrix.d;
- }
- this.tx = tx1 * matrix.a + this.ty * matrix.c + matrix.tx;
- this.ty = tx1 * matrix.b + this.ty * matrix.d + matrix.ty;
- return this;
- }
- decompose(transform:any)
- {
- // sort out rotation / skew..
- const a = this.a;
- const b = this.b;
- const c = this.c;
- const d = this.d;
- const skewX = -Math.atan2(-c, d);
- const skewY = Math.atan2(b, a);
- const delta = Math.abs(skewX + skewY);
- transform.rotation = skewY;
- transform.skew.x = transform.skew.y = 0;
- if (delta < 0.00001 || Math.abs(PI_2 - delta) < 0.00001)
- {
- transform.rotation = skewY;
- transform.skew.x = transform.skew.y = 0;
- }
- else
- {
- transform.rotation = 0;
- transform.skew.x = skewX;
- transform.skew.y = skewY;
- }
- // next set scale
- transform.scale.x = Math.sqrt((a * a) + (b * b));
- transform.scale.y = Math.sqrt((c * c) + (d * d));
- // next set position
- transform.position.x = this.tx;
- transform.position.y = this.ty;
- return transform;
- }
- invert() {
- const a1 = this.a;
- const b1 = this.b;
- const c1 = this.c;
- const d1 = this.d;
- const tx1 = this.tx;
- const n = a1 * d1 - b1 * c1;
- this.a = d1 / n;
- this.b = -b1 / n;
- this.c = -c1 / n;
- this.d = a1 / n;
- this.tx = (c1 * this.ty - d1 * tx1) / n;
- this.ty = -(a1 * this.ty - b1 * tx1) / n;
- return this;
- }
- identity() {
- this.a = 1;
- this.b = 0;
- this.c = 0;
- this.d = 1;
- this.tx = 0;
- this.ty = 0;
- return this;
- }
- clone() {
- const matrix = new Matrix();
- matrix.a = this.a;
- matrix.b = this.b;
- matrix.c = this.c;
- matrix.d = this.d;
- matrix.tx = this.tx;
- matrix.ty = this.ty;
- return matrix;
- }
- copyTo(matrix: Matrix) {
- matrix.a = this.a;
- matrix.b = this.b;
- matrix.c = this.c;
- matrix.d = this.d;
- matrix.tx = this.tx;
- matrix.ty = this.ty;
- return matrix;
- }
- copyFrom(matrix: Matrix) {
- this.a = matrix.a;
- this.b = matrix.b;
- this.c = matrix.c;
- this.d = matrix.d;
- this.tx = matrix.tx;
- this.ty = matrix.ty;
- return this;
- }
- static get IDENTITY() {
- return new Matrix();
- }
- static get TEMP_MATRIX() {
- return new Matrix();
- }
- }
|