UNPKG

3.8 kBPlain TextView Raw
1/**
2 * based on
3 * https://github.com/CreateJS/EaselJS/blob/631cdffb85eff9413dab43b4676f059b4232d291/src/easeljs/geom/Matrix2D.js
4 */
5const DEG_TO_RAD = Math.PI / 180;
6
7export const identity: [number, number, number, number, number, number] = [
8 1,
9 0,
10 0,
11 1,
12 0,
13 0,
14];
15
16let a = 1;
17let b = 0;
18let c = 0;
19let d = 1;
20let tx = 0;
21let ty = 0;
22let hasInitialState = true;
23
24/**
25 * Represents an affine transformation matrix, and provides tools for concatenating transforms.
26 *
27 * This matrix can be visualized as:
28 *
29 * [ a c tx
30 * b d ty
31 * 0 0 1 ]
32 *
33 * Note the locations of b and c.
34 **/
35
36/**
37 * Reset current matrix to an identity matrix.
38 * @method reset
39 **/
40export function reset() {
41 if (hasInitialState) {
42 return;
43 }
44 a = d = 1;
45 b = c = tx = ty = 0;
46 hasInitialState = true;
47}
48
49/**
50 * Returns an array with current matrix values.
51 * @method toArray
52 * @return {Array} an array with current matrix values.
53 **/
54export function toArray(): [number, number, number, number, number, number] {
55 if (hasInitialState) {
56 return identity;
57 }
58 return [a, b, c, d, tx, ty];
59}
60
61/**
62 * Appends the specified matrix properties to this matrix. All parameters are required.
63 * This is the equivalent of multiplying `(this matrix) * (specified matrix)`.
64 * @method append
65 * @param {Number} a2
66 * @param {Number} b2
67 * @param {Number} c2
68 * @param {Number} d2
69 * @param {Number} tx2
70 * @param {Number} ty2
71 **/
72export function append(
73 a2: number,
74 b2: number,
75 c2: number,
76 d2: number,
77 tx2: number,
78 ty2: number,
79) {
80 const change = a2 !== 1 || b2 !== 0 || c2 !== 0 || d2 !== 1;
81 const translate = tx2 !== 0 || ty2 !== 0;
82 if (!change && !translate) {
83 return;
84 }
85 if (hasInitialState) {
86 hasInitialState = false;
87 a = a2;
88 b = b2;
89 c = c2;
90 d = d2;
91 tx = tx2;
92 ty = ty2;
93 return;
94 }
95 const a1 = a;
96 const b1 = b;
97 const c1 = c;
98 const d1 = d;
99 if (change) {
100 a = a1 * a2 + c1 * b2;
101 b = b1 * a2 + d1 * b2;
102 c = a1 * c2 + c1 * d2;
103 d = b1 * c2 + d1 * d2;
104 }
105 if (translate) {
106 tx = a1 * tx2 + c1 * ty2 + tx;
107 ty = b1 * tx2 + d1 * ty2 + ty;
108 }
109}
110
111/**
112 * Generates matrix properties from the specified display object transform properties, and appends them to this matrix.
113 * For example, you can use this to generate a matrix representing the transformations of a display object:
114 *
115 * reset();
116 * appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation);
117 * var matrix = toArray()
118 *
119 * @method appendTransform
120 * @param {Number} x
121 * @param {Number} y
122 * @param {Number} scaleX
123 * @param {Number} scaleY
124 * @param {Number} rotation
125 * @param {Number} skewX
126 * @param {Number} skewY
127 * @param {Number} regX Optional.
128 * @param {Number} regY Optional.
129 **/
130export function appendTransform(
131 x: number,
132 y: number,
133 scaleX: number,
134 scaleY: number,
135 rotation: number,
136 skewX: number,
137 skewY: number,
138 regX: number,
139 regY: number,
140) {
141 if (
142 x === 0 &&
143 y === 0 &&
144 scaleX === 1 &&
145 scaleY === 1 &&
146 rotation === 0 &&
147 skewX === 0 &&
148 skewY === 0 &&
149 regX === 0 &&
150 regY === 0
151 ) {
152 return;
153 }
154 let cos, sin;
155 if (rotation % 360) {
156 const r = rotation * DEG_TO_RAD;
157 cos = Math.cos(r);
158 sin = Math.sin(r);
159 } else {
160 cos = 1;
161 sin = 0;
162 }
163
164 const a2 = cos * scaleX;
165 const b2 = sin * scaleX;
166 const c2 = -sin * scaleY;
167 const d2 = cos * scaleY;
168
169 if (skewX || skewY) {
170 const b1 = Math.tan(skewY * DEG_TO_RAD);
171 const c1 = Math.tan(skewX * DEG_TO_RAD);
172 append(a2 + c1 * b2, b1 * a2 + b2, c2 + c1 * d2, b1 * c2 + d2, x, y);
173 } else {
174 append(a2, b2, c2, d2, x, y);
175 }
176
177 if (regX || regY) {
178 // append the registration offset:
179 tx -= regX * a + regY * c;
180 ty -= regX * b + regY * d;
181 hasInitialState = false;
182 }
183}