Skip to content

Support translate array syntax, enables translateZ #538

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

Merged
merged 2 commits into from
Aug 8, 2020

Conversation

msand
Copy link
Contributor

@msand msand commented Jan 7, 2020

    <Animated.View
      style={{
        color: 'green',
        transform: [
          {rotateY: '30deg'},
          Platform.OS === 'web'
            ? {translateZ: 100}
            : {translate: [0, 0, 100]},
        ],
      }}
    />

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
<Animated.View
      style={{
        color: 'green',
        transform: [
          {rotateY: '30deg'},
          Platform.OS === 'web'
            ? {translateZ: 100}
            : {translate: [0, 0, 100]},
        ],
      }}
    />
@wcandillon
Copy link
Contributor

wcandillon commented Apr 11, 2020

to use tranzlateZ when there is no rotation of the origin, there is a helper function named translateZ(): https://github.com/wcandillon/react-native-redash/blob/master/packages/core/src/Transformations.ts#L19

translateZ: https://github.com/wcandillon/react-native-redash/blob/master/packages/core/src/Transformations.ts#L14

@msand
Copy link
Contributor Author

msand commented Apr 11, 2020

@wcandillon That actually gives different behaviour when combined with e.g. rotateY, you need to translate it in 3d space to get a cube like rotation using only those two primitives, with the translateZ it only scales it, rather than lift it out in 3d space. Check Stories2 implementation with alt = false on android here: https://snack.expo.io/@msand/new-instagram-stories

@wcandillon
Copy link
Contributor

That makes sense, big thank you 🙌🏻

@msand
Copy link
Contributor Author

msand commented Apr 11, 2020

And to clarify to maintainers, this works in plain View element styles, and,
with Animated.View + useNativeDriver: false (check Stories1 with alt = false, on ios, android, web), and with reanimated + useNativeDriver: true in ios, (check Stories2 with alt = false)

In this specific case It's possible to emulate using translateX, rotateY and perspective
with plain Animated.View + useNativeDriver: true on ios, android and web (check Stories3).

But, more complex 3d scenes would be very hard to keep track of, without being able to adjust their position on the Z axis.

@msand
Copy link
Contributor Author

msand commented Apr 11, 2020

So, this pull request fixes the broken reanimated + android case, doesn't fix the web part, but the web doesn't have any integration with the native WebAnimation api anyway (doesn't lock animations if javascript is blocking), so the web components can use the plain react-native Animated.View logic just fine atm.

@wcandillon
Copy link
Contributor

wcandillon commented Apr 24, 2020

I would be interested to see this PR merged into reanimated :)
There is also an issues with translateZ on iOS. It works if you use a number but doesn't if you use a an animated node instead. The translate + array syntax is not supported with Reanimated (even for x and y).

@jgonet jgonet self-assigned this Jul 31, 2020
Copy link
Member

@jgonet jgonet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 🎉

@jgonet jgonet changed the base branch from master to v1 July 31, 2020 10:19
@jgonet jgonet merged commit f81ce35 into software-mansion:v1 Aug 8, 2020
@mikehardy
Copy link
Contributor

I can't speculate why this would be the case, but taking the same working project from reanimated 1.10.2 to 1.11.0 (which had the sole change of this PR), I began crashing on android with this stack trace:

2020-08-10 13:31:09.407 13168-13168/com.kullki.kscore.dev E/unknown:ViewManager: Error while updating prop transform
    java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:87)
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:136)
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:56)
        at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:49)
        at com.facebook.react.uimanager.NativeViewHierarchyManager.updateProperties(NativeViewHierarchyManager.java:137)
        at com.facebook.react.uimanager.UIImplementation.synchronouslyUpdateViewOnUIThread(UIImplementation.java:291)
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:127)
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:19)
        at com.swmansion.reanimated.nodes.Node.value(Node.java:46)
        at com.swmansion.reanimated.nodes.PropsNode.update(PropsNode.java:155)
        at com.swmansion.reanimated.nodes.Node.runUpdates(Node.java:130)
        at com.swmansion.reanimated.NodesManager.onAnimationFrame(NodesManager.java:160)
        at com.swmansion.reanimated.NodesManager.access$000(NodesManager.java:55)
        at com.swmansion.reanimated.NodesManager$1.doFrameGuarded(NodesManager.java:108)
        at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
        at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
        at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:872)
        at android.view.Choreographer.doCallbacks(Choreographer.java:686)
        at android.view.Choreographer.doFrame(Choreographer.java:618)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Number.doubleValue()' on a null object reference
        at com.facebook.react.bridge.JavaOnlyMap.getDouble(JavaOnlyMap.java:101)
        at com.facebook.react.uimanager.TransformHelper.processTransform(TransformHelper.java:84)
        at com.facebook.react.uimanager.BaseViewManager.setTransformProperty(BaseViewManager.java:322)
        at com.facebook.react.uimanager.BaseViewManager.setTransform(BaseViewManager.java:82)
        at com.facebook.react.views.view.ReactViewManager.setTransform(ReactViewManager.java:272)
        at com.facebook.react.views.view.ReactViewManager.setTransform(ReactViewManager.java:37)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:87) 
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:136) 
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:56) 
        at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:49) 
        at com.facebook.react.uimanager.NativeViewHierarchyManager.updateProperties(NativeViewHierarchyManager.java:137) 
        at com.facebook.react.uimanager.UIImplementation.synchronouslyUpdateViewOnUIThread(UIImplementation.java:291) 
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:127) 
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:19) 
        at com.swmansion.reanimated.nodes.Node.value(Node.java:46) 
        at com.swmansion.reanimated.nodes.PropsNode.update(PropsNode.java:155) 
        at com.swmansion.reanimated.nodes.Node.runUpdates(Node.java:130) 
        at com.swmansion.reanimated.NodesManager.onAnimationFrame(NodesManager.java:160) 
        at com.swmansion.reanimated.NodesManager.access$000(NodesManager.java:55) 
        at com.swmansion.reanimated.NodesManager$1.doFrameGuarded(NodesManager.java:108) 
        at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29) 
        at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175) 
        at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85) 
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:872) 
        at android.view.Choreographer.doCallbacks(Choreographer.java:686) 
        at android.view.Choreographer.doFrame(Choreographer.java:618) 
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860) 
        at android.os.Handler.handleCallback(Handler.java:751) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
2020-08-10 13:31:09.409 13168-13168/com.kullki.kscore.dev E/unknown:ReactNative: Exception in native call
    com.facebook.react.bridge.JSApplicationIllegalArgumentException: Error while updating property 'transform' of a view managed by: RCTView
        at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:102)
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:136)
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:56)
        at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:49)
        at com.facebook.react.uimanager.NativeViewHierarchyManager.updateProperties(NativeViewHierarchyManager.java:137)
        at com.facebook.react.uimanager.UIImplementation.synchronouslyUpdateViewOnUIThread(UIImplementation.java:291)
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:127)
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:19)
        at com.swmansion.reanimated.nodes.Node.value(Node.java:46)
        at com.swmansion.reanimated.nodes.PropsNode.update(PropsNode.java:155)
        at com.swmansion.reanimated.nodes.Node.runUpdates(Node.java:130)
        at com.swmansion.reanimated.NodesManager.onAnimationFrame(NodesManager.java:160)
        at com.swmansion.reanimated.NodesManager.access$000(NodesManager.java:55)
        at com.swmansion.reanimated.NodesManager$1.doFrameGuarded(NodesManager.java:108)
        at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
        at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175)
        at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:872)
        at android.view.Choreographer.doCallbacks(Choreographer.java:686)
        at android.view.Choreographer.doFrame(Choreographer.java:618)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:87)
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:136) 
        at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:56) 
        at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:49) 
        at com.facebook.react.uimanager.NativeViewHierarchyManager.updateProperties(NativeViewHierarchyManager.java:137) 
        at com.facebook.react.uimanager.UIImplementation.synchronouslyUpdateViewOnUIThread(UIImplementation.java:291) 
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:127) 
        at com.swmansion.reanimated.nodes.PropsNode.evaluate(PropsNode.java:19) 
        at com.swmansion.reanimated.nodes.Node.value(Node.java:46) 
        at com.swmansion.reanimated.nodes.PropsNode.update(PropsNode.java:155) 
        at com.swmansion.reanimated.nodes.Node.runUpdates(Node.java:130) 
        at com.swmansion.reanimated.NodesManager.onAnimationFrame(NodesManager.java:160) 
        at com.swmansion.reanimated.NodesManager.access$000(NodesManager.java:55) 
        at com.swmansion.reanimated.NodesManager$1.doFrameGuarded(NodesManager.java:108) 
        at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29) 
        at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175) 
        at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85) 
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:872) 
        at android.view.Choreographer.doCallbacks(Choreographer.java:686) 
        at android.view.Choreographer.doFrame(Choreographer.java:618) 
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860) 
        at android.os.Handler.handleCallback(Handler.java:751) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Number.doubleValue()' on a null object reference
        at com.facebook.react.bridge.JavaOnlyMap.getDouble(JavaOnlyMap.java:101)
        at com.facebook.react.uimanager.TransformHelper.processTransform(TransformHelper.java:84)
        at com.facebook.react.uimanager.BaseViewManager.setTransformProperty(BaseViewManager.java:322)
        at com.facebook.react.uimanager.BaseViewManager.setTransform(BaseViewManager.java:82)
        at com.facebook.react.views.view.ReactViewManager.setTransform(ReactViewManager.java:272)
        at com.facebook.react.views.view.ReactViewManager.setTransform(ReactViewManager.java:37)

That only happens when I open a screen in my app that uses a drawer navigator ("react-navigation-drawer": "2.5.0") which is the only transform I can think of

Reverting to 1.10.2 results in a working screen

@jgonet
Copy link
Member

jgonet commented Aug 10, 2020

@mikehardy

It's possible, I looked at the diff and it seems that after changing ternary to if-else ladder I forgot to do assignment in double case. You can check if changing transformConfigMap.getDouble("value"); line to transformConfig.value = transformConfigMap.getDouble("value"); inside node_modules/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/nodes/TransformNode.java helps

I'll try to repro it and create a fix for that tomorrow. We version reanimated like expo (native changes always go into minor, even if it's patch), so you can expect that 1.12 should work.

Thanks for reporting!

@mikehardy
Copy link
Contributor

I have a pretty easy repro case and am handy with patch-package etc, so I'll test your hypothesis and report back

@jgonet
Copy link
Member

jgonet commented Aug 10, 2020

Can you share it here, please?

jgonet added a commit that referenced this pull request Aug 10, 2020
After changing original nested ternary in #538 to if-else chain double case didn't have assignment, so it was crashing with null value for transform style error.

Example:

import React from 'react';
import {SafeAreaView, Text} from 'react-native';
import Animated from 'react-native-reanimated';

const App = () => {
  return (
    <SafeAreaView>
      <Animated.View
        style={{
          transform: [{translateX: 100.2}],
        }}>
        <Text>Test </Text>
      </Animated.View>
    </SafeAreaView>
  );
};

export default App;
@mikehardy
Copy link
Contributor

I cannot sorry, I know it would help, but it's a proprietary app. But since your response was so fast (thank you!) I still had the issue laying out on the dissection table as it were, so just at this moment with this app I can break it or not depending on that version. I'm rebuilding now to check the patch you mention

I can say that it's not super fancy, it's an app with bottom tab navigator and on one screen I have a drawer navigator that pulls out from the left, using pretty default settings but (unfortunately) on the old versions of all the react-navigation stuff. So I don't know how it would translate.

@jgonet
Copy link
Member

jgonet commented Aug 10, 2020

It's alright, I thought you made some small example on new RN app using the drawer. I already submitted PR with a fix and example, so it's not necessary now.

Thanks for testing that though, small examples often overlook things that bubble up in real apps.

jgonet added a commit that referenced this pull request Aug 10, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
## Description

After changing the original nested ternary in #538 to if-else chain double case didn't have an assignment, so it was crashing with a null value for transform style error.

## Example

```jsx
import React from 'react';
import {SafeAreaView, Text} from 'react-native';
import Animated from 'react-native-reanimated';

const App = () => {
  return (
    <SafeAreaView>
      <Animated.View
        style={{
          transform: [{translateX: 100.2}],
        }}>
        <Text>Test </Text>
      </Animated.View>
    </SafeAreaView>
  );
};

export default App;
```
jgonet added a commit that referenced this pull request Aug 12, 2020
```jsx
    <Animated.View
      style={{
        color: 'green',
        transform: [
          {rotateY: '30deg'},
          Platform.OS === 'web'
            ? {translateZ: 100}
            : {translate: [0, 0, 100]},
        ],
      }}
    />
```

Co-authored-by: Jakub Gonet <jakub.gonet@swmansion.com>
jgonet added a commit that referenced this pull request Aug 12, 2020
After changing the original nested ternary in #538 to if-else chain double case didn't have an assignment, so it was crashing with a null value for transform style error.

```jsx
import React from 'react';
import {SafeAreaView, Text} from 'react-native';
import Animated from 'react-native-reanimated';

const App = () => {
  return (
    <SafeAreaView>
      <Animated.View
        style={{
          transform: [{translateX: 100.2}],
        }}>
        <Text>Test </Text>
      </Animated.View>
    </SafeAreaView>
  );
};

export default App;
```
kmagiera pushed a commit that referenced this pull request Aug 13, 2020

Unverified

This user has not yet uploaded their public signing key.
```jsx
    <Animated.View
      style={{
        color: 'green',
        transform: [
          {rotateY: '30deg'},
          Platform.OS === 'web'
            ? {translateZ: 100}
            : {translate: [0, 0, 100]},
        ],
      }}
    />
```

Co-authored-by: Jakub Gonet <jakub.gonet@swmansion.com>
kmagiera pushed a commit that referenced this pull request Aug 13, 2020

Unverified

This user has not yet uploaded their public signing key.
After changing the original nested ternary in #538 to if-else chain double case didn't have an assignment, so it was crashing with a null value for transform style error.

```jsx
import React from 'react';
import {SafeAreaView, Text} from 'react-native';
import Animated from 'react-native-reanimated';

const App = () => {
  return (
    <SafeAreaView>
      <Animated.View
        style={{
          transform: [{translateX: 100.2}],
        }}>
        <Text>Test </Text>
      </Animated.View>
    </SafeAreaView>
  );
};

export default App;
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants