Code Monkey home page Code Monkey logo

react-native-skottie's Introduction

ReactNativeSkottie

Features

Skottie is a high performance library for running Lottie animations in Skia.

  • 📄 Supports Lottie files (JSON) and DotLottie files (.lottie)
  • 📈 Uses Skia's GPU-acceleration
  • 📉 Lower CPU usage
  • 🏃 Higher frame rates
  • 🔗 Based on @shopify/react-native-skia

Benchmark

We benchmarked react-native-skottie against lottie-react-native on a low-end Android device running a complex animation and saw a +63% improvement in frame rates.

Screenshot of a Performance Comparison with lottie

Installation

Important

react-native-skottie depends on @shopify/react-native-skia, so make sure you install it first! (minimum required version: 0.1.230)

yarn add react-native-skottie

Usage

import { Skottie } from 'react-native-skottie';
// DotLottie files are supported as well!
import LottieAnimationFile from './animation.json';

export default function App() {
  return (
    <Skottie
      style={styles.flex1}
      source={LottieAnimationFile}
      autoPlay={true}
    />
  );
}

Advanced usage

Imperative ref API
import { Skottie } from 'react-native-skottie';
import { Button } from 'react-native';

export default function App() {
  const skottieRef = useRef<SkottieViewRef>(null);

  return (
    <View>
      <Skottie
        ref={skottieRef}
        style={styles.flex1}
        source={LottieAnimationFile}
      />

      <Button
        title="Play"
        onPress={() => skottieRef.current?.play()}
      />
      <Button
        title="Pause"
        onPress={() => skottieRef.current?.pause()}
      />
      <Button
        title="Reset"
        onPress={() => skottieRef.current?.reset()}
      />
    </View>
  );
}
Controlled by props
import { Skottie } from 'react-native-skottie';
import { Button } from 'react-native';

export default function App() {
  const [isPlaying, setIsPlaying] = useState(false);

  return (
    <View>
      <Skottie
        autoPlay={isPlaying}
        style={styles.flex1}
        source={LottieAnimationFile}
      />

      <Button
        title="Play"
        onPress={() => setIsPlaying(true)}
      />
      <Button
        title="Pause"
        onPress={() => setIsPlaying(false)}
      />
    </View>
  );
}
Controlled by reanimated
Note: React Native Animated API is not supported yet.
import { Skottie, SkottieAPI } from 'react-native-skottie';
import { useSharedValue, withTiming, Easing } from 'react-native-reanimated';

export default function App() {
  // A progress value from 0 to 1
  const progress = useSharedValue(0);

  // We need to run the animation on our own, therefor, we need to know the
  // animation's duration. We can either look that up from the lottie file,
  // or we can create the SkSkottie instance ourselves and get the duration:
  const skottieAnimation = useMemo(() => SkottieAPI.createFrom(lottieFile), []);
  const duration = skottieAnimation.duration;

  // Run the animation:
  useEffect(() => {
    // Will play the animation once …
    progress.value = withTiming(1, {
      duration: duration,
      easing: Easing.linear,
    });
    // … if you want to loop you could use withRepeat
  }, [duration]);

  return (
    <Skottie
      autoPlay={true}
      style={styles.flex1}
      source={LottieAnimationFile}
      // Pass the shared value to Skottie to drive the animation:
      progress={progress}
    />
  );
}

API

react-native-skottie can be used as drop-in replacement for lottie-react-native, as it tries to support the same props. Note, not all props are supported yet. If you are missing a prop for your use-case please open an issue (and at best also a PR 🤝):

Props

Prop name Type Default Description
source number | string | JSONObject | SkSkottie - The source of the animation. Can be a JSON file or a DotLottie file. Playing from web URLs is not supported yet. You can also pass a SkSkottie instance on your own, see API.
autoPlay boolean false If true, the animation will start playing as soon as it is ready.
loop boolean true If true, the animation will loop.
progress SharedValue<number> - A reanimated shared value from 0 to 1 that controls the progress of the animation. Note: if this is used neither the prop or imperative API will work, but you are responsible for controlling the animation state.
speed number 1 A value that controls the speed of the animation.
style ViewStyle - The style of the animation.
resizeMode ResizeMode (cover, contain, fill) cover The resize mode of the animation.

Ref

react-native-skottie provides a ref API that allows you to control the animation imperatively. The ref is of type SkottieViewRef and provides the following methods:

Method name Description
play Plays the animation.
pause Pauses the animation.
reset Resets the animation to the beginning.

SkottieAPI

react-native-skottie provides a SkottieAPI that allows you to create Skottie instances on your own. This is useful if you want to control the animation with reanimated or if you want to know the duration of the animation before it is played. The API is of type SkottieAPI and provides the following methods:

Method name Description
SkottieAPI.createFrom Creates a Skottie instance from a source (string, json, file import)

Community Discord

Join the Margelo Community Discord to chat about react-native-skottie or other Margelo libraries.

Adopting at scale

This library is provided as is.

If you stumble upon bugs or need help implementing react-native-skottie, reach out to us at https://margelo.io!

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT


Made with create-react-native-library

react-native-skottie's People

Contributors

gabimoncha avatar hannojg avatar jferrettiboke avatar mrousavy avatar tomekzaw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-skottie's Issues

IOS build issue

Platform iOS
Cloned main on commit 3850942410b9e9d4fcbfc3ca2a8ad601198ec0f4
and got the error

repo/node_modules/react-native-skottie/cpp/JsiSkSkottie.h:11:10 'modules/skottie/include/Skottie.h' file not found

onAnimationFinish is not invoked

onAnimationFinish isn't called for my lottie animation on iOS. I have tested without loop (and with aswell).
I am unsure about Android.

Add fabric support

Hey guys, i couldn't find in the docs if there is support. If not, is there any work being done for it? tks.

First class support for expo

As this is just a regular native module I'd assume it'd work with expo (not go) out of the box. However, users on twitter are reporting that it doesn't work, getting the following error:

"Error: The package 'react-native-skottie' doesn't seem to be linked. Make sure:

- You rebuilt the app after installing the package
- You are not using Expo Go"

Missing file `JniSkiaBaseView.h`

I got the error: "JniSkiaBaseView.h file not found" when building android app (Android Studio Iguana). Seem like this file is missing in package/android/cpp/jni/include

Progress controlled crashes example app

Reproducing repo: example app

Instructions: Enabling Progress controlled switch and opening any animation crashes the app.

Simulator screenshot
Simulator screenshot

Xcode screenshot
Xcode Screenshot

Add support for embedded images

We are using a lottie animation with embedded images in our onboarding flow, the images are part of the JSON lottie file as base64 strings.

Currently it looks like those base64 elements are ignored, the animation is still playing, but only the vector based parts are visible.

Is support for rasterized elements is planned?

EAS Dev client failed

We have an issue when trying to use skottie package, here is logs:


❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkTypeface.h:40:41)

  38 |             ? static_cast<int>(arguments[1].asNumber())
  39 |             : getObject()->textToGlyphs(str.c_str(), str.length(),
> 40 |                                         SkTextEncoding::kUTF8, nullptr, 0);
     |                                         ^ incomplete type 'SkTextEncoding' named in nested name specifier
  41 |     std::vector<SkGlyphID> glyphIDs;
  42 |     glyphIDs.resize(numGlyphIDs);
  43 |     getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8,

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkTypeface.h:43:58)

  41 |     std::vector<SkGlyphID> glyphIDs;
  42 |     glyphIDs.resize(numGlyphIDs);
> 43 |     getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8,
     |                                                          ^ incomplete type 'SkTextEncoding' named in nested name specifier
  44 |                               static_cast<SkGlyphID *>(glyphIDs.data()),
  45 |                               numGlyphIDs);
  46 |     auto jsiGlyphIDs = jsi::Array(runtime, numGlyphIDs);

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkFont.h:67:47)

  65 |     auto str = arguments[0].asString(runtime).utf8(runtime);
  66 |     auto numGlyphIDs = getObject()->countText(str.c_str(), str.length(),
> 67 |                                               SkTextEncoding::kUTF8);
     |                                               ^ incomplete type 'SkTextEncoding' named in nested name specifier
  68 |     std::vector<SkGlyphID> glyphs;
  69 |     glyphs.resize(numGlyphIDs);
  70 |     int glyphsSize = static_cast<int>(numGlyphIDs);

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkFont.h:71:58)

  69 |     glyphs.resize(numGlyphIDs);
  70 |     int glyphsSize = static_cast<int>(numGlyphIDs);
> 71 |     getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8,
     |                                                          ^ incomplete type 'SkTextEncoding' named in nested name specifier
  72 |                               static_cast<SkGlyphID *>(glyphs.data()),
  73 |                               glyphsSize);
  74 |     std::vector<SkScalar> widthPtrs;

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkFont.h:94:59)

  92 |     if (count > 1) {
  93 |       auto paint = JsiSkPaint::fromValue(runtime, arguments[1]);
> 94 |       getObject()->measureText(str.c_str(), str.length(), SkTextEncoding::kUTF8,
     |                                                           ^ incomplete type 'SkTextEncoding' named in nested name specifier
  95 |                                &bounds, paint.get());
  96 |     } else {
  97 |       getObject()->measureText(str.c_str(), str.length(), SkTextEncoding::kUTF8,

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkFont.h:97:59)

   95 |                                &bounds, paint.get());
   96 |     } else {
>  97 |       getObject()->measureText(str.c_str(), str.length(), SkTextEncoding::kUTF8,
      |                                                           ^ incomplete type 'SkTextEncoding' named in nested name specifier
   98 |                                &bounds);
   99 |     }
  100 |     return jsi::Object::createFromHostObject(

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkFont.h:126:38)

  124 |             ? static_cast<int>(arguments[1].asNumber())
  125 |             : getObject()->countText(str.c_str(), str.length(),
> 126 |                                      SkTextEncoding::kUTF8);
      |                                      ^ incomplete type 'SkTextEncoding' named in nested name specifier
  127 |     std::vector<SkGlyphID> glyphIDs;
  128 |     glyphIDs.resize(numGlyphIDs);
  129 |     getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8,

❌  (ios/Pods/Headers/Public/react-native-skia/JsiSkFont.h:129:58)

  127 |     std::vector<SkGlyphID> glyphIDs;
  128 |     glyphIDs.resize(numGlyphIDs);
> 129 |     getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8,
      |                                                          ^ incomplete type 'SkTextEncoding' named in nested name specifier
  130 |                               static_cast<SkGlyphID *>(glyphIDs.data()),
  131 |                               numGlyphIDs);
  132 |     auto jsiGlyphIDs = jsi::Array(runtime, numGlyphIDs);```

Dotlotties not loading on iOS

The library works great with lottie files, but I am unable to load a dotlottie file on iOS

      <Skottie
        autoPlay
        loop={false}
        source={'../assets/lotties/coins.lottie'}
        style={styles.splash}
        resizeMode="cover"
        onAnimationFinish={closeSplash}
      />

Version: 2.0.3

Missing prop `colorFilters`

Kudos to @hannojg for the release of v1 of react-native-skottie! 🎉

Today, I attempted to migrate our app from lottie-react-native to react-native-skottie and encountered an issue with a missing property. Our application utilizes relatively simple Lottie animations, but we frequently adjust the colors. For example, our animations feature bright colors on a dark background when dark mode is enabled. This functionality is achieved in lottie-react-native through the colorFilters prop. However, I noticed this prop seems to be absent in react-native-skottie. This feature would be essential for us to be able to use this library as a drop-in replacement.

Build error using rnskia > 1.x.x

Thanks for awesome library, i got crash when use skottie

import LottieAnimationFile from 'assets/lottie/loading.json';
import { Skottie } from 'react-native-skottie';

import React from 'react';

const Loading = () => {
  return (
    <Skottie
      source={LottieAnimationFile}
      style={{ width: 100, height: 100 }}
      autoPlay
      loop
    />
  );
};

export default Loading;

Version

"@shopify/react-native-skia": "^1.0.3",
"react-native-skottie": "^2.1.0",

The app crashes when using multiple skottie components.

Using one Skottie component works fine, but as soon as I add another one the app immediately crashes. Removing the second component does not solve the problem. The application works after uninstalling and reinstalling.

react-native-skottie: 2.1.0

The animation keeps looping

The animation loops regardless of the "loop" property.
Also tried setting autoPlay to false and playing the animation via imperative API, once started the animation never stops.
I only tested it on iOS, so I don't know what will happen on Android.

react-native-skottie: 2.0.3

JSI import bug for Android react-native-skottie v2.0.3

After installing the latest version 2.0.3, Android gives build error.

image
/node_modules/react-native-skottie/android/../cpp/JsiSkSkottie.h:11:10: fatal error: 'modules/skottie/include/Skottie.h' file not found
  #include <modules/skottie/include/Skottie.h>
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It seems that the #include path is incorrect in react-native-skottie/cpp/JsiSkSkottie.h:

 #pragma once

#include <jsi/jsi.h>

#include <JsiSkCanvas.h>
#include <JsiSkHostObjects.h>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"

#include <modules/skottie/include/Skottie.h> - this line triggers build error

#pragma clang diagnostic pop

namespace RNSkia {
using namespace facebook;

class JsiSkSkottie : public JsiSkWrappingSkPtrHostObject<skottie::Animation> {
public:
  // #region Properties
  JSI_PROPERTY_GET(duration) {
    return static_cast<double>(getObject()->duration());
  }
  JSI_PROPERTY_GET(fps) {
    return static_cast<double>(getObject()->fps());
  }

  JSI_PROPERTY_GET(__typename__) {
    return jsi::String::createFromUtf8(runtime, "Skottie");
  }

  JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(JsiSkSkottie, duration), JSI_EXPORT_PROP_GET(JsiSkSkottie, fps),
                              JSI_EXPORT_PROP_GET(JsiSkSkottie, __typename__))
  // #endregion

  // #region Methods
  JSI_HOST_FUNCTION(seek) {
    getObject()->seek(arguments[0].asNumber());
    return jsi::Value::undefined();
  }

  JSI_HOST_FUNCTION(render) {
    auto canvas = arguments[0].asObject(runtime).asHostObject<JsiSkCanvas>(runtime)->getCanvas();

    auto rect = JsiSkRect::fromValue(runtime, arguments[1]);
    if (canvas != nullptr && rect != nullptr) {
      getObject()->render(canvas, rect.get());
    }

    return jsi::Value::undefined();
  }

  JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkSkottie, seek), JSI_EXPORT_FUNC(JsiSkSkottie, render), JSI_EXPORT_FUNC(JsiSkSkottie, dispose))
  // #endregion

  /**
    Constructor
  */
  JsiSkSkottie(std::shared_ptr<RNSkPlatformContext> context, const sk_sp<skottie::Animation> animation)
      : JsiSkWrappingSkPtrHostObject<skottie::Animation>(std::move(context), std::move(animation)) {}

  /**
    Returns the jsi object from a host object of this type
  */
  static sk_sp<skottie::Animation> fromValue(jsi::Runtime& runtime, const jsi::Value& obj) {
    return obj.asObject(runtime).asHostObject<JsiSkSkottie>(runtime)->getObject();
  }

  /**
   * Creates the function for contructing a new instance of the
   * JsiSkSkottie class.
   *
   * @param context platform context
   * @return A function for creating a new host object wrapper for the JsiSkSkottie class.
   */
  static const jsi::HostFunctionType createCtor(std::shared_ptr<RNSkPlatformContext> context) {
    return JSI_HOST_FUNCTION_LAMBDA {
      auto jsonStr = arguments[0].asString(runtime).utf8(runtime);
      auto animation = skottie::Animation::Builder().make(jsonStr.c_str(), jsonStr.size());

      // Return the newly constructed object
      return jsi::Object::createFromHostObject(runtime, std::make_shared<JsiSkSkottie>(std::move(context), std::move(animation)));
    };
  }
};
} // namespace RNSkia

Package json dependencies:
"@shopify/react-native-skia": "^0.1.233",
"react-native": "0.72.7",
"react-native-skottie": "^2.0.3",

Minimum react-native version ?

Hey guys, thanks for this awesome library. I wanted to try it out but facing a problem in installing this with various errors on iOS and Android.

Upon googling, most of the errors seems to be hinting towards the fact that I am on [email protected] and this library probably requires a higher minimum version.

Is that correct?

[BUG] Tried to register two views with the same name SkiaPictureView

CleanShot 2024-01-25 at 22 13 24@2x

Hello, I love Skottie. Thanks for introducing amazing lib :)

I found out when I use useFont and skottie together, my app crashed.
I guess there are some issues using them together.

Here is the code below.

import { useFont } from '@shopify/react-native-skia';
import { FC } from 'react';
import { Skottie } from 'react-native-skottie';

export const Example: FC = () => {
  const font = useFont(require('.Hind-Bold.ttf'));
  
  return (
    <Skottie
      source={require('./lottie.json')}
      style={{ width: '100%', height: '100%' }}
      autoPlay
      loop
    />
  );
};

Thanks :)

Could we use skottie inside rn-skia canvas

I am exploring the use of react-native-skottie in a project. I'm interested in knowing if there's a possibility or future plans to integrate react-native-skottie within a react-native-skia Canvas.

something like this

<Canvas>
  <Skottie/>
  <OtherCanvasChildern/>
</Canvas>

This integration could enable combining Lottie animations with Skia's drawing capabilities, offering enhanced UI possibilities in React Native apps.

Is this a feasible enhancement for future releases?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.