├── .gitignore
├── LICENSE
├── README.md
├── android
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── dk
│ └── madslee
│ └── imageSequence
│ ├── RCTImageSequenceManager.java
│ ├── RCTImageSequencePackage.java
│ ├── RCTImageSequenceView.java
│ └── RCTResourceDrawableIdHelper.java
├── index.js
├── ios
├── RCTImageSequence.xcodeproj
│ └── project.pbxproj
└── RCTImageSequence
│ ├── RCTImageSequenceManager.h
│ ├── RCTImageSequenceManager.m
│ ├── RCTImageSequenceView.h
│ └── RCTImageSequenceView.m
├── package.json
├── react-native-image-sequence.podspec
└── typings
└── index.d.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IJ
26 | #
27 | android.iml
28 | .idea
29 | .gradle
30 | local.properties
31 |
32 | # node.js
33 | #
34 | node_modules/*
35 | npm-debug.log
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Mads Lee Jensen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-image-sequence
2 | native modules for handling image sequence animations. (created because i had performance issues with a javascript only solution like: https://github.com/remobile/react-native-image-animation)
3 |
4 | its a simple wrapper around **iOS** `UIImageView.animationImages` and **Android** `AnimationDrawable`
5 |
6 | ## Installation
7 |
8 | 1. `npm i --save react-native-image-sequence`
9 | 2. `react-native link react-native-image-sequence`
10 |
11 |
12 | ## Examples
13 |
14 | ```javascript
15 | import ImageSequence from 'react-native-image-sequence';
16 |
17 | const images = [
18 | require('1.jpg'),
19 | require('2.jpg'),
20 | require('3.jpg'),
21 | require('4.jpg'),
22 | require('5.jpg'),
23 | ];
24 |
25 | const centerIndex = Math.round(images.length / 2);
26 |
27 |
31 | ```
32 |
33 | ### Change animation speed
34 | You can change the speed of the animation by setting the `framesPerSecond` property.
35 |
36 | ```javascript
37 |
41 | ```
42 |
43 | ### Looping
44 | You can change if animation loops indefinitely by setting the `loop` property.
45 |
46 | ```javascript
47 |
52 | ```
53 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | }
5 |
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:1.3.1'
8 | }
9 | }
10 |
11 | apply plugin: 'com.android.library'
12 |
13 | android {
14 | compileSdkVersion 23
15 | buildToolsVersion "23.0.1"
16 |
17 | defaultConfig {
18 | minSdkVersion 16
19 | targetSdkVersion 22
20 | versionCode 1
21 | versionName "1.0"
22 | }
23 | lintOptions {
24 | abortOnError false
25 | }
26 | }
27 |
28 | dependencies {
29 | compile 'com.facebook.react:react-native:+'
30 | }
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madsleejensen/react-native-image-sequence/543d3b4a5fe517d59e14fb2026a417884eceea51/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/android/src/main/java/dk/madslee/imageSequence/RCTImageSequenceManager.java:
--------------------------------------------------------------------------------
1 | package dk.madslee.imageSequence;
2 |
3 | import com.facebook.react.bridge.ReadableArray;
4 | import com.facebook.react.bridge.ReadableMap;
5 | import com.facebook.react.uimanager.SimpleViewManager;
6 | import com.facebook.react.uimanager.ThemedReactContext;
7 | import com.facebook.react.uimanager.annotations.ReactProp;
8 |
9 | import java.util.ArrayList;
10 |
11 |
12 | public class RCTImageSequenceManager extends SimpleViewManager {
13 | @Override
14 | public String getName() {
15 | return "RCTImageSequence";
16 | }
17 |
18 | @Override
19 | protected RCTImageSequenceView createViewInstance(ThemedReactContext reactContext) {
20 | return new RCTImageSequenceView(reactContext);
21 | }
22 |
23 | /**
24 | * sets the speed of the animation.
25 | *
26 | * @param view
27 | * @param framesPerSecond
28 | */
29 | @ReactProp(name = "framesPerSecond")
30 | public void setFramesPerSecond(final RCTImageSequenceView view, Integer framesPerSecond) {
31 | view.setFramesPerSecond(framesPerSecond);
32 | }
33 |
34 | /**
35 | * @param view
36 | * @param images an array of ReadableMap's {uri: "http://...."} return value of the resolveAssetSource(....)
37 | */
38 | @ReactProp(name = "images")
39 | public void setImages(final RCTImageSequenceView view, ReadableArray images) {
40 | ArrayList uris = new ArrayList<>();
41 | for (int index = 0; index < images.size(); index++) {
42 | ReadableMap map = images.getMap(index);
43 | uris.add(map.getString("uri"));
44 | }
45 |
46 | view.setImages(uris);
47 | }
48 |
49 | /**
50 | * sets if animations is looped indefinitely.
51 | *
52 | * @param view
53 | * @param loop
54 | */
55 | @ReactProp(name = "loop")
56 | public void setLoop(final RCTImageSequenceView view, Boolean loop) {
57 | view.setLoop(loop);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/android/src/main/java/dk/madslee/imageSequence/RCTImageSequencePackage.java:
--------------------------------------------------------------------------------
1 | package dk.madslee.imageSequence;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.JavaScriptModule;
5 | import com.facebook.react.bridge.NativeModule;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.react.uimanager.ViewManager;
8 |
9 | import java.util.Arrays;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | public class RCTImageSequencePackage implements ReactPackage {
14 |
15 | @Override
16 | public List createNativeModules(ReactApplicationContext reactContext) {
17 | return Collections.emptyList();
18 | }
19 |
20 | // Deprecated RN 0.47
21 | public List> createJSModules() {
22 | return Collections.emptyList();
23 | }
24 |
25 | @Override
26 | public List createViewManagers(ReactApplicationContext reactContext) {
27 | return Arrays.asList(new RCTImageSequenceManager());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/android/src/main/java/dk/madslee/imageSequence/RCTImageSequenceView.java:
--------------------------------------------------------------------------------
1 | package dk.madslee.imageSequence;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.graphics.drawable.AnimationDrawable;
7 | import android.graphics.drawable.BitmapDrawable;
8 | import android.util.Log;
9 | import android.os.AsyncTask;
10 | import android.widget.ImageView;
11 |
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.net.URL;
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.concurrent.RejectedExecutionException;
18 |
19 |
20 | public class RCTImageSequenceView extends ImageView {
21 | private Integer framesPerSecond = 24;
22 | private Boolean loop = true;
23 | private ArrayList activeTasks;
24 | private HashMap bitmaps;
25 | private RCTResourceDrawableIdHelper resourceDrawableIdHelper;
26 |
27 | public RCTImageSequenceView(Context context) {
28 | super(context);
29 |
30 | resourceDrawableIdHelper = new RCTResourceDrawableIdHelper();
31 | }
32 |
33 | private class DownloadImageTask extends AsyncTask {
34 | private final Integer index;
35 | private final String uri;
36 | private final Context context;
37 |
38 | public DownloadImageTask(Integer index, String uri, Context context) {
39 | this.index = index;
40 | this.uri = uri;
41 | this.context = context;
42 | }
43 |
44 | @Override
45 | protected Bitmap doInBackground(String... params) {
46 | if (this.uri.startsWith("http")) {
47 | return this.loadBitmapByExternalURL(this.uri);
48 | }
49 |
50 | return this.loadBitmapByLocalResource(this.uri);
51 | }
52 |
53 |
54 | private Bitmap loadBitmapByLocalResource(String uri) {
55 | return BitmapFactory.decodeResource(this.context.getResources(), resourceDrawableIdHelper.getResourceDrawableId(this.context, uri));
56 | }
57 |
58 | private Bitmap loadBitmapByExternalURL(String uri) {
59 | Bitmap bitmap = null;
60 |
61 | try {
62 | InputStream in = new URL(uri).openStream();
63 | bitmap = BitmapFactory.decodeStream(in);
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 |
68 | return bitmap;
69 | }
70 |
71 | @Override
72 | protected void onPostExecute(Bitmap bitmap) {
73 | if (!isCancelled()) {
74 | onTaskCompleted(this, index, bitmap);
75 | }
76 | }
77 | }
78 |
79 | private void onTaskCompleted(DownloadImageTask downloadImageTask, Integer index, Bitmap bitmap) {
80 | if (index == 0) {
81 | // first image should be displayed as soon as possible.
82 | this.setImageBitmap(bitmap);
83 | }
84 |
85 | bitmaps.put(index, bitmap);
86 | activeTasks.remove(downloadImageTask);
87 |
88 | if (activeTasks.isEmpty()) {
89 | setupAnimationDrawable();
90 | }
91 | }
92 |
93 | public void setImages(ArrayList uris) {
94 | if (isLoading()) {
95 | // cancel ongoing tasks (if still loading previous images)
96 | for (int index = 0; index < activeTasks.size(); index++) {
97 | activeTasks.get(index).cancel(true);
98 | }
99 | }
100 |
101 | activeTasks = new ArrayList<>(uris.size());
102 | bitmaps = new HashMap<>(uris.size());
103 |
104 | for (int index = 0; index < uris.size(); index++) {
105 | DownloadImageTask task = new DownloadImageTask(index, uris.get(index), getContext());
106 | activeTasks.add(task);
107 |
108 | try {
109 | task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
110 | } catch (RejectedExecutionException e){
111 | Log.e("react-native-image-sequence", "DownloadImageTask failed" + e.getMessage());
112 | break;
113 | }
114 | }
115 | }
116 |
117 | public void setFramesPerSecond(Integer framesPerSecond) {
118 | this.framesPerSecond = framesPerSecond;
119 |
120 | // updating frames per second, results in building a new AnimationDrawable (because we cant alter frame duration)
121 | if (isLoaded()) {
122 | setupAnimationDrawable();
123 | }
124 | }
125 |
126 | public void setLoop(Boolean loop) {
127 | this.loop = loop;
128 |
129 | // updating looping, results in building a new AnimationDrawable
130 | if (isLoaded()) {
131 | setupAnimationDrawable();
132 | }
133 | }
134 |
135 | private boolean isLoaded() {
136 | return !isLoading() && bitmaps != null && !bitmaps.isEmpty();
137 | }
138 |
139 | private boolean isLoading() {
140 | return activeTasks != null && !activeTasks.isEmpty();
141 | }
142 |
143 | private void setupAnimationDrawable() {
144 | AnimationDrawable animationDrawable = new AnimationDrawable();
145 | for (int index = 0; index < bitmaps.size(); index++) {
146 | BitmapDrawable drawable = new BitmapDrawable(this.getResources(), bitmaps.get(index));
147 | animationDrawable.addFrame(drawable, 1000 / framesPerSecond);
148 | }
149 |
150 | animationDrawable.setOneShot(!this.loop);
151 |
152 | this.setImageDrawable(animationDrawable);
153 | animationDrawable.start();
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/android/src/main/java/dk/madslee/imageSequence/RCTResourceDrawableIdHelper.java:
--------------------------------------------------------------------------------
1 | package dk.madslee.imageSequence;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.net.Uri;
6 | import com.facebook.common.util.UriUtil;
7 |
8 | import javax.annotation.Nullable;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 |
13 | public class RCTResourceDrawableIdHelper {
14 |
15 | private Map mResourceDrawableIdMap;
16 |
17 | public RCTResourceDrawableIdHelper() {
18 | mResourceDrawableIdMap = new HashMap();
19 | }
20 |
21 | public int getResourceDrawableId(Context context, @Nullable String name) {
22 | if (name == null || name.isEmpty()) {
23 | return 0;
24 | }
25 | name = name.toLowerCase().replace("-", "_");
26 | if (mResourceDrawableIdMap.containsKey(name)) {
27 | return mResourceDrawableIdMap.get(name);
28 | }
29 | int id = context.getResources().getIdentifier(
30 | name,
31 | "drawable",
32 | context.getPackageName());
33 | mResourceDrawableIdMap.put(name, id);
34 | return id;
35 | }
36 |
37 | public @Nullable Drawable getResourceDrawable(Context context, @Nullable String name) {
38 | int resId = getResourceDrawableId(context, name);
39 | return resId > 0 ? context.getResources().getDrawable(resId) : null;
40 | }
41 |
42 | public Uri getResourceDrawableUri(Context context, @Nullable String name) {
43 | int resId = getResourceDrawableId(context, name);
44 | return resId > 0 ? new Uri.Builder()
45 | .scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
46 | .path(String.valueOf(resId))
47 | .build() : Uri.EMPTY;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | View,
4 | requireNativeComponent,
5 | ViewPropTypes
6 | } from 'react-native';
7 | import { bool, string, number, array, shape, arrayOf } from 'prop-types';
8 | import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
9 |
10 | class ImageSequence extends Component {
11 | render() {
12 | let normalized = this.props.images.map(resolveAssetSource);
13 |
14 | // reorder elements if start-index is different from 0 (beginning)
15 | if (this.props.startFrameIndex !== 0) {
16 | normalized = [...normalized.slice(this.props.startFrameIndex), ...normalized.slice(0, this.props.startFrameIndex)];
17 | }
18 |
19 | return (
20 |
23 | );
24 | }
25 | }
26 |
27 | ImageSequence.defaultProps = {
28 | startFrameIndex: 0,
29 | framesPerSecond: 24,
30 | loop: true
31 | };
32 |
33 | ImageSequence.propTypes = {
34 | startFrameIndex: number,
35 | images: array.isRequired,
36 | framesPerSecond: number,
37 | loop: bool
38 | };
39 |
40 | const RCTImageSequence = requireNativeComponent('RCTImageSequence', {
41 | propTypes: {
42 | ...ViewPropTypes,
43 | images: arrayOf(shape({
44 | uri: string.isRequired
45 | })).isRequired,
46 | framesPerSecond: number,
47 | loop: bool
48 | },
49 | });
50 |
51 | export default ImageSequence;
52 |
--------------------------------------------------------------------------------
/ios/RCTImageSequence.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | C75D3D5D1D3671B500B6F44B /* RCTImageSequenceView.m in Sources */ = {isa = PBXBuildFile; fileRef = C75D3D591D3671B500B6F44B /* RCTImageSequenceView.m */; };
11 | C75D3D5E1D3671B500B6F44B /* RCTImageSequenceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C75D3D5B1D3671B500B6F44B /* RCTImageSequenceManager.m */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXCopyFilesBuildPhase section */
15 | C75D3D4B1D36714700B6F44B /* CopyFiles */ = {
16 | isa = PBXCopyFilesBuildPhase;
17 | buildActionMask = 2147483647;
18 | dstPath = "include/$(PRODUCT_NAME)";
19 | dstSubfolderSpec = 16;
20 | files = (
21 | );
22 | runOnlyForDeploymentPostprocessing = 0;
23 | };
24 | /* End PBXCopyFilesBuildPhase section */
25 |
26 | /* Begin PBXFileReference section */
27 | C75D3D4D1D36714700B6F44B /* libRCTImageSequence.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTImageSequence.a; sourceTree = BUILT_PRODUCTS_DIR; };
28 | C75D3D591D3671B500B6F44B /* RCTImageSequenceView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageSequenceView.m; sourceTree = ""; };
29 | C75D3D5A1D3671B500B6F44B /* RCTImageSequenceView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageSequenceView.h; sourceTree = ""; };
30 | C75D3D5B1D3671B500B6F44B /* RCTImageSequenceManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageSequenceManager.m; sourceTree = ""; };
31 | C75D3D5C1D3671B500B6F44B /* RCTImageSequenceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageSequenceManager.h; sourceTree = ""; };
32 | /* End PBXFileReference section */
33 |
34 | /* Begin PBXFrameworksBuildPhase section */
35 | C75D3D4A1D36714700B6F44B /* Frameworks */ = {
36 | isa = PBXFrameworksBuildPhase;
37 | buildActionMask = 2147483647;
38 | files = (
39 | );
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXFrameworksBuildPhase section */
43 |
44 | /* Begin PBXGroup section */
45 | C75D3D441D36714700B6F44B = {
46 | isa = PBXGroup;
47 | children = (
48 | C75D3D4F1D36714700B6F44B /* RCTImageSequence */,
49 | C75D3D4E1D36714700B6F44B /* Products */,
50 | );
51 | sourceTree = "";
52 | };
53 | C75D3D4E1D36714700B6F44B /* Products */ = {
54 | isa = PBXGroup;
55 | children = (
56 | C75D3D4D1D36714700B6F44B /* libRCTImageSequence.a */,
57 | );
58 | name = Products;
59 | sourceTree = "";
60 | };
61 | C75D3D4F1D36714700B6F44B /* RCTImageSequence */ = {
62 | isa = PBXGroup;
63 | children = (
64 | C75D3D591D3671B500B6F44B /* RCTImageSequenceView.m */,
65 | C75D3D5A1D3671B500B6F44B /* RCTImageSequenceView.h */,
66 | C75D3D5B1D3671B500B6F44B /* RCTImageSequenceManager.m */,
67 | C75D3D5C1D3671B500B6F44B /* RCTImageSequenceManager.h */,
68 | );
69 | path = RCTImageSequence;
70 | sourceTree = "";
71 | };
72 | /* End PBXGroup section */
73 |
74 | /* Begin PBXNativeTarget section */
75 | C75D3D4C1D36714700B6F44B /* RCTImageSequence */ = {
76 | isa = PBXNativeTarget;
77 | buildConfigurationList = C75D3D561D36714700B6F44B /* Build configuration list for PBXNativeTarget "RCTImageSequence" */;
78 | buildPhases = (
79 | C75D3D491D36714700B6F44B /* Sources */,
80 | C75D3D4A1D36714700B6F44B /* Frameworks */,
81 | C75D3D4B1D36714700B6F44B /* CopyFiles */,
82 | );
83 | buildRules = (
84 | );
85 | dependencies = (
86 | );
87 | name = RCTImageSequence;
88 | productName = RCTImageSequence;
89 | productReference = C75D3D4D1D36714700B6F44B /* libRCTImageSequence.a */;
90 | productType = "com.apple.product-type.library.static";
91 | };
92 | /* End PBXNativeTarget section */
93 |
94 | /* Begin PBXProject section */
95 | C75D3D451D36714700B6F44B /* Project object */ = {
96 | isa = PBXProject;
97 | attributes = {
98 | LastUpgradeCheck = 0730;
99 | ORGANIZATIONNAME = "Mads Lee Jensen";
100 | TargetAttributes = {
101 | C75D3D4C1D36714700B6F44B = {
102 | CreatedOnToolsVersion = 7.3.1;
103 | };
104 | };
105 | };
106 | buildConfigurationList = C75D3D481D36714700B6F44B /* Build configuration list for PBXProject "RCTImageSequence" */;
107 | compatibilityVersion = "Xcode 3.2";
108 | developmentRegion = English;
109 | hasScannedForEncodings = 0;
110 | knownRegions = (
111 | en,
112 | );
113 | mainGroup = C75D3D441D36714700B6F44B;
114 | productRefGroup = C75D3D4E1D36714700B6F44B /* Products */;
115 | projectDirPath = "";
116 | projectRoot = "";
117 | targets = (
118 | C75D3D4C1D36714700B6F44B /* RCTImageSequence */,
119 | );
120 | };
121 | /* End PBXProject section */
122 |
123 | /* Begin PBXSourcesBuildPhase section */
124 | C75D3D491D36714700B6F44B /* Sources */ = {
125 | isa = PBXSourcesBuildPhase;
126 | buildActionMask = 2147483647;
127 | files = (
128 | C75D3D5E1D3671B500B6F44B /* RCTImageSequenceManager.m in Sources */,
129 | C75D3D5D1D3671B500B6F44B /* RCTImageSequenceView.m in Sources */,
130 | );
131 | runOnlyForDeploymentPostprocessing = 0;
132 | };
133 | /* End PBXSourcesBuildPhase section */
134 |
135 | /* Begin XCBuildConfiguration section */
136 | C75D3D541D36714700B6F44B /* Debug */ = {
137 | isa = XCBuildConfiguration;
138 | buildSettings = {
139 | ALWAYS_SEARCH_USER_PATHS = NO;
140 | CLANG_ANALYZER_NONNULL = YES;
141 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
142 | CLANG_CXX_LIBRARY = "libc++";
143 | CLANG_ENABLE_MODULES = YES;
144 | CLANG_ENABLE_OBJC_ARC = YES;
145 | CLANG_WARN_BOOL_CONVERSION = YES;
146 | CLANG_WARN_CONSTANT_CONVERSION = YES;
147 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
148 | CLANG_WARN_EMPTY_BODY = YES;
149 | CLANG_WARN_ENUM_CONVERSION = YES;
150 | CLANG_WARN_INT_CONVERSION = YES;
151 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
152 | CLANG_WARN_UNREACHABLE_CODE = YES;
153 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
154 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
155 | COPY_PHASE_STRIP = NO;
156 | DEBUG_INFORMATION_FORMAT = dwarf;
157 | ENABLE_STRICT_OBJC_MSGSEND = YES;
158 | ENABLE_TESTABILITY = YES;
159 | GCC_C_LANGUAGE_STANDARD = gnu99;
160 | GCC_DYNAMIC_NO_PIC = NO;
161 | GCC_NO_COMMON_BLOCKS = YES;
162 | GCC_OPTIMIZATION_LEVEL = 0;
163 | GCC_PREPROCESSOR_DEFINITIONS = (
164 | "DEBUG=1",
165 | "$(inherited)",
166 | );
167 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
168 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
169 | GCC_WARN_UNDECLARED_SELECTOR = YES;
170 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
171 | GCC_WARN_UNUSED_FUNCTION = YES;
172 | GCC_WARN_UNUSED_VARIABLE = YES;
173 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
174 | MTL_ENABLE_DEBUG_INFO = YES;
175 | ONLY_ACTIVE_ARCH = YES;
176 | SDKROOT = iphoneos;
177 | };
178 | name = Debug;
179 | };
180 | C75D3D551D36714700B6F44B /* Release */ = {
181 | isa = XCBuildConfiguration;
182 | buildSettings = {
183 | ALWAYS_SEARCH_USER_PATHS = NO;
184 | CLANG_ANALYZER_NONNULL = YES;
185 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
186 | CLANG_CXX_LIBRARY = "libc++";
187 | CLANG_ENABLE_MODULES = YES;
188 | CLANG_ENABLE_OBJC_ARC = YES;
189 | CLANG_WARN_BOOL_CONVERSION = YES;
190 | CLANG_WARN_CONSTANT_CONVERSION = YES;
191 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
192 | CLANG_WARN_EMPTY_BODY = YES;
193 | CLANG_WARN_ENUM_CONVERSION = YES;
194 | CLANG_WARN_INT_CONVERSION = YES;
195 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
196 | CLANG_WARN_UNREACHABLE_CODE = YES;
197 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
198 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
199 | COPY_PHASE_STRIP = NO;
200 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
201 | ENABLE_NS_ASSERTIONS = NO;
202 | ENABLE_STRICT_OBJC_MSGSEND = YES;
203 | GCC_C_LANGUAGE_STANDARD = gnu99;
204 | GCC_NO_COMMON_BLOCKS = YES;
205 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
206 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
207 | GCC_WARN_UNDECLARED_SELECTOR = YES;
208 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
209 | GCC_WARN_UNUSED_FUNCTION = YES;
210 | GCC_WARN_UNUSED_VARIABLE = YES;
211 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
212 | MTL_ENABLE_DEBUG_INFO = NO;
213 | SDKROOT = iphoneos;
214 | VALIDATE_PRODUCT = YES;
215 | };
216 | name = Release;
217 | };
218 | C75D3D571D36714700B6F44B /* Debug */ = {
219 | isa = XCBuildConfiguration;
220 | buildSettings = {
221 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../../react-native/React/**";
222 | OTHER_LDFLAGS = "-ObjC";
223 | PRODUCT_NAME = "$(TARGET_NAME)";
224 | SKIP_INSTALL = YES;
225 | };
226 | name = Debug;
227 | };
228 | C75D3D581D36714700B6F44B /* Release */ = {
229 | isa = XCBuildConfiguration;
230 | buildSettings = {
231 | HEADER_SEARCH_PATHS = "$(SRCROOT)/../../react-native/React/**";
232 | OTHER_LDFLAGS = "-ObjC";
233 | PRODUCT_NAME = "$(TARGET_NAME)";
234 | SKIP_INSTALL = YES;
235 | };
236 | name = Release;
237 | };
238 | /* End XCBuildConfiguration section */
239 |
240 | /* Begin XCConfigurationList section */
241 | C75D3D481D36714700B6F44B /* Build configuration list for PBXProject "RCTImageSequence" */ = {
242 | isa = XCConfigurationList;
243 | buildConfigurations = (
244 | C75D3D541D36714700B6F44B /* Debug */,
245 | C75D3D551D36714700B6F44B /* Release */,
246 | );
247 | defaultConfigurationIsVisible = 0;
248 | defaultConfigurationName = Release;
249 | };
250 | C75D3D561D36714700B6F44B /* Build configuration list for PBXNativeTarget "RCTImageSequence" */ = {
251 | isa = XCConfigurationList;
252 | buildConfigurations = (
253 | C75D3D571D36714700B6F44B /* Debug */,
254 | C75D3D581D36714700B6F44B /* Release */,
255 | );
256 | defaultConfigurationIsVisible = 0;
257 | defaultConfigurationName = Release;
258 | };
259 | /* End XCConfigurationList section */
260 | };
261 | rootObject = C75D3D451D36714700B6F44B /* Project object */;
262 | }
263 |
--------------------------------------------------------------------------------
/ios/RCTImageSequence/RCTImageSequenceManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Mads Lee Jensen on 07/07/16.
3 | // Copyright (c) 2016 Facebook. All rights reserved.
4 | //
5 |
6 | #import "RCTViewManager.h"
7 |
8 | @interface RCTImageSequenceManager : RCTViewManager
9 |
10 |
11 | @end
--------------------------------------------------------------------------------
/ios/RCTImageSequence/RCTImageSequenceManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Mads Lee Jensen on 07/07/16.
3 | // Copyright (c) 2016 Facebook. All rights reserved.
4 | //
5 |
6 | #import "RCTImageSequenceManager.h"
7 | #import "RCTImageSequenceView.h"
8 |
9 | @implementation RCTImageSequenceManager {
10 | }
11 |
12 | RCT_EXPORT_MODULE();
13 | RCT_EXPORT_VIEW_PROPERTY(images, NSArray);
14 | RCT_EXPORT_VIEW_PROPERTY(framesPerSecond, NSUInteger);
15 | RCT_EXPORT_VIEW_PROPERTY(loop, BOOL);
16 |
17 | - (UIView *)view {
18 | return [RCTImageSequenceView new];
19 | }
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/ios/RCTImageSequence/RCTImageSequenceView.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Mads Lee Jensen on 07/07/16.
3 | // Copyright (c) 2016 Facebook. All rights reserved.
4 | //
5 |
6 | #import
7 |
8 | @interface RCTImageSequenceView : UIImageView
9 |
10 |
11 | @end
--------------------------------------------------------------------------------
/ios/RCTImageSequence/RCTImageSequenceView.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Mads Lee Jensen on 07/07/16.
3 | // Copyright (c) 2016 Facebook. All rights reserved.
4 | //
5 |
6 | #import "RCTImageSequenceView.h"
7 |
8 | @implementation RCTImageSequenceView {
9 | NSUInteger _framesPerSecond;
10 | NSMutableDictionary *_activeTasks;
11 | NSMutableDictionary *_imagesLoaded;
12 | BOOL _loop;
13 | }
14 |
15 | - (void)setImages:(NSArray *)images {
16 | __weak RCTImageSequenceView *weakSelf = self;
17 |
18 | self.animationImages = nil;
19 |
20 | _activeTasks = [NSMutableDictionary new];
21 | _imagesLoaded = [NSMutableDictionary new];
22 |
23 | for (NSUInteger index = 0; index < images.count; index++) {
24 | NSDictionary *item = images[index];
25 |
26 | #ifdef DEBUG
27 | NSString *url = item[@"uri"];
28 | #else
29 | NSString *url = [NSString stringWithFormat:@"file://%@", item[@"uri"]]; // when not in debug, the paths are "local paths" (because resources are bundled in app)
30 | #endif
31 |
32 | dispatch_async(dispatch_queue_create("dk.mads-lee.ImageSequence.Downloader", NULL), ^{
33 | UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]];
34 | dispatch_async(dispatch_get_main_queue(), ^{
35 | [weakSelf onImageLoadTaskAtIndex:index image:image];
36 | });
37 | });
38 |
39 | _activeTasks[@(index)] = url;
40 | }
41 | }
42 |
43 | - (void)onImageLoadTaskAtIndex:(NSUInteger)index image:(UIImage *)image {
44 | if (index == 0) {
45 | self.image = image;
46 | }
47 |
48 | [_activeTasks removeObjectForKey:@(index)];
49 |
50 | _imagesLoaded[@(index)] = image;
51 |
52 | if (_activeTasks.allValues.count == 0) {
53 | [self onImagesLoaded];
54 | }
55 | }
56 |
57 | - (void)onImagesLoaded {
58 | NSMutableArray *images = [NSMutableArray new];
59 | for (NSUInteger index = 0; index < _imagesLoaded.allValues.count; index++) {
60 | UIImage *image = _imagesLoaded[@(index)];
61 | [images addObject:image];
62 | }
63 |
64 | [_imagesLoaded removeAllObjects];
65 |
66 | self.image = nil;
67 | self.animationDuration = images.count * (1.0f / _framesPerSecond);
68 | self.animationImages = images;
69 | self.animationRepeatCount = _loop ? 0 : 1;
70 | [self startAnimating];
71 | }
72 |
73 | - (void)setFramesPerSecond:(NSUInteger)framesPerSecond {
74 | _framesPerSecond = framesPerSecond;
75 |
76 | if (self.animationImages.count > 0) {
77 | self.animationDuration = self.animationImages.count * (1.0f / _framesPerSecond);
78 | }
79 | }
80 |
81 | - (void)setLoop:(NSUInteger)loop {
82 | _loop = loop;
83 |
84 | self.animationRepeatCount = _loop ? 0 : 1;
85 | }
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-image-sequence",
3 | "repository": {
4 | "type": "git",
5 | "url": "https://github.com/madsleejensen/react-native-image-sequence.git"
6 | },
7 | "version": "0.7.0",
8 | "description": "A component for react-native",
9 | "author": {
10 | "name": "Mads Lee Jensen",
11 | "email": "madsleejensen@gmail.com",
12 | "url": "http://mads-lee.dk"
13 | },
14 | "peerDependencies": {
15 | "react-native": ">=0.47.0",
16 | "prop-types": ">=15.5.0"
17 | },
18 | "license": "MIT",
19 | "homepage": "https://github.com/madsleejensen/react-native-image-sequence",
20 | "main": "index.js",
21 | "types": "typings/index.d.ts",
22 | "keywords": [
23 | "react-native",
24 | "native",
25 | "sequence",
26 | "imagesequence",
27 | "frames",
28 | "frame-animation",
29 | "animation",
30 | "animationImages"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/react-native-image-sequence.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = package["name"]
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.author = "Mads Lee Jensen "
10 | s.homepage = package["homepage"]
11 | s.license = package["license"]
12 | s.platform = :ios, "9.0"
13 | s.source = {:git => "https://github.com/madsleejensen/react-native-image-sequence.git" }
14 | s.source_files = "ios/RCTImageSequence/*.{h,m}"
15 | s.dependency "React"
16 | end
17 |
--------------------------------------------------------------------------------
/typings/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Component } from 'react';
2 |
3 | interface ImageSequenceProps {
4 | /** An array of source images. Each element of the array should be the result of a call to require(imagePath). */
5 | images: any[];
6 | /** Which index of the images array should the sequence start at. Default: 0 */
7 | startFrameIndex?: number;
8 | /** Playback speed of the image sequence. Default: 24 */
9 | framesPerSecond?: number;
10 | /** Should the sequence loop. Default: true */
11 | loop?: boolean;
12 | }
13 |
14 | declare class ImageSequence extends Component {
15 | }
16 |
17 | export default ImageSequence;
18 |
--------------------------------------------------------------------------------