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

[Web] Not possible to interpolate / do SVG morphing with useAnimatedProps and 'react-native-svg' #1951

Closed
1 of 3 tasks
marcuzgabriel opened this issue Apr 20, 2021 · 11 comments · Fixed by #2053
Closed
1 of 3 tasks
Labels
Bug Platform: Web This issue is specific to web 🏠 Reanimated 2

Comments

@marcuzgabriel
Copy link

marcuzgabriel commented Apr 20, 2021

Description

useAnimatedProps breaks when trying to interpolate / morph Path on web. While testing around with my own library and William Candillons I figured that the reason is located in ./react-native-reanimated/lib/reanimated2/js-reanimated/index.web.js.
setNativeProps is not a recognizable function anymore for web together with the library ‘react-native-svg’ since software-mansion/react-native-svg#1010.

Expected behavior

I expect a smooth morphing experience when interpolating path on web.

Video: http://somup.com/crfrIaFog8

Actual behavior & steps to reproduce

It currently crashes with the information:

image

How to reproduce:

  1. Clone and install https://github.com/marcuzgabriel/reanimated-animation-library
  2. Do yarn and yarn web
  3. Try to pull down the card
  4. Observe it breaks

Extra info: File where useAnimatedProps is implemented https://github.com/marcuzgabriel/reanimated-animation-library/blob/master/src/components/BottomSheet/MorphingArrow/index.tsx

Video: http://somup.com/crfrIxFogA

Snack or minimal code example

Working example:
Edit the following file in node_modules and remember to restart webpack otherwise changes wont take effect: '.\node_modules\react-native-reanimated\lib\reanimated2\js-reanimated\index.web.js' to:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import JSReanimated from './JSReanimated';
const reanimatedJS = new JSReanimated();
global._frameTimestamp = null;

export const _updatePropsJS = (_viewTag, _viewName, updates, viewRef) => {
    if (viewRef.current && viewRef.current._component) {
        const [rawStyles] = Object.keys(updates).reduce((acc, key) => {
            const value = updates[key];
            const index = typeof value === 'function' ? 1 : 0;
            acc[index][key] = value;
            return acc;
        }, [{}, {}]);


        /* Previously it was only:  viewRef.current._component.setNativeProps({ style: rawStyles });
        which caused it to crash */

        if (typeof viewRef.current._component.setNativeProps === 'function') {
            viewRef.current._component.setNativeProps({ style: rawStyles });
        } else if (viewRef.current._component.props.d) {
            viewRef.current._component._touchableNode.setAttribute('d', rawStyles.d);
        } else {
            console.warn('It is not possible to manipulate component');
        }
    }
};
global._setGlobalConsole = (_val) => {
    // noop
};
export default reanimatedJS;

Not working example:
Leave '.\node_modules\react-native-reanimated\lib\reanimated2\js-reanimated\index.web.js' intact so it is as original:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import JSReanimated from './JSReanimated';
const reanimatedJS = new JSReanimated();
global._frameTimestamp = null;
export const _updatePropsJS = (_viewTag, _viewName, updates, viewRef) => {
    if (viewRef.current && viewRef.current._component) {
        const [rawStyles] = Object.keys(updates).reduce((acc, key) => {
            const value = updates[key];
            const index = typeof value === 'function' ? 1 : 0;
            acc[index][key] = value;
            return acc;
        }, [{}, {}]);
        viewRef.current._component.setNativeProps({ style: rawStyles });
    }
};
global._setGlobalConsole = (_val) => {
    // noop
};
export default reanimatedJS;

Problematic code
Line 14 in https://github.com/software-mansion/react-native-reanimated/blob/master/src/reanimated2/js-reanimated/index.web.ts: viewRef.current._component.setNativeProps({ style: rawStyles });

Package versions

  • React-native: "0.64.0"
  • React-native-gesture-handler: "1.10.3"
  • React-native-svg: "12.1.1"
  • React-native-svg-web: "1.0.9"
  • React-native-reanimated": "2.1.0"
  • React-dom: "17.0.2"
  • NodeJS: v14.15.4

"react-native-web": "0.15.7",

Affected platforms

  • Android
  • iOS
  • Web
@github-actions
Copy link

Issue validator

The issue is valid!

@marcuzgabriel marcuzgabriel changed the title [Web] Not possible to interpolate / do SVG morphing with useAnimatedProps [Web] Not possible to interpolate / do SVG morphing with useAnimatedProps with 'react-native-svg' Apr 20, 2021
@marcuzgabriel marcuzgabriel changed the title [Web] Not possible to interpolate / do SVG morphing with useAnimatedProps with 'react-native-svg' [Web] Not possible to interpolate / do SVG morphing with useAnimatedProps and 'react-native-svg' Apr 20, 2021
@alisivgin
Copy link

I have the same issue with these versions

  • react-native: "0.63.4"

  • react-native-gesture-handler: "1.8.0"

  • react-native-svg: "12.1.0"

  • react-native-reanimated": "2.1.0"

  • react-dom: "16.13.1"

  • react-native-web: "0.15.5"

  • expo: "40.0.0"

@noldidrita
Copy link

Same issue here. I'm unable to animate SVG elements from 'react-native-svg'

@Daavidaviid
Copy link
Contributor

Same issue here

@marcuzgabriel
Copy link
Author

marcuzgabriel commented May 19, 2021

As a temporary fix I forked the reanimated library and changed .\node_modules\react-native-reanimated\lib\reanimated2\js-reanimated\index.web.js code to this:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import JSReanimated from './JSReanimated';
const reanimatedJS = new JSReanimated();
global._frameTimestamp = null;

export const _updatePropsJS = (_viewTag, _viewName, updates, viewRef) => {
    if (viewRef.current && viewRef.current._component) {
        const [rawStyles] = Object.keys(updates).reduce((acc, key) => {
            const value = updates[key];
            const index = typeof value === 'function' ? 1 : 0;
            acc[index][key] = value;
            return acc;
        }, [{}, {}]);


        /* Previously it was only:  viewRef.current._component.setNativeProps({ style: rawStyles });
        which caused it to crash */

        if (typeof viewRef.current._component.setNativeProps === 'function') {
            viewRef.current._component.setNativeProps({ style: rawStyles });
        } else if (viewRef.current._component.props.d) {
            viewRef.current._component._touchableNode.setAttribute('d', rawStyles.d);
        } else {
            console.warn('It is not possible to manipulate component');
        }
    }
};
global._setGlobalConsole = (_val) => {
    // noop
};
export default reanimatedJS;

The fix does the job when morphing svg's on the web, but it is limited / focused to only manipulate the d property.

@Daavidaviid
Copy link
Contributor

Daavidaviid commented May 19, 2021

Oh thanks, I was able to make it work.
Here is my generic (probably dirty but WORKING) solution :

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import JSReanimated from './JSReanimated';
const reanimatedJS = new JSReanimated();
global._frameTimestamp = null;

export const _updatePropsJS = (_viewTag, _viewName, updates, viewRef) => {
    if (viewRef.current && viewRef.current._component) {
        const [rawStyles] = Object.keys(updates).reduce((acc, key) => {
            const value = updates[key];
            const index = typeof value === 'function' ? 1 : 0;
            acc[index][key] = value;
            return acc;
        }, [{}, {}]);

        if (typeof viewRef.current._component.setNativeProps === 'function') {
            viewRef.current._component.setNativeProps({ style: rawStyles });
        } else if (Object.keys(viewRef.current._component.props).length > 0) {
            Object.keys(viewRef.current._component.props).forEach((key) => {
                if (!rawStyles[key]) {
                    return;
                }
                const dashedKey = key.replace(/[A-Z]/g, m => "-" + m.toLowerCase());
                viewRef.current._component._touchableNode.setAttribute(dashedKey, rawStyles[key]);
            })
        } else {
           console.warn('It is not possible to manipulate component');
        }
    }
};
global._setGlobalConsole = (_val) => {
    // noop
};
export default reanimatedJS;

@renanmav
Copy link
Contributor

Same issue here. Patched reanimated with @Daavidaviid script and it worked.

@jakub-gonet jakub-gonet added the Platform: Web This issue is specific to web label May 28, 2021
@jakub-gonet jakub-gonet linked a pull request May 28, 2021 that will close this issue
6 tasks
piaskowyk pushed a commit that referenced this issue Jun 17, 2021
## Description

Add the ability to animate svg components with `createAnimatedComponent` on the web.
Cf : #1951

## Checklist

- [X] Ensured that CI passes
@piaskowyk
Copy link
Member

Thanks for the help!

@noldidrita
Copy link

This fix seems to work with ReAnimated 2 SharedValues. However, when I try to get it working with Animated.Value from ReAnimated 1, it doesn't seem to do anything. Is there a way I can port this fix to ReAnimated 1 easily, without having to change my code to ReAnimated 2?

@nandorojo
Copy link
Contributor

For some reason, I'm still getting this with SVG on web with Reanimated 2.2.0.

Screen Shot 2021-10-07 at 2 29 05 PM

Is the fix in a later version?

@marcuzgabriel
Copy link
Author

marcuzgabriel commented Oct 7, 2021

For some reason, I'm still getting this with SVG on web with Reanimated 2.2.0.

Screen Shot 2021-10-07 at 2 29 05 PM

Is the fix in a later version?

@nandorojo The fix is introduced in latest 2.3.0-beta.2:
2.2.0...2.3.0-beta.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Platform: Web This issue is specific to web 🏠 Reanimated 2
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants