Skip to content

Commit ee147ab

Browse files
authored
[docs] Add guide for transformations example (#4289)
## Description Originally we thought about adding `useTransformGesture` hook. However, we decided to drop the idea and describe important caveats in docs guide. I've also updated transformations examples to use 3x3 matrices instead of 4x4. ## Test plan - Transformations examples - Read docs 🤓
1 parent 35afdc7 commit ee147ab

3 files changed

Lines changed: 416 additions & 120 deletions

File tree

apps/common-app/src/legacy/v2_api/transformations/index.tsx

Lines changed: 35 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,41 @@ import Animated, {
88

99
import SIGNET from '../../../ListWithHeader/signet.png';
1010

11-
function identity4() {
11+
function identity3() {
1212
'worklet';
13-
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
13+
return [1, 0, 0, 0, 1, 0, 0, 0, 1];
1414
}
1515

16-
function multiply4(a: number[], b: number[]) {
16+
function multiply3(a: number[], b: number[]) {
1717
'worklet';
1818
return [
19-
a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12],
20-
a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13],
21-
a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14],
22-
a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15],
23-
a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12],
24-
a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13],
25-
a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14],
26-
a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15],
27-
a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12],
28-
a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13],
29-
a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14],
30-
a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15],
31-
a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12],
32-
a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13],
33-
a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14],
34-
a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15],
19+
a[0] * b[0] + a[1] * b[3] + a[2] * b[6],
20+
a[0] * b[1] + a[1] * b[4] + a[2] * b[7],
21+
a[0] * b[2] + a[1] * b[5] + a[2] * b[8],
22+
a[3] * b[0] + a[4] * b[3] + a[5] * b[6],
23+
a[3] * b[1] + a[4] * b[4] + a[5] * b[7],
24+
a[3] * b[2] + a[4] * b[5] + a[5] * b[8],
25+
a[6] * b[0] + a[7] * b[3] + a[8] * b[6],
26+
a[6] * b[1] + a[7] * b[4] + a[8] * b[7],
27+
a[6] * b[2] + a[7] * b[5] + a[8] * b[8],
3528
];
3629
}
3730

38-
function scale4(sx: number, sy: number, sz: number) {
31+
function scale3(sx: number, sy: number) {
3932
'worklet';
40-
return [sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1];
33+
return [sx, 0, 0, 0, sy, 0, 0, 0, 1];
4134
}
4235

43-
function translate4(tx: number, ty: number, tz: number) {
36+
function translate3(tx: number, ty: number) {
4437
'worklet';
45-
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1];
38+
return [1, 0, 0, 0, 1, 0, tx, ty, 1];
4639
}
4740

48-
function rotate4(rad: number, x: number, y: number, z: number) {
41+
function rotate3(rad: number) {
4942
'worklet';
50-
const len = Math.hypot(x, y, z);
5143
const c = Math.cos(rad);
5244
const s = Math.sin(rad);
53-
const t = 1 - c;
54-
x /= len;
55-
y /= len;
56-
z /= len;
57-
return [
58-
t * x * x + c,
59-
t * x * y - s * z,
60-
t * x * z + s * y,
61-
0,
62-
t * x * y + s * z,
63-
t * y * y + c,
64-
t * y * z - s * x,
65-
0,
66-
t * x * z - s * y,
67-
t * y * z + s * x,
68-
t * z * z + c,
69-
0,
70-
0,
71-
0,
72-
0,
73-
1,
74-
];
45+
return [c, -s, 0, s, c, 0, 0, 0, 1];
7546
}
7647

7748
function invert2(m: number[]) {
@@ -82,6 +53,10 @@ function invert2(m: number[]) {
8253
const d = m[3];
8354
const det = a * d - b * c;
8455

56+
if (Math.abs(det) < 1e-6) {
57+
return [1, 0, 0, 1];
58+
}
59+
8560
return [d / det, -b / det, -c / det, a / det];
8661
}
8762

@@ -90,7 +65,7 @@ function toTransformedCoords(
9065
matrix: number[]
9166
) {
9267
'worklet';
93-
const m2 = [matrix[0], matrix[1], matrix[4], matrix[5]];
68+
const m2 = [matrix[0], matrix[1], matrix[3], matrix[4]];
9469
const inv = invert2(m2);
9570
const x = point.x;
9671
const y = point.y;
@@ -107,21 +82,21 @@ function createMatrix(
10782
origin: { x: number; y: number }
10883
) {
10984
'worklet';
110-
let matrix = identity4();
85+
let matrix = identity3();
11186

11287
if (scale !== 1) {
113-
matrix = multiply4(matrix, translate4(origin.x, origin.y, 0));
114-
matrix = multiply4(matrix, scale4(scale, scale, 1));
115-
matrix = multiply4(matrix, translate4(-origin.x, -origin.y, 0));
88+
matrix = multiply3(matrix, translate3(origin.x, origin.y));
89+
matrix = multiply3(matrix, scale3(scale, scale));
90+
matrix = multiply3(matrix, translate3(-origin.x, -origin.y));
11691
}
11792
if (rotation !== 0) {
118-
matrix = multiply4(matrix, translate4(origin.x, origin.y, 0));
119-
matrix = multiply4(matrix, rotate4(-rotation, 0, 0, 1));
120-
matrix = multiply4(matrix, translate4(-origin.x, -origin.y, 0));
93+
matrix = multiply3(matrix, translate3(origin.x, origin.y));
94+
matrix = multiply3(matrix, rotate3(-rotation));
95+
matrix = multiply3(matrix, translate3(-origin.x, -origin.y));
12196
}
12297

12398
if (translation.x !== 0 || translation.y !== 0) {
124-
matrix = multiply4(matrix, translate4(translation.x, translation.y, 0));
99+
matrix = multiply3(matrix, translate3(translation.x, translation.y));
125100
}
126101

127102
return matrix;
@@ -142,7 +117,7 @@ function applyTransformations(
142117
rotation,
143118
origin
144119
);
145-
return multiply4(transform, matrix);
120+
return multiply3(transform, matrix);
146121
}
147122

148123
function Photo() {
@@ -154,7 +129,7 @@ function Photo() {
154129
const isRotating = useSharedValue(false);
155130
const isScaling = useSharedValue(false);
156131

157-
const transform = useSharedValue(identity4());
132+
const transform = useSharedValue(identity3());
158133

159134
const style = useAnimatedStyle(() => {
160135
const matrix = applyTransformations(
@@ -167,8 +142,8 @@ function Photo() {
167142

168143
return {
169144
transform: [
170-
{ translateX: matrix[12] },
171-
{ translateY: matrix[13] },
145+
{ translateX: matrix[6] },
146+
{ translateY: matrix[7] },
172147
{ scale: Math.hypot(matrix[0], matrix[1]) },
173148
{ rotateZ: `${Math.atan2(matrix[1], matrix[0])}rad` },
174149
],

apps/common-app/src/new_api/complicated/transformations/index.tsx

Lines changed: 35 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,70 +16,41 @@ import Animated, {
1616
// @ts-ignore it's an image
1717
import SIGNET from '../../../ListWithHeader/signet.png';
1818

19-
function identity4() {
19+
function identity3() {
2020
'worklet';
21-
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
21+
return [1, 0, 0, 0, 1, 0, 0, 0, 1];
2222
}
2323

24-
function multiply4(a: number[], b: number[]) {
24+
function multiply3(a: number[], b: number[]) {
2525
'worklet';
2626
return [
27-
a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12],
28-
a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13],
29-
a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14],
30-
a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15],
31-
a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12],
32-
a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13],
33-
a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14],
34-
a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15],
35-
a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12],
36-
a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13],
37-
a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14],
38-
a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15],
39-
a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12],
40-
a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13],
41-
a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14],
42-
a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15],
27+
a[0] * b[0] + a[1] * b[3] + a[2] * b[6],
28+
a[0] * b[1] + a[1] * b[4] + a[2] * b[7],
29+
a[0] * b[2] + a[1] * b[5] + a[2] * b[8],
30+
a[3] * b[0] + a[4] * b[3] + a[5] * b[6],
31+
a[3] * b[1] + a[4] * b[4] + a[5] * b[7],
32+
a[3] * b[2] + a[4] * b[5] + a[5] * b[8],
33+
a[6] * b[0] + a[7] * b[3] + a[8] * b[6],
34+
a[6] * b[1] + a[7] * b[4] + a[8] * b[7],
35+
a[6] * b[2] + a[7] * b[5] + a[8] * b[8],
4336
];
4437
}
4538

46-
function scale4(sx: number, sy: number, sz: number) {
39+
function scale3(sx: number, sy: number) {
4740
'worklet';
48-
return [sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1];
41+
return [sx, 0, 0, 0, sy, 0, 0, 0, 1];
4942
}
5043

51-
function translate4(tx: number, ty: number, tz: number) {
44+
function translate3(tx: number, ty: number) {
5245
'worklet';
53-
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1];
46+
return [1, 0, 0, 0, 1, 0, tx, ty, 1];
5447
}
5548

56-
function rotate4(rad: number, x: number, y: number, z: number) {
49+
function rotate3(rad: number) {
5750
'worklet';
58-
const len = Math.hypot(x, y, z);
5951
const c = Math.cos(rad);
6052
const s = Math.sin(rad);
61-
const t = 1 - c;
62-
x /= len;
63-
y /= len;
64-
z /= len;
65-
return [
66-
t * x * x + c,
67-
t * x * y - s * z,
68-
t * x * z + s * y,
69-
0,
70-
t * x * y + s * z,
71-
t * y * y + c,
72-
t * y * z - s * x,
73-
0,
74-
t * x * z - s * y,
75-
t * y * z + s * x,
76-
t * z * z + c,
77-
0,
78-
0,
79-
0,
80-
0,
81-
1,
82-
];
53+
return [c, -s, 0, s, c, 0, 0, 0, 1];
8354
}
8455

8556
function invert2(m: number[]) {
@@ -90,6 +61,10 @@ function invert2(m: number[]) {
9061
const d = m[3];
9162
const det = a * d - b * c;
9263

64+
if (Math.abs(det) < 1e-6) {
65+
return [1, 0, 0, 1];
66+
}
67+
9368
return [d / det, -b / det, -c / det, a / det];
9469
}
9570

@@ -98,7 +73,7 @@ function toTransformedCoords(
9873
matrix: number[]
9974
) {
10075
'worklet';
101-
const m2 = [matrix[0], matrix[1], matrix[4], matrix[5]];
76+
const m2 = [matrix[0], matrix[1], matrix[3], matrix[4]];
10277
const inv = invert2(m2);
10378
const x = point.x;
10479
const y = point.y;
@@ -115,21 +90,21 @@ function createMatrix(
11590
origin: { x: number; y: number }
11691
) {
11792
'worklet';
118-
let matrix = identity4();
93+
let matrix = identity3();
11994

12095
if (scale !== 1) {
121-
matrix = multiply4(matrix, translate4(origin.x, origin.y, 0));
122-
matrix = multiply4(matrix, scale4(scale, scale, 1));
123-
matrix = multiply4(matrix, translate4(-origin.x, -origin.y, 0));
96+
matrix = multiply3(matrix, translate3(origin.x, origin.y));
97+
matrix = multiply3(matrix, scale3(scale, scale));
98+
matrix = multiply3(matrix, translate3(-origin.x, -origin.y));
12499
}
125100
if (rotation !== 0) {
126-
matrix = multiply4(matrix, translate4(origin.x, origin.y, 0));
127-
matrix = multiply4(matrix, rotate4(-rotation, 0, 0, 1));
128-
matrix = multiply4(matrix, translate4(-origin.x, -origin.y, 0));
101+
matrix = multiply3(matrix, translate3(origin.x, origin.y));
102+
matrix = multiply3(matrix, rotate3(-rotation));
103+
matrix = multiply3(matrix, translate3(-origin.x, -origin.y));
129104
}
130105

131106
if (translation.x !== 0 || translation.y !== 0) {
132-
matrix = multiply4(matrix, translate4(translation.x, translation.y, 0));
107+
matrix = multiply3(matrix, translate3(translation.x, translation.y));
133108
}
134109

135110
return matrix;
@@ -150,7 +125,7 @@ function applyTransformations(
150125
rotation,
151126
origin
152127
);
153-
return multiply4(transform, matrix);
128+
return multiply3(transform, matrix);
154129
}
155130

156131
function Photo() {
@@ -162,7 +137,7 @@ function Photo() {
162137
const isRotating = useSharedValue(false);
163138
const isScaling = useSharedValue(false);
164139

165-
const transform = useSharedValue(identity4());
140+
const transform = useSharedValue(identity3());
166141

167142
const style = useAnimatedStyle(() => {
168143
const matrix = applyTransformations(
@@ -175,8 +150,8 @@ function Photo() {
175150

176151
return {
177152
transform: [
178-
{ translateX: matrix[12] },
179-
{ translateY: matrix[13] },
153+
{ translateX: matrix[6] },
154+
{ translateY: matrix[7] },
180155
{ scale: Math.hypot(matrix[0], matrix[1]) },
181156
{ rotateZ: `${Math.atan2(matrix[1], matrix[0])}rad` },
182157
],

0 commit comments

Comments
 (0)