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

[Feature] Support loading Rive animations from Expo Assets #241

Open
nderscore opened this issue May 15, 2024 · 4 comments
Open

[Feature] Support loading Rive animations from Expo Assets #241

nderscore opened this issue May 15, 2024 · 4 comments

Comments

@nderscore
Copy link

nderscore commented May 15, 2024

This is a follow-up to #123 and #185 - please refer to these issues for additional context.


Description

This issue seeks to add support for Expo Assets to the React Native Rive integration.

Expo Assets enables developers to load custom assets asynchronously without needing to explicitly bundle them into the native app code. This enables features like hot-reloading during local development, as well as the ability to deploy updates through EAS update

Without this, there is a lot of friction that discourages the use of Rive on an Expo project:

  • During local development, you can't hot-reload Rive animations. You need to do a full build of your custom dev client.

  • After deployment, it is not possible to update the Rive animations embedded in the app without a new native build being published to the app store. There is no way to update the animations over EAS Update.

Current behavior

On iOS, it is already possible to use Expo Assets using the instructions found in the initial issue (#123)

On Android, this does not work. The Rive adaptor chokes when it receives a file:// URL.

Expected behavior

I can pass in a file:// URL from Expo Asset into the Rive adapter for React Native, and it works on all platforms.

@nderscore nderscore changed the title Feat: Support Expo Assets [Feature] Support Expo Assets May 15, 2024
@nderscore nderscore changed the title [Feature] Support Expo Assets [Feature] Support loading Rive animations with Expo Assets May 15, 2024
@nderscore nderscore changed the title [Feature] Support loading Rive animations with Expo Assets [Feature] Support loading Rive animations from Expo Assets May 15, 2024
@kevin-ashton
Copy link

kevin-ashton commented Jun 10, 2024

We are considering using Rive in our Expo app. Our current two options are

a) Download the rive assets with urls, which isn't a great user experience especially on startup.
b) Do a new dev build every time we update something (5-6 minutes), which is not a great developer experience.

Neither option seems that great.

This feature seems critical if you are going to get any wider adoption in react-native.

@D1no
Copy link

D1no commented Jul 18, 2024

Glad I found this issue. Thank you. Will be sticking with Lottie

@tslater
Copy link

tslater commented Aug 31, 2024

I finally have a solution. Hope this makes its way into Rive eventually...but it requires 2 steps:

  1. edit your metro config so that it knows to bundle *.riv files:
config.resolver["assetExts"] = [
  ...(config.resolver.assetExts || []),
  // for rive animations
  "riv",
];
  1. Write a wrapper around the default Rive component in order to convert the required asset:
import React, { forwardRef } from 'react';
import Rive, { RiveRef } from "rive-react-native";
// @ts-ignore
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';

type RiveComponentProps = Omit<React.ComponentProps<typeof Rive>, 'url' | 'resourceName'> & {
  source: any
}

// detects if it is an http or file url
const stringIsUrl = (uri: string) => {
  return uri.startsWith('http') || uri.startsWith('file');
}

export const RiveAnimation = forwardRef<RiveRef, RiveComponentProps>(
  (props, ref) => {

    const { source, ...riveProps } = props;
    const resolved = resolveAssetSource(source);
    const uriIsUrl = stringIsUrl(resolved.uri);

    return (
      <Rive
        ref={ref}
        {...riveProps}
        resourceName={!uriIsUrl ? resolved.uri : undefined}
        url={uriIsUrl ? resolved.uri : undefined}
      />
    );
  }
);

This works just like images in expo and react-native. In development, the file is served by metro, so it's super fast and dynamic to change images. In production, the asset is bundled and the appropriate local uri is handled for you. It just works. I just tested in both environments and it works great. SOOOO much better than every other solution I've seen here on github.

*note that this is edited. The original code was missing the resourceName prop for bundled Android apps and was only working in dev mode

@anatoleblanc
Copy link

Hey @tslater

Thanks a lot for the code snippet!
We implemented the same and it works great on IOS. On Android though it only works in development mode ; not in production. Does this work for you?

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

No branches or pull requests

5 participants