Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(android): fix transform order and convert perspective same as iOS #3562

Merged
merged 3 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions docs/api/style/transform.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ transform: [{ rotateX: '45deg' }, { rotateZ: '0.785398rad' }]

它与 CSS 的 transform 参数类似,请参考 [MDN](//developer.mozilla.org/zh-CN/docs/Web/CSS/transform) 上的详细信息。

| 类型 | 必需 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| array of object: { perspective: number }, object: { rotate: string }, object: { rotateX: string }, object: { rotateY: string }, object: { rotateZ: string }, object: { scale: number }, object: { scaleX: number }, object: { scaleY: number }, object: { translateX: number }, object: {translateY: number}, object: { skewX: string }, object: { skewY: string } | 否 |
| 参数 | 描述 | 类型 | 支持平台 |
| ----------- | ------------------------------------------------------------ | -------- | -------------- |
| perspective | 指定观察者与 z=0 平面的距离,默认值`1280`,Android 从 `3.2.0` 版本开始支持 | `number` | `Android、iOS` |
| rotate | 旋转,角度或弧度 | `string` | `Android、iOS` |
| rotateX | X轴旋转,角度或弧度 | `string` | `Android、iOS` |
| rotateY | Y轴旋转,角度或弧度 | `string` | `Android、iOS` |
| rotateZ | Z轴旋转(同rotate) | `string` | `Android、iOS` |
| scale | 缩放 | `number` | `Android、iOS` |
| scaleX | X轴缩放 | `number` | `Android、iOS` |
| scaleY | Y轴缩放 | `number` | `Android、iOS` |
| translateX | X轴平移 | `number` | `Android、iOS` |
| translateY | Y轴平移 | `number` | `Android、iOS` |
| skewX | X轴倾斜,角度或弧度 | `string` | `iOS` |
| skewY | Y轴倾斜,角度或弧度 | `string` | `iOS` |

!> Android 不支持 `skewX` 和 `skewY` 。

!> Android 从 `3.2.0` 版本开始支持设置perspective,并把默认值改为和 iOS 一致。

!> Android 旧版本处理多个变形参数的顺序是反转的,从 `3.2.0` 开始改为和 iOS 一致。
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public abstract class HippyViewController<T extends View & HippyViewBase> implem
private static final String GET_BOUNDING_CLIENT_RECT = "getBoundingClientRect";
public static final String KEY_REL_TO_CONTAINER = "relToContainer";
public static final String KEY_ERR_MSG = "errMsg";
private static final int PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX = 2;
private static final float CAMERA_DISTANCE_NORMALIZATION_MULTIPLIER = (float) Math.sqrt(5);
private static final MatrixUtil.MatrixDecompositionContext sMatrixDecompositionContext = new MatrixUtil.MatrixDecompositionContext();
private static final double[] sTransformDecompositionArray = new double[16];
private boolean bUserChangeFocus = false;
Expand Down Expand Up @@ -412,6 +414,27 @@ private void applyTransform(T view, ArrayList<Object> transformArray) {
view.setRotationY((float) sMatrixDecompositionContext.rotationDegrees[1]);
view.setScaleX((float) sMatrixDecompositionContext.scale[0]);
view.setScaleY((float) sMatrixDecompositionContext.scale[1]);

double[] perspectiveArray = sMatrixDecompositionContext.perspective;

if (perspectiveArray.length > PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX) {
float invertedCameraDistance = (float) perspectiveArray[PERSPECTIVE_ARRAY_INVERTED_CAMERA_DISTANCE_INDEX];
if (invertedCameraDistance == 0) {
// Default camera distance, before scale multiplier (1280)
invertedCameraDistance = 0.00078125f;
}
float cameraDistance = -1 / invertedCameraDistance;
float scale = PixelUtil.getDensity();

// The following converts the matrix's perspective to a camera distance
// such that the camera perspective looks the same on Android and iOS.
// The native Android implementation removed the screen density from the
// calculation, so squaring and a normalization value of
// sqrt(5) produces an exact replica with iOS.
// For more information, see https://github.com/facebook/react-native/pull/18302
float normalizedCameraDistance = scale * scale * cameraDistance * CAMERA_DISTANCE_NORMALIZATION_MULTIPLIER;
view.setCameraDistance(normalizedCameraDistance);
}
}

public static void resetTransform(View view) {
Expand All @@ -422,6 +445,7 @@ public static void resetTransform(View view) {
view.setRotationY(0);
view.setScaleX(1);
view.setScaleY(1);
view.setCameraDistance(0);
}

@SuppressWarnings("deprecation")
Expand Down
Loading
Loading