Skip to content

Commit eb12cb5

Browse files
JoshuaGrossfacebook-github-bot
authored andcommitted
Support interpolating transform View property
Summary: For Fabric LayoutAnimations, we need to support interpolating the Transform property (which really ends up just being interpolation of ScaleX, ScaleY, or ScaleXY transforms - not arbitrary matrices). To support that, we need to be able to convert Transform back to folly::dynamic, and on the Java side we need to support accepting arbitrary matrices instead of transform maps of properties. Changelog: [Internal] Fabric-only changes Reviewed By: sammy-SC Differential Revision: D21564590 fbshipit-source-id: b137f659b27e4b8fae83921a28ccf46035e18651
1 parent a7bbc85 commit eb12cb5

File tree

4 files changed

+78
-4
lines changed

4 files changed

+78
-4
lines changed

ReactAndroid/src/main/java/com/facebook/react/uimanager/TransformHelper.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ public static void processTransform(ReadableArray transforms, double[] result) {
4848
double[] helperMatrix = sHelperMatrix.get();
4949
MatrixMathHelper.resetIdentityMatrix(result);
5050

51+
// If the transforms array is actually just the matrix itself,
52+
// copy that directly. This is for Fabric LayoutAnimations support.
53+
// All of the stuff this Java helper does is already done in C++ in Fabric, so we
54+
// can just use that matrix directly.
55+
if (transforms.getType(0) == ReadableType.Number && transforms.size() == 16) {
56+
for (int i = 0; i < transforms.size(); i++) {
57+
result[i] = transforms.getDouble(i);
58+
}
59+
return;
60+
}
61+
5162
for (int transformIdx = 0, size = transforms.size(); transformIdx < size; transformIdx++) {
5263
ReadableMap transform = transforms.getMap(transformIdx);
5364
String transformType = transform.keySetIterator().nextKey();

ReactCommon/fabric/components/view/ViewComponentDescriptor.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@ class ViewComponentDescriptor
2828
dynamic_cast<ViewProps const *>(props.get());
2929
ViewProps const *newViewProps =
3030
dynamic_cast<ViewProps const *>(newProps.get());
31-
float opacity = oldViewProps->opacity +
32-
(newViewProps->opacity - oldViewProps->opacity) * animationProgress;
3331

3432
SharedProps interpolatedPropsShared = cloneProps(newProps, {});
3533
ViewProps *interpolatedProps = const_cast<ViewProps *>(
3634
dynamic_cast<ViewProps const *>(interpolatedPropsShared.get()));
37-
interpolatedProps->opacity = opacity;
35+
36+
interpolatedProps->opacity = oldViewProps->opacity +
37+
(newViewProps->opacity - oldViewProps->opacity) * animationProgress;
38+
39+
interpolatedProps->transform = Transform::Interpolate(
40+
animationProgress, oldViewProps->transform, newViewProps->transform);
3841

3942
// Android uses RawProps, not props, to update props on the platform...
4043
// Since interpolated props don't interpolate at all using RawProps, we need
@@ -44,7 +47,10 @@ class ViewComponentDescriptor
4447
// mounting layer. Once we can remove this, we should change `rawProps` to
4548
// be const again.
4649
#ifdef ANDROID
47-
interpolatedProps->rawProps["opacity"] = opacity;
50+
interpolatedProps->rawProps["opacity"] = interpolatedProps->opacity;
51+
52+
interpolatedProps->rawProps["transform"] =
53+
(folly::dynamic)interpolatedProps->transform;
4854
#endif
4955

5056
return interpolatedPropsShared;

ReactCommon/fabric/graphics/Transform.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ Transform Transform::Rotate(Float x, Float y, Float z) {
8686
return transform;
8787
}
8888

89+
Transform Transform::Interpolate(
90+
float animationProgress,
91+
Transform const &lhs,
92+
Transform const &rhs) {
93+
auto result = Transform{};
94+
for (size_t i = 0; i < 16; i++) {
95+
result.matrix[i] =
96+
lhs.matrix[i] + (rhs.matrix[i] - lhs.matrix[i]) * animationProgress;
97+
}
98+
return result;
99+
}
100+
89101
bool Transform::operator==(Transform const &rhs) const {
90102
for (auto i = 0; i < 16; i++) {
91103
if (matrix[i] != rhs.matrix[i]) {

ReactCommon/fabric/graphics/Transform.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include <react/graphics/Float.h>
1414
#include <react/graphics/Geometry.h>
1515

16+
#ifdef ANDROID
17+
#include <folly/dynamic.h>
18+
#endif
19+
1620
namespace facebook {
1721
namespace react {
1822

@@ -56,6 +60,22 @@ struct Transform {
5660
static Transform RotateZ(Float angle);
5761
static Transform Rotate(Float angleX, Float angleY, Float angleZ);
5862

63+
/**
64+
* Perform a simple interpolation between lhs and rhs, given "progress"
65+
* between the two assuming that we are "moving" from lhs to rhs. This is a
66+
* simple linear interpolation between each matrix index and will only work
67+
* for simple scaling or translation; this will not work for rotation.
68+
*
69+
* @param progress
70+
* @param lhs
71+
* @param rhs
72+
* @return
73+
*/
74+
static Transform Interpolate(
75+
float animationProgress,
76+
Transform const &lhs,
77+
Transform const &rhs);
78+
5979
/*
6080
* Equality operators.
6181
*/
@@ -72,6 +92,31 @@ struct Transform {
7292
* Concatenates (multiplies) transform matrices.
7393
*/
7494
Transform operator*(Transform const &rhs) const;
95+
96+
/**
97+
* Convert to folly::dynamic.
98+
*/
99+
#ifdef ANDROID
100+
operator folly::dynamic() const {
101+
return folly::dynamic::array(
102+
matrix[0],
103+
matrix[1],
104+
matrix[2],
105+
matrix[3],
106+
matrix[4],
107+
matrix[5],
108+
matrix[6],
109+
matrix[7],
110+
matrix[8],
111+
matrix[9],
112+
matrix[10],
113+
matrix[11],
114+
matrix[12],
115+
matrix[13],
116+
matrix[14],
117+
matrix[15]);
118+
}
119+
#endif
75120
};
76121

77122
/*

0 commit comments

Comments
 (0)