Skip to content
New issue

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

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

Already on GitHub? # to your account

[Feature Request] Add "lottie-react-native" compatibility mode #409

Open
aschultz opened this issue Jan 9, 2021 · 0 comments
Open

[Feature Request] Add "lottie-react-native" compatibility mode #409

aschultz opened this issue Jan 9, 2021 · 0 comments
Labels
feature-lottiegen Feature requests or enhancements for the LottieGen tool

Comments

@aschultz
Copy link
Contributor

aschultz commented Jan 9, 2021

Overview

The C++/WinRT implementation of lottie-react-native is a wrapper around AnimatedVisualPlayer to support playback of Lottie animations in React Native.

On the native side, it expects consuming applications to implement ILottieSourceProvider and supply the player with a mapping between animation names and implementations of IAnimatedVisualSource (such as those created by LottieGen).

// LottieReactNative
interface ILottieSourceProvider
{
   Microsoft.UI.Xaml.Controls.IAnimatedVisualSource GetSourceFromName(String name);
}

// Consuming app implements mapping
IAnimatedVisualSource MySourceProvider::GetSourceFromName(hstring name) {
    if (name == L"MyAnimation") return winrt::AnimatedVisuals::MyAnimation();
    if (name == L"Foo") return winrt::AnimatedVisuals::Foo();
    ...
}

// Consuming app registers Lottie player with React and supplies it with the name mapper
App() {
    ...
    PackageProviders().Append(winrt::LottieReactNative::ReactPackageProvider(winrt::MySourceProvider());
}

On the JS side, the app can then use Lottie like:

<LottieView source="MyAnimation" />

This works fairly well except that the LottieView API, which is shared with iOS and Android, accepts calls like play(from, to) where from and to are frame numbers, not the normalized time values that AnimatedVisualPlayer expects. As such, our Windows implementation needs a way to convert.

We added an interface to LottieReactNative that we can query in the player. We then tell LottieGen to add the interface to its generated objects. This interface matches the code that LottieGen is already designed to generate.

// LottieReactNative
interface ILottieMediaSource
{
    Double FrameToProgress(Double frame);
};

void LottieView::Play(int64_t from, int64_t to) {
    auto lottieMediaSource = m_player.Source().try_as<ILottieMediaSource>();
    if (lottieMediaSource) {
        lottieMediaSource.Play( lottieMediaSource.FrameToProgress(from), lottieMediaSource.FrameToProgress(to) );
    } else {
        //  TODO: Don't know how to convert frames to time. Maybe fall back to default framerate?
    }
}

// Generated code in app project
// Created with: lottiegen -AdditionalInterface ILottieMediaSource ...
runtimeclass MyAnimation : [default] IAnimatedVisualSource, ILottieMediaSource {
    MyAnimation();
};

class MyAnimation ... {
    ...
    double FrameToProgress(double frame);
    ...
}

Problem

As you can see, there's an expectation here that the code LottieGen creates will adhere to the schema of the interface exposed by lottie-react-native. That's not guaranteed. If a future version of LottieGen unknowingly introduces a breaking change, apps would not be able to consume that new version unless lottie-react-native is also updated with a new interface. Since LottieGen is currently unaware of these needs, such a change would come easily.

Solution

We can codify the requirements of lottie-react-native into LottieGen to prevent breaking changes. Add a flag to the tool, say -LottieReactNative 1.0, that has the following effects:

  1. Each generated runtimeclass is configured to extend the interface LottieReactNative.ILottieMediaSource (the same as if we had specified using -AdditionalInterface
  2. The code in the generated implementations adheres to that interface

Note that the COM interface itself is NOT exported. The expectation is that lottie-react-native will be exporting the interface. LottieGen just needs to create animations that match it.

TODO: Settle on what the interface should be. Is Double FrameToProgress(Double frame); enough? Should we go ahead and add Int64 FrameCount { get; } and Double Duration {get;}?

@aborziak-ms aborziak-ms added the feature-lottiegen Feature requests or enhancements for the LottieGen tool label Feb 27, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
feature-lottiegen Feature requests or enhancements for the LottieGen tool
Projects
None yet
Development

No branches or pull requests

2 participants