rn-newarch-svga-player 1.1.4 → 1.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -0
- package/SvgaPlayer.tsx +52 -13
- package/android/build.gradle +25 -54
- package/android/gradle.properties +4 -5
- package/android/src/main/java/com/svgaplayer/RNSvgaPlayer.kt +13 -0
- package/android/src/main/java/com/svgaplayer/RNSvgaPlayerManager.kt +98 -26
- package/android/src/main/java/com/svgaplayer/events/TopFrameEvent.kt +19 -0
- package/android/src/main/java/com/svgaplayer/events/TopPercentageEvent.kt +19 -0
- package/ios/RCTSvgaPlayer.h +1 -5
- package/ios/RCTSvgaPlayer.mm +113 -27
- package/package.json +3 -3
- package/src/specs/SvgaPlayerNativeComponent.ts +35 -10
- package/readme.md +0 -184
package/README.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
## **这是一款使用 ReactNative 新架构 加载`Android/iOS` Svga 动画的开源插件**[三端 Svga 动画统一使用点击这里](https://github.com/yrjwcharm/react-native-ohos/tree/feature/rnoh/svgaplayer)
|
2
|
+
|
3
|
+
> ### 版本:latest
|
4
|
+
|
5
|
+
<p align="center">
|
6
|
+
<h1 align="center"> <code>rn-newarch-svga-player</code> </h1>
|
7
|
+
</p>
|
8
|
+
<p align="center">
|
9
|
+
<a href="https://github.com/wonday/react-native-pdf/blob/master/LICENSE">
|
10
|
+
<img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License" />
|
11
|
+
</a>
|
12
|
+
</p>
|
13
|
+
|
14
|
+
> [!TIP] [Github 地址](https://github.com/yrjwcharm/rn-newarch-svga-player)
|
15
|
+
|
16
|
+
## 安装与使用
|
17
|
+
|
18
|
+
> [!TIP] 注意 ⚠️ 本库 android/ios 仅给予 Fabric 新架构 支持,旧架构不在跟进,若需旧架构支持请移步<https://github.com/yrjwcharm/react-native-svga-player>
|
19
|
+
|
20
|
+
#### **npm**
|
21
|
+
|
22
|
+
```bash
|
23
|
+
npm install rn-newarch-svga-player
|
24
|
+
```
|
25
|
+
|
26
|
+
#### **yarn**
|
27
|
+
|
28
|
+
```bash
|
29
|
+
yarn add rn-newarch-svga-player
|
30
|
+
|
31
|
+
```
|
32
|
+
|
33
|
+
> 若想更改库的别名 react-native-svga-player 来导入。你则需要把 rn-newarch-svga-player 库修改下,重新 yarn 执行
|
34
|
+
|
35
|
+
```diff
|
36
|
+
+ "dependencies": {
|
37
|
+
"@react-native-oh/react-native-harmony": "0.72.48",
|
38
|
+
"patch-package": "^8.0.0",
|
39
|
+
"postinstall-postinstall": "^2.1.0",
|
40
|
+
"react": "18.2.0",
|
41
|
+
"react-native": "0.72.5",
|
42
|
+
- "rn-newarch-svga-player":"^latest"
|
43
|
+
+ "react-native-svga-player":"npm:rn-newarch-svga-player@latest"
|
44
|
+
},
|
45
|
+
```
|
46
|
+
|
47
|
+
android 需要
|
48
|
+
|
49
|
+
```bash
|
50
|
+
./gradlew generateCodegenArtifactsFromSchema
|
51
|
+
```
|
52
|
+
|
53
|
+
ios 需要
|
54
|
+
|
55
|
+
```bash
|
56
|
+
cd ios
|
57
|
+
bundle install && bundle exec pod install
|
58
|
+
```
|
59
|
+
|
60
|
+
### ios react-native 0.76 以上 AppDelegate.mm 需要显示注册该组件
|
61
|
+
|
62
|
+
```diff
|
63
|
+
#import "AppDelegate.h"
|
64
|
+
#import "RCTSvgaPlayer.h"
|
65
|
+
#import <React/RCTBundleURLProvider.h>
|
66
|
+
#import <React/RCTBridge+Private.h>
|
67
|
+
|
68
|
+
@implementation AppDelegate
|
69
|
+
// ...
|
70
|
+
|
71
|
+
+ - (NSDictionary<NSString *,Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
|
72
|
+
+ {
|
73
|
+
+ NSMutableDictionary * dictionary = [super thirdPartyFabricComponents].mutableCopy;
|
74
|
+
+ dictionary[@"RNSvgaPlayer"] = [RCTSvgaPlayer class];
|
75
|
+
+ return dictionary;
|
76
|
+
+ }
|
77
|
+
|
78
|
+
@end
|
79
|
+
```
|
80
|
+
|
81
|
+
## API 参考
|
82
|
+
|
83
|
+
### Props
|
84
|
+
|
85
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
86
|
+
| ----------------- | ------------------------- | ----------- | ----------------------------------------------------- |
|
87
|
+
| `source` | `SvgaSource` | - | SVGA 文件源 |
|
88
|
+
| `autoPlay` | `boolean` | `true` | 是否自动播放 |
|
89
|
+
| `loops` | `number` | `0` | 循环播放次数,默认值:0 表示无限循环 |
|
90
|
+
| `clearsAfterStop` | `boolean` | `true` | 动画停止后是否清空画布 |
|
91
|
+
| `fillMode` | `'Forward' \| 'Backward'` | `'Forward'` | 填充模式:Forward 停留在最后一帧,Backward 回到第一帧 |
|
92
|
+
| `onFinished` | `function` | - | 播放完成时的回调函数 |
|
93
|
+
| `onFrame` | `function` | - | 帧变化时的回调函数 |
|
94
|
+
| `onPercentage` | `function` | - | 播放进度变化时的回调函数 |
|
95
|
+
|
96
|
+
### Ref 方法
|
97
|
+
|
98
|
+
| 方法 | 描述 |
|
99
|
+
| ---------------------------------------------------- | ----------------------------------------------- |
|
100
|
+
| `startAnimation()` | 从第 0 帧开始播放动画 |
|
101
|
+
| `startAnimationWithRange(location, length, reverse)` | 在指定范围内播放动画,可选择反向播放 |
|
102
|
+
| `pauseAnimation()` | 暂停动画,停留在当前帧 |
|
103
|
+
| `stopAnimation()` | 停止动画,根据 clearsAfterStop 决定是否清空画布 |
|
104
|
+
| `stepToFrame(frame, andPlay)` | 跳转到指定帧,可选择是否从该帧开始播放 |
|
105
|
+
| `stepToPercentage(percentage, andPlay)` | 跳转到指定百分比位置 (0.0-1.0),可选择是否播放 |
|
106
|
+
|
107
|
+
下面的代码展示了这个库的基本使用场景:
|
108
|
+
|
109
|
+
```js
|
110
|
+
import React from "react";
|
111
|
+
import { View, Dimensions, StyleSheet } from "react-native";
|
112
|
+
import { RNSvgaPlayer } from "react-native-svga-player";
|
113
|
+
|
114
|
+
export function App() {
|
115
|
+
return (
|
116
|
+
<RNSvgaPlayer
|
117
|
+
source="https://raw.githubusercontent.com/yyued/SVGAPlayer-iOS/master/SVGAPlayer/Samples/Goddess.svga"
|
118
|
+
style={{
|
119
|
+
width: 300,
|
120
|
+
height: 150,
|
121
|
+
}}
|
122
|
+
/>
|
123
|
+
);
|
124
|
+
}
|
125
|
+
|
126
|
+
const styles = StyleSheet.create({
|
127
|
+
container: {
|
128
|
+
flex: 1,
|
129
|
+
justifyContent: "flex-start",
|
130
|
+
alignItems: "center",
|
131
|
+
},
|
132
|
+
});
|
133
|
+
```
|
134
|
+
|
135
|
+
更多详情用法参考 [三端 Svga 动画统一使用点击这里](https://github.com/yrjwcharm/react-native-ohos/tree/feature/rnoh/svgaplayer)
|
136
|
+
|
137
|
+
#### 开源不易,希望您可以动一动小手点点小 ⭐⭐
|
138
|
+
|
139
|
+
#### 👴 希望大家如有好的需求踊跃提交,如有问题请提交 issue,空闲时间会扩充与修复优化
|
140
|
+
|
141
|
+
## 开源协议
|
142
|
+
|
143
|
+
本项目基于 [The MIT License (MIT)](https://github.com/yrjwcharm/react-native-ohos-svgaplayer/blob/master/LICENSE) ,请自由地享受和参与开源。
|
package/SvgaPlayer.tsx
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
|
2
2
|
import type { ViewProps } from 'react-native';
|
3
|
-
import
|
3
|
+
import SvgaPlayerView, {
|
4
4
|
Commands,
|
5
5
|
type ComponentType,
|
6
6
|
} from './src/specs/SvgaPlayerNativeComponent';
|
7
|
-
|
8
7
|
export interface SvgaErrorEvent {
|
9
8
|
error: string;
|
10
9
|
}
|
11
10
|
|
12
11
|
export interface SvgaPlayerProps extends ViewProps {
|
13
|
-
source
|
12
|
+
source: string;
|
14
13
|
/**
|
15
14
|
* 是否自动播放,默认 true
|
16
15
|
*/
|
17
16
|
autoPlay?: boolean;
|
18
17
|
/**
|
19
|
-
* 循环播放次数,默认 0
|
18
|
+
* 循环播放次数,默认 0(无限循环播放)
|
20
19
|
*/
|
21
20
|
loops?: number;
|
22
21
|
/**
|
@@ -28,10 +27,14 @@ export interface SvgaPlayerProps extends ViewProps {
|
|
28
27
|
*/
|
29
28
|
align?: 'top' | 'bottom' | 'center';
|
30
29
|
|
30
|
+
fillMode?: 'Forward' | 'Backward';
|
31
|
+
|
31
32
|
// 事件回调
|
32
33
|
onError?: (event: SvgaErrorEvent) => void;
|
33
34
|
onFinished?: () => void;
|
34
35
|
onLoaded?: () => void;
|
36
|
+
onFrame?: (event: { value: number }) => void;
|
37
|
+
onPercentage?: (event: { value: number }) => void;
|
35
38
|
}
|
36
39
|
|
37
40
|
export interface SvgaPlayerRef {
|
@@ -43,6 +46,14 @@ export interface SvgaPlayerRef {
|
|
43
46
|
* 停止动画,如果 clearsAfterStop 为 true 则清空画布
|
44
47
|
*/
|
45
48
|
stopAnimation: () => void;
|
49
|
+
pauseAnimation: () => void;
|
50
|
+
stepToFrame: (frame: number, andPlay: boolean) => void;
|
51
|
+
stepToPercentage: (percentage: number, andPlay: boolean) => void;
|
52
|
+
startAnimationWithRange: (
|
53
|
+
location: number,
|
54
|
+
length: number,
|
55
|
+
reverse: boolean
|
56
|
+
) => void;
|
46
57
|
}
|
47
58
|
|
48
59
|
const RNSvgaPlayer = forwardRef<SvgaPlayerRef, SvgaPlayerProps>(
|
@@ -50,11 +61,13 @@ const RNSvgaPlayer = forwardRef<SvgaPlayerRef, SvgaPlayerProps>(
|
|
50
61
|
{
|
51
62
|
autoPlay = true,
|
52
63
|
loops = 0,
|
53
|
-
clearsAfterStop =
|
54
|
-
source,
|
64
|
+
clearsAfterStop = true,
|
65
|
+
source = '',
|
55
66
|
onError,
|
56
67
|
onFinished,
|
57
68
|
onLoaded,
|
69
|
+
onFrame,
|
70
|
+
onPercentage,
|
58
71
|
...restProps
|
59
72
|
},
|
60
73
|
ref
|
@@ -72,22 +85,48 @@ const RNSvgaPlayer = forwardRef<SvgaPlayerRef, SvgaPlayerProps>(
|
|
72
85
|
Commands.stopAnimation(nativeRef.current);
|
73
86
|
}
|
74
87
|
},
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
88
|
+
pauseAnimation: () => {
|
89
|
+
if (nativeRef.current) {
|
90
|
+
Commands.pauseAnimation(nativeRef.current);
|
91
|
+
}
|
92
|
+
},
|
93
|
+
stepToFrame: (frame: number, andPlay: boolean) => {
|
94
|
+
if (nativeRef.current) {
|
95
|
+
Commands.stepToFrame(nativeRef.current, frame, andPlay);
|
96
|
+
}
|
97
|
+
},
|
98
|
+
stepToPercentage: (frame: number, andPlay: boolean) => {
|
99
|
+
if (nativeRef.current) {
|
100
|
+
Commands.stepToPercentage(nativeRef.current, frame, andPlay);
|
101
|
+
}
|
102
|
+
},
|
103
|
+
startAnimationWithRange: (
|
104
|
+
location: number,
|
105
|
+
length: number,
|
106
|
+
reverse: boolean
|
107
|
+
) => {
|
108
|
+
if (nativeRef.current) {
|
109
|
+
Commands.startAnimationWithRange(
|
110
|
+
nativeRef.current,
|
111
|
+
location,
|
112
|
+
length,
|
113
|
+
reverse
|
114
|
+
);
|
115
|
+
}
|
116
|
+
},
|
80
117
|
}));
|
81
118
|
|
82
119
|
return (
|
83
|
-
<
|
120
|
+
<SvgaPlayerView
|
84
121
|
ref={nativeRef}
|
85
122
|
source={source}
|
86
123
|
autoPlay={autoPlay}
|
87
124
|
loops={loops}
|
88
125
|
clearsAfterStop={clearsAfterStop}
|
89
|
-
onError={(
|
126
|
+
onError={(event) => onError?.(event.nativeEvent)}
|
90
127
|
onFinished={onFinished}
|
128
|
+
onFrameChanged={(event) => onFrame?.(event.nativeEvent)}
|
129
|
+
onPercentageChanged={(event) => onPercentage?.(event.nativeEvent)}
|
91
130
|
onLoaded={onLoaded}
|
92
131
|
{...restProps}
|
93
132
|
/>
|
package/android/build.gradle
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
+
import java.nio.file.Paths
|
1
2
|
buildscript {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
ext.safeExtGet = {prop ->
|
4
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : project.properties['SvgaPlayer_' + prop]
|
5
|
+
}
|
6
6
|
repositories {
|
7
7
|
// 使用阿里云镜像源
|
8
8
|
maven { url 'https://maven.aliyun.com/repository/google' }
|
@@ -15,21 +15,32 @@ buildscript {
|
|
15
15
|
}
|
16
16
|
|
17
17
|
dependencies {
|
18
|
-
classpath "com.android.tools.build:gradle:
|
18
|
+
classpath "com.android.tools.build:gradle:7.0.4"
|
19
19
|
// noinspection DifferentKotlinGradleVersion
|
20
|
-
classpath
|
20
|
+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion')}")
|
21
|
+
|
21
22
|
}
|
22
23
|
}
|
23
24
|
|
24
25
|
|
25
26
|
apply plugin: "com.android.library"
|
26
27
|
apply plugin: "kotlin-android"
|
27
|
-
|
28
28
|
apply plugin: "com.facebook.react"
|
29
29
|
|
30
30
|
def getExtOrIntegerDefault(name) {
|
31
31
|
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["SvgaPlayer_" + name]).toInteger()
|
32
32
|
}
|
33
|
+
static def findNodeModulePath(baseDir, packageName) {
|
34
|
+
def basePath = baseDir.toPath().normalize()
|
35
|
+
while (basePath) {
|
36
|
+
def candidatePath = Paths.get(basePath.toString(), "node_modules", packageName)
|
37
|
+
if (candidatePath.toFile().exists()) {
|
38
|
+
return candidatePath.toString()
|
39
|
+
}
|
40
|
+
basePath = basePath.getParent()
|
41
|
+
}
|
42
|
+
return null
|
43
|
+
}
|
33
44
|
|
34
45
|
android {
|
35
46
|
namespace "com.svgaplayer"
|
@@ -40,59 +51,19 @@ android {
|
|
40
51
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
41
52
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
42
53
|
}
|
43
|
-
|
44
|
-
buildFeatures {
|
45
|
-
buildConfig true
|
46
|
-
}
|
47
|
-
|
48
|
-
buildTypes {
|
49
|
-
release {
|
50
|
-
minifyEnabled false
|
51
|
-
}
|
52
|
-
}
|
53
|
-
|
54
|
-
lintOptions {
|
55
|
-
disable "GradleCompatible"
|
56
|
-
}
|
57
|
-
|
58
|
-
compileOptions {
|
59
|
-
sourceCompatibility JavaVersion.VERSION_1_8
|
60
|
-
targetCompatibility JavaVersion.VERSION_1_8
|
61
|
-
}
|
62
|
-
|
63
|
-
sourceSets {
|
64
|
-
main {
|
65
|
-
java.srcDirs += [
|
66
|
-
"generated/java",
|
67
|
-
"generated/jni"
|
68
|
-
]
|
69
|
-
}
|
70
|
-
}
|
71
54
|
}
|
55
|
+
def reactNativePath = findNodeModulePath(projectDir, "react-native")
|
72
56
|
|
73
57
|
repositories {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
// 添加 JitPack 仓库(用于 GitHub 依赖)
|
80
|
-
maven { url 'https://jitpack.io' }
|
81
|
-
// 备用官方源
|
82
|
-
mavenCentral()
|
83
|
-
google()
|
58
|
+
maven {
|
59
|
+
url "${reactNativePath}/android"
|
60
|
+
}
|
61
|
+
mavenCentral()
|
62
|
+
google()
|
84
63
|
}
|
85
64
|
|
86
|
-
def kotlin_version = getExtOrDefault("kotlinVersion")
|
87
|
-
|
88
65
|
dependencies {
|
89
66
|
implementation "com.facebook.react:react-android"
|
90
|
-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$
|
67
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:${safeExtGet('kotlinVersion')}"
|
91
68
|
implementation "com.github.yyued:SVGAPlayer-Android:2.6.1"
|
92
69
|
}
|
93
|
-
|
94
|
-
react {
|
95
|
-
jsRootDir = file("../src/")
|
96
|
-
libraryName = "RNSvgaPlayer"
|
97
|
-
codegenJavaPackageName = "com.svgaplayer"
|
98
|
-
}
|
@@ -1,5 +1,4 @@
|
|
1
|
-
SvgaPlayer_kotlinVersion=
|
2
|
-
SvgaPlayer_minSdkVersion=
|
3
|
-
SvgaPlayer_targetSdkVersion=
|
4
|
-
SvgaPlayer_compileSdkVersion=
|
5
|
-
SvgaPlayer_ndkVersion=27.1.12297006
|
1
|
+
SvgaPlayer_kotlinVersion=1.6.0
|
2
|
+
SvgaPlayer_minSdkVersion=21
|
3
|
+
SvgaPlayer_targetSdkVersion=31
|
4
|
+
SvgaPlayer_compileSdkVersion=31
|
@@ -11,6 +11,9 @@ import com.facebook.react.uimanager.events.EventDispatcher
|
|
11
11
|
import com.opensource.svgaplayer.SVGACallback
|
12
12
|
import com.opensource.svgaplayer.SVGAImageView
|
13
13
|
import com.svgaplayer.events.TopFinishedEvent
|
14
|
+
import com.svgaplayer.events.TopFrameEvent
|
15
|
+
import com.svgaplayer.events.TopLoadedEvent
|
16
|
+
import com.svgaplayer.events.TopPercentageEvent
|
14
17
|
|
15
18
|
class RNSvgaPlayer(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : SVGAImageView(context, attrs, defStyleAttr) {
|
16
19
|
|
@@ -23,6 +26,16 @@ class RNSvgaPlayer(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
|
|
23
26
|
override fun onStep(frame: Int, percentage: Double) {
|
24
27
|
// 动画开始播放,清除启动标记
|
25
28
|
isStarting = false
|
29
|
+
val frameArguments = Arguments.createMap()
|
30
|
+
val percentageArguments = Arguments.createMap()
|
31
|
+
frameArguments.putDouble("value",frame.toDouble());
|
32
|
+
percentageArguments.putDouble("value", percentage);
|
33
|
+
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
34
|
+
val framedEvent = TopFrameEvent(surfaceId, id, frameArguments)
|
35
|
+
var percentageEvent = TopPercentageEvent(surfaceId,id,percentageArguments);
|
36
|
+
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context as ThemedReactContext, id)
|
37
|
+
dispatcher?.dispatchEvent(framedEvent)
|
38
|
+
dispatcher?.dispatchEvent(percentageEvent);
|
26
39
|
}
|
27
40
|
|
28
41
|
override fun onRepeat() {
|
@@ -1,10 +1,8 @@
|
|
1
1
|
package com.svgaplayer
|
2
2
|
|
3
|
-
import android.content.Context
|
4
3
|
import android.util.Log
|
5
|
-
import
|
4
|
+
import android.widget.ImageView
|
6
5
|
import com.facebook.react.bridge.Arguments
|
7
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
8
6
|
import com.facebook.react.bridge.ReadableArray
|
9
7
|
import com.facebook.react.module.annotations.ReactModule
|
10
8
|
import com.facebook.react.uimanager.SimpleViewManager
|
@@ -12,37 +10,35 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
12
10
|
import com.facebook.react.uimanager.UIManagerHelper
|
13
11
|
import com.facebook.react.uimanager.ViewManagerDelegate
|
14
12
|
import com.facebook.react.uimanager.annotations.ReactProp
|
15
|
-
import android.widget.ImageView
|
16
13
|
import com.facebook.react.viewmanagers.RNSvgaPlayerManagerDelegate
|
17
14
|
import com.facebook.react.viewmanagers.RNSvgaPlayerManagerInterface
|
15
|
+
import com.opensource.svgaplayer.SVGACache
|
18
16
|
import com.opensource.svgaplayer.SVGAParser
|
19
17
|
import com.opensource.svgaplayer.SVGAVideoEntity
|
20
|
-
import com.opensource.svgaplayer.
|
18
|
+
import com.opensource.svgaplayer.utils.SVGARange
|
21
19
|
import com.svgaplayer.events.TopErrorEvent
|
22
|
-
import com.svgaplayer.events.TopFinishedEvent
|
23
20
|
import com.svgaplayer.events.TopLoadedEvent
|
24
21
|
import java.io.File
|
25
22
|
import java.io.FileInputStream
|
26
|
-
import java.io.IOException
|
27
23
|
import java.net.URL
|
28
24
|
|
29
|
-
|
30
|
-
|
25
|
+
|
26
|
+
@ReactModule(name = RNSvgaPlayerManager.REACT_CLASS)
|
27
|
+
class RNSvgaPlayerManager() : SimpleViewManager<RNSvgaPlayer>(), RNSvgaPlayerManagerInterface<RNSvgaPlayer> {
|
31
28
|
|
32
29
|
companion object {
|
33
|
-
const val
|
30
|
+
const val REACT_CLASS = "RNSvgaPlayer"
|
34
31
|
}
|
35
|
-
|
36
32
|
private val mDelegate: ViewManagerDelegate<RNSvgaPlayer> = RNSvgaPlayerManagerDelegate(this)
|
37
33
|
|
38
|
-
override fun getName(): String =
|
34
|
+
override fun getName(): String = REACT_CLASS
|
39
35
|
|
40
36
|
override fun getDelegate(): ViewManagerDelegate<RNSvgaPlayer>? = mDelegate
|
41
37
|
|
42
38
|
override fun createViewInstance(c: ThemedReactContext): RNSvgaPlayer {
|
43
39
|
return RNSvgaPlayer(c, null, 0)
|
44
40
|
}
|
45
|
-
|
41
|
+
@ReactProp(name = "source")
|
46
42
|
override fun setSource(view: RNSvgaPlayer, source: String?) {
|
47
43
|
val context = view.context
|
48
44
|
source?.let {
|
@@ -67,7 +63,7 @@ class RNSvgaPlayerManager : SimpleViewManager<RNSvgaPlayer>(), RNSvgaPlayerManag
|
|
67
63
|
val surfaceId = UIManagerHelper.getSurfaceId(context)
|
68
64
|
val loadedEvent = TopLoadedEvent(surfaceId, view.id, loadedData)
|
69
65
|
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context as ThemedReactContext, view.id)
|
70
|
-
|
66
|
+
dispatcher?.dispatchEvent(loadedEvent)
|
71
67
|
|
72
68
|
if(view.autoPlay){
|
73
69
|
view.startAnimationSafely()
|
@@ -99,20 +95,20 @@ class RNSvgaPlayerManager : SimpleViewManager<RNSvgaPlayer>(), RNSvgaPlayerManag
|
|
99
95
|
}
|
100
96
|
}
|
101
97
|
}
|
102
|
-
|
98
|
+
@ReactProp(name = "loops", defaultInt = 0)
|
103
99
|
override fun setLoops(view: RNSvgaPlayer, loops: Int) {
|
104
100
|
view.loops = loops
|
105
101
|
}
|
106
|
-
|
102
|
+
@ReactProp(name = "clearsAfterStop", defaultBoolean = true)
|
107
103
|
override fun setClearsAfterStop(view: RNSvgaPlayer, clearsAfterStop: Boolean) {
|
108
104
|
view.clearsAfterDetached = clearsAfterStop
|
109
105
|
view.clearsAfterStop = clearsAfterStop
|
110
106
|
}
|
111
|
-
|
107
|
+
@ReactProp(name = "autoPlay", defaultBoolean = true)
|
112
108
|
override fun setAutoPlay(view: RNSvgaPlayer, autoPlay: Boolean) {
|
113
109
|
view.autoPlay = autoPlay
|
114
110
|
}
|
115
|
-
|
111
|
+
@ReactProp(name = "align")
|
116
112
|
override fun setAlign(view: RNSvgaPlayer, align: String?) {
|
117
113
|
val scaleType = when (align) {
|
118
114
|
"bottom" -> ImageView.ScaleType.FIT_END
|
@@ -130,6 +126,26 @@ class RNSvgaPlayerManager : SimpleViewManager<RNSvgaPlayer>(), RNSvgaPlayerManag
|
|
130
126
|
when (commandId) {
|
131
127
|
"startAnimation" -> startAnimation(root)
|
132
128
|
"stopAnimation" -> stopAnimation(root)
|
129
|
+
"pauseAnimation" -> pauseAnimation(root)
|
130
|
+
"stepToFrame" -> {
|
131
|
+
val frame = args?.getInt(0) ?: 0
|
132
|
+
val andPlay = args?.getBoolean(1) ?: false
|
133
|
+
stepToFrame(root, frame, andPlay)
|
134
|
+
}
|
135
|
+
"stepToPercentage" -> {
|
136
|
+
val percentage = args?.getInt(0) ?: 0
|
137
|
+
val andPlay = args?.getBoolean(1) ?: false
|
138
|
+
stepToPercentage(root, percentage, andPlay)
|
139
|
+
}
|
140
|
+
"startAnimationWithRange" -> {
|
141
|
+
val location = args?.getInt(0) ?: 0
|
142
|
+
val length = args?.getInt(1) ?: 0
|
143
|
+
val reverse = args?.getBoolean(2) ?: false
|
144
|
+
startAnimationWithRange(root, location, length, reverse)
|
145
|
+
}
|
146
|
+
else -> {
|
147
|
+
Log.w(REACT_CLASS, "Unknown command: $commandId")
|
148
|
+
}
|
133
149
|
}
|
134
150
|
}
|
135
151
|
|
@@ -138,17 +154,73 @@ class RNSvgaPlayerManager : SimpleViewManager<RNSvgaPlayer>(), RNSvgaPlayerManag
|
|
138
154
|
}
|
139
155
|
|
140
156
|
override fun stopAnimation(view: RNSvgaPlayer) {
|
141
|
-
view.stopAnimation(
|
157
|
+
view.stopAnimation(view.clearsAfterStop)
|
158
|
+
}
|
159
|
+
|
160
|
+
// override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any>? {
|
161
|
+
// val export = super.getExportedCustomDirectEventTypeConstants()?.toMutableMap()
|
162
|
+
// ?: mutableMapOf<String, Any>()
|
163
|
+
// export[TopErrorEvent.EVENT_NAME] = mapOf("registrationName" to "onError")
|
164
|
+
// export[TopFinishedEvent.EVENT_NAME] = mapOf("registrationName" to "onFinished")
|
165
|
+
// export[TopLoadedEvent.EVENT_NAME] = mapOf("registrationName" to "onLoaded")
|
166
|
+
// export[TopFrameEvent.EVENT_NAME] = mapOf("registrationName" to "onFrameChanged")
|
167
|
+
// export[TopPercentageEvent.EVENT_NAME] = mapOf("registrationName" to "onPercentageChanged")
|
168
|
+
// return export
|
169
|
+
// }
|
170
|
+
override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
|
171
|
+
val map: MutableMap<String, Any> = HashMap()
|
172
|
+
map["onError"] = createBubblingEventConfig(
|
173
|
+
bubbledName = "onError",
|
174
|
+
capturedName = "onErrorCapture"
|
175
|
+
)
|
176
|
+
map["onFinished"] = createBubblingEventConfig(
|
177
|
+
bubbledName = "onFinished",
|
178
|
+
capturedName = "onFinishedCapture"
|
179
|
+
)
|
180
|
+
map["onLoaded"] = createBubblingEventConfig(
|
181
|
+
bubbledName = "onLoaded",
|
182
|
+
capturedName = "onLoadedCapture"
|
183
|
+
)
|
184
|
+
map["onFrameChanged"] = createBubblingEventConfig(
|
185
|
+
bubbledName = "onFrameChanged",
|
186
|
+
capturedName = "onFrameChangedCapture"
|
187
|
+
)
|
188
|
+
map["onPercentageChanged"] = createBubblingEventConfig(
|
189
|
+
bubbledName = "onPercentageChanged",
|
190
|
+
capturedName = "onPercentageChangedCapture"
|
191
|
+
)
|
192
|
+
return map;
|
193
|
+
}
|
194
|
+
private fun createBubblingEventConfig(
|
195
|
+
bubbledName: String,
|
196
|
+
capturedName: String
|
197
|
+
): Map<String, Any> {
|
198
|
+
return mapOf(
|
199
|
+
"phasedRegistrationNames" to mapOf(
|
200
|
+
"bubbled" to bubbledName,
|
201
|
+
"captured" to capturedName
|
202
|
+
)
|
203
|
+
)
|
204
|
+
}
|
205
|
+
override fun pauseAnimation(view: RNSvgaPlayer?) {
|
206
|
+
view?.pauseAnimation()
|
142
207
|
}
|
143
208
|
|
144
|
-
override fun
|
145
|
-
|
146
|
-
|
209
|
+
override fun stepToFrame(view: RNSvgaPlayer?, frame: Int, andPlay: Boolean) {
|
210
|
+
view?.stepToFrame(frame, andPlay);
|
211
|
+
}
|
147
212
|
|
148
|
-
|
149
|
-
|
150
|
-
|
213
|
+
override fun stepToPercentage(view: RNSvgaPlayer?, percentage: Int, andPlay: Boolean) {
|
214
|
+
view?.stepToFrame(percentage, andPlay);
|
215
|
+
}
|
151
216
|
|
152
|
-
|
217
|
+
override fun startAnimationWithRange(
|
218
|
+
view: RNSvgaPlayer?,
|
219
|
+
location: Int,
|
220
|
+
length: Int,
|
221
|
+
reverse: Boolean
|
222
|
+
) {
|
223
|
+
var range = SVGARange(location, length)
|
224
|
+
view?.startAnimation(range,reverse)
|
153
225
|
}
|
154
226
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
package com.svgaplayer.events
|
2
|
+
|
3
|
+
import com.facebook.react.bridge.WritableMap
|
4
|
+
import com.facebook.react.uimanager.events.Event
|
5
|
+
|
6
|
+
class TopFrameEvent(
|
7
|
+
surfaceId: Int,
|
8
|
+
viewTag: Int,
|
9
|
+
private val eventData: WritableMap
|
10
|
+
) : Event<TopFrameEvent>(surfaceId, viewTag) {
|
11
|
+
|
12
|
+
companion object {
|
13
|
+
const val EVENT_NAME = "onFrameChanged"
|
14
|
+
}
|
15
|
+
|
16
|
+
override fun getEventName(): String = EVENT_NAME
|
17
|
+
|
18
|
+
override fun getEventData(): WritableMap? = eventData
|
19
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
package com.svgaplayer.events
|
2
|
+
|
3
|
+
import com.facebook.react.bridge.WritableMap
|
4
|
+
import com.facebook.react.uimanager.events.Event
|
5
|
+
|
6
|
+
class TopPercentageEvent(
|
7
|
+
surfaceId: Int,
|
8
|
+
viewTag: Int,
|
9
|
+
private val eventData: WritableMap
|
10
|
+
) : Event<TopPercentageEvent>(surfaceId, viewTag) {
|
11
|
+
|
12
|
+
companion object {
|
13
|
+
const val EVENT_NAME = "onPercentageChanged"
|
14
|
+
}
|
15
|
+
|
16
|
+
override fun getEventName(): String = EVENT_NAME
|
17
|
+
|
18
|
+
override fun getEventData(): WritableMap? = eventData
|
19
|
+
}
|
package/ios/RCTSvgaPlayer.h
CHANGED
package/ios/RCTSvgaPlayer.mm
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
#import "RCTSvgaPlayer.h"
|
2
|
-
|
3
2
|
#import <react/renderer/components/RNSvgaPlayerSpec/ComponentDescriptors.h>
|
4
3
|
#import <react/renderer/components/RNSvgaPlayerSpec/EventEmitters.h>
|
5
4
|
#import <react/renderer/components/RNSvgaPlayerSpec/Props.h>
|
@@ -16,6 +15,7 @@ using namespace facebook::react;
|
|
16
15
|
|
17
16
|
@end
|
18
17
|
|
18
|
+
|
19
19
|
@implementation RCTSvgaPlayer {
|
20
20
|
SVGAPlayer * _svgaPlayer;
|
21
21
|
NSString * _currentSource;
|
@@ -25,11 +25,20 @@ using namespace facebook::react;
|
|
25
25
|
SVGAVideoEntity * _currentVideoItem;
|
26
26
|
}
|
27
27
|
|
28
|
+
// Event emitter convenience method
|
29
|
+
- (const RNSvgaPlayerEventEmitter &)eventEmitter
|
30
|
+
{
|
31
|
+
return static_cast<const RNSvgaPlayerEventEmitter &>(*_eventEmitter);
|
32
|
+
}
|
33
|
+
|
28
34
|
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
29
35
|
{
|
30
36
|
return concreteComponentDescriptorProvider<RNSvgaPlayerComponentDescriptor>();
|
31
37
|
}
|
32
|
-
|
38
|
+
Class<RCTComponentViewProtocol> RNSvgaPlayerCls(void)
|
39
|
+
{
|
40
|
+
return RCTSvgaPlayer.class;
|
41
|
+
}
|
33
42
|
- (instancetype)initWithFrame:(CGRect)frame
|
34
43
|
{
|
35
44
|
if (self = [super initWithFrame:frame]) {
|
@@ -104,12 +113,6 @@ using namespace facebook::react;
|
|
104
113
|
|
105
114
|
[super updateProps:props oldProps:oldProps];
|
106
115
|
}
|
107
|
-
|
108
|
-
Class<RCTComponentViewProtocol> SvgaPlayerViewCls(void)
|
109
|
-
{
|
110
|
-
return RCTSvgaPlayer.class;
|
111
|
-
}
|
112
|
-
|
113
116
|
// 辅助方法:根据 align 属性设置 contentMode
|
114
117
|
- (void)updateContentModeWithAlign:(RNSvgaPlayerAlign)align
|
115
118
|
{
|
@@ -135,20 +138,30 @@ Class<RCTComponentViewProtocol> SvgaPlayerViewCls(void)
|
|
135
138
|
[_svgaPlayer setVideoItem:nil];
|
136
139
|
[_svgaPlayer clear];
|
137
140
|
_currentVideoItem = nil;
|
138
|
-
|
139
|
-
if
|
140
|
-
|
141
|
-
|
142
|
-
.error = std::string([errorMessage UTF8String])
|
143
|
-
});
|
141
|
+
|
142
|
+
if(_eventEmitter!= nullptr) {
|
143
|
+
RNSvgaPlayerEventEmitter::OnError result = RNSvgaPlayerEventEmitter::OnError{RNSvgaPlayerEventEmitter::OnError( [errorMessage UTF8String] )};
|
144
|
+
self.eventEmitter.onError(result);
|
144
145
|
}
|
146
|
+
|
147
|
+
// if (_eventEmitter != nullptr) {
|
148
|
+
// std::dynamic_pointer_cast<const facebook::react::RNSvgaPlayerEventEmitter>(_eventEmitter)
|
149
|
+
// ->onError(facebook::react::RNSvgaPlayerEventEmitter::OnError{
|
150
|
+
// .error = std::string([errorMessage UTF8String])
|
151
|
+
// });
|
152
|
+
// }
|
145
153
|
}
|
146
154
|
|
147
155
|
- (void)sendLoadedEvent
|
148
156
|
{
|
149
|
-
if (_eventEmitter != nullptr) {
|
150
|
-
std::dynamic_pointer_cast<const facebook::react::RNSvgaPlayerEventEmitter>(_eventEmitter)
|
151
|
-
->onLoaded(facebook::react::RNSvgaPlayerEventEmitter::OnLoaded{});
|
157
|
+
// if (_eventEmitter != nullptr) {
|
158
|
+
// std::dynamic_pointer_cast<const facebook::react::RNSvgaPlayerEventEmitter>(_eventEmitter)
|
159
|
+
// ->onLoaded(facebook::react::RNSvgaPlayerEventEmitter::OnLoaded{});
|
160
|
+
//
|
161
|
+
// }
|
162
|
+
if(_eventEmitter != nullptr) {
|
163
|
+
RNSvgaPlayerEventEmitter::OnLoaded result = RNSvgaPlayerEventEmitter::OnLoaded{RNSvgaPlayerEventEmitter::OnLoaded( {} )};
|
164
|
+
self.eventEmitter.onLoaded(result);
|
152
165
|
}
|
153
166
|
}
|
154
167
|
|
@@ -372,7 +385,34 @@ Class<RCTComponentViewProtocol> SvgaPlayerViewCls(void)
|
|
372
385
|
{
|
373
386
|
[_svgaPlayer stopAnimation];
|
374
387
|
}
|
375
|
-
|
388
|
+
- (void)pauseAnimation {
|
389
|
+
[_svgaPlayer pauseAnimation];
|
390
|
+
}
|
391
|
+
-(void)stepToFrame:(NSInteger)frame andPlay:(BOOL)play {
|
392
|
+
if (frame < 0 || !_svgaPlayer || _svgaPlayer.delegate != self) {
|
393
|
+
return;
|
394
|
+
}
|
395
|
+
[_svgaPlayer stepToFrame:frame andPlay:play];
|
396
|
+
}
|
397
|
+
-(void)stepToPercentage:(NSInteger)percentage andPlay:(BOOL)play {
|
398
|
+
if (percentage < 0 || !_svgaPlayer || _svgaPlayer.delegate != self) {
|
399
|
+
return;
|
400
|
+
}
|
401
|
+
[_svgaPlayer stepToPercentage:percentage andPlay:play];
|
402
|
+
}
|
403
|
+
-(void)startAnimationWithRange:(NSInteger)location length:(NSInteger)length reverse:(BOOL)reverse{
|
404
|
+
if (!_svgaPlayer || _svgaPlayer.delegate != self) {
|
405
|
+
return;
|
406
|
+
}
|
407
|
+
|
408
|
+
// 检查 location 和 length 的有效性
|
409
|
+
if (location < 0 || length <= 0) {
|
410
|
+
return;
|
411
|
+
}
|
412
|
+
// 设置动画范围
|
413
|
+
[_svgaPlayer startAnimationWithRange:NSMakeRange(location, length) reverse:reverse];
|
414
|
+
}
|
415
|
+
|
376
416
|
// 处理来自 JavaScript 的命令调用
|
377
417
|
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
378
418
|
{
|
@@ -380,7 +420,49 @@ Class<RCTComponentViewProtocol> SvgaPlayerViewCls(void)
|
|
380
420
|
[self startAnimation];
|
381
421
|
} else if ([commandName isEqualToString:@"stopAnimation"]) {
|
382
422
|
[self stopAnimation];
|
423
|
+
}else if ([commandName isEqualToString:@"pauseAnimation"]) {
|
424
|
+
[self pauseAnimation];
|
425
|
+
}else if([commandName isEqualToString:@"stepToFrame"]){
|
426
|
+
[self stepToFrame:[args[0] integerValue] andPlay:[args[1] boolValue]];
|
427
|
+
|
428
|
+
}else if([commandName isEqualToString:@"stepToPercentage"]){
|
429
|
+
[self stepToPercentage:[args[0] integerValue] andPlay:[args[1] boolValue]];
|
430
|
+
|
431
|
+
}else if([commandName isEqualToString:@"startAnimationWithRange"]){
|
432
|
+
// 处理 startAnimationWithRange 命令
|
433
|
+
[self startAnimationWithRange:[args[0] integerValue]
|
434
|
+
length:[args[1] integerValue]
|
435
|
+
reverse:[args[2] boolValue]];
|
383
436
|
}
|
437
|
+
|
438
|
+
}
|
439
|
+
-(void) svgaPlayerDidAnimatedToFrame:(NSInteger)frame{
|
440
|
+
if (!_svgaPlayer || _svgaPlayer.delegate != self) {
|
441
|
+
return;
|
442
|
+
}
|
443
|
+
if(_eventEmitter!= nullptr) {
|
444
|
+
|
445
|
+
RNSvgaPlayerEventEmitter::OnFrameChanged result = RNSvgaPlayerEventEmitter::OnFrameChanged{RNSvgaPlayerEventEmitter::OnFrameChanged( frame )};
|
446
|
+
self.eventEmitter.onFrameChanged(result);
|
447
|
+
}
|
448
|
+
// std::dynamic_pointer_cast<const RNSvgaPlayerEventEmitter>(_eventEmitter)
|
449
|
+
// ->onFrameChanged(RNSvgaPlayerEventEmitter::OnFrameChanged{.value=(float)frame});
|
450
|
+
|
451
|
+
|
452
|
+
}
|
453
|
+
-(void) svgaPlayerDidAnimatedToPercentage:(CGFloat)percentage{
|
454
|
+
// 检查播放器是否还有效
|
455
|
+
if (!_svgaPlayer || _svgaPlayer.delegate != self) {
|
456
|
+
return;
|
457
|
+
}
|
458
|
+
if(_eventEmitter != nullptr) {
|
459
|
+
|
460
|
+
RNSvgaPlayerEventEmitter::OnPercentageChanged result = RNSvgaPlayerEventEmitter::OnPercentageChanged{RNSvgaPlayerEventEmitter::OnPercentageChanged( percentage )};
|
461
|
+
self.eventEmitter.onPercentageChanged(result);
|
462
|
+
}
|
463
|
+
//直接事件
|
464
|
+
// std::dynamic_pointer_cast<const RNSvgaPlayerEventEmitter>(_eventEmitter)
|
465
|
+
// ->onFrameChanged(RNSvgaPlayerEventEmitter::OnFrameChanged{.value=(float)percentage});
|
384
466
|
}
|
385
467
|
|
386
468
|
// SVGAPlayerDelegate methods
|
@@ -390,16 +472,16 @@ Class<RCTComponentViewProtocol> SvgaPlayerViewCls(void)
|
|
390
472
|
if (!_svgaPlayer || player != _svgaPlayer) {
|
391
473
|
return;
|
392
474
|
}
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
475
|
+
if(_eventEmitter != nullptr) {
|
476
|
+
|
477
|
+
// 检查事件发送器是否还有效
|
478
|
+
RNSvgaPlayerEventEmitter::OnFinished result = RNSvgaPlayerEventEmitter::OnFinished{RNSvgaPlayerEventEmitter::OnFinished( true )};
|
479
|
+
self.eventEmitter.onFinished(result);
|
397
480
|
}
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
});
|
481
|
+
// std::dynamic_pointer_cast<const facebook::react::RNSvgaPlayerEventEmitter>(_eventEmitter)
|
482
|
+
// ->onFinished(facebook::react::RNSvgaPlayerEventEmitter::OnFinished{
|
483
|
+
// .finished = true
|
484
|
+
// });
|
403
485
|
}
|
404
486
|
|
405
487
|
// React Native Fabric 生命周期方法
|
@@ -481,4 +563,8 @@ Class<RCTComponentViewProtocol> SvgaPlayerViewCls(void)
|
|
481
563
|
_currentSource = nil;
|
482
564
|
}
|
483
565
|
|
566
|
+
|
567
|
+
|
484
568
|
@end
|
569
|
+
|
570
|
+
|
package/package.json
CHANGED
@@ -26,10 +26,10 @@
|
|
26
26
|
"files": [
|
27
27
|
"android",
|
28
28
|
"ios",
|
29
|
-
"
|
29
|
+
"lib",
|
30
30
|
"src",
|
31
31
|
"SvgaPlayer.tsx",
|
32
|
-
"
|
32
|
+
"rn-newarch-svga-player.podspec"
|
33
33
|
],
|
34
34
|
"homepage": "https://github.com/yrjwcharm/rn-newarch-svga-player#readme",
|
35
35
|
"keywords": [
|
@@ -53,5 +53,5 @@
|
|
53
53
|
"scripts": {
|
54
54
|
"codegen-lib": "react-native codegen-lib-harmony --no-safety-check --npm-package-name react-native-ohos-svgaplayer --cpp-output-path ../../harmony/svgaplayer/src/main/cpp/generated --ets-output-path ../../harmony/svgaplayer/src/main/ets/generated --turbo-modules-spec-paths ./src --arkts-components-spec-paths ./src"
|
55
55
|
},
|
56
|
-
"version": "1.1.
|
56
|
+
"version": "1.1.16"
|
57
57
|
}
|
@@ -1,35 +1,60 @@
|
|
1
|
-
import type {HostComponent, ViewProps} from 'react-native';
|
1
|
+
import type { HostComponent, ViewProps } from 'react-native';
|
2
2
|
import type {
|
3
3
|
BubblingEventHandler,
|
4
|
+
Double,
|
4
5
|
Int32,
|
5
6
|
WithDefault,
|
6
7
|
} from 'react-native/Libraries/Types/CodegenTypes';
|
7
8
|
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
|
8
9
|
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
|
9
10
|
|
10
|
-
interface
|
11
|
-
source
|
11
|
+
interface SvgaPlayerProps extends ViewProps {
|
12
|
+
source: string;
|
12
13
|
autoPlay?: boolean;
|
13
14
|
loops?: Int32;
|
14
15
|
clearsAfterStop?: boolean;
|
15
16
|
align?: WithDefault<'top' | 'bottom' | 'center', 'center'>;
|
16
|
-
|
17
17
|
// 事件回调
|
18
|
-
onError?: BubblingEventHandler<{error: string}>;
|
19
|
-
onFinished?: BubblingEventHandler<{finished: boolean}>;
|
18
|
+
onError?: BubblingEventHandler<{ error: string }>;
|
19
|
+
onFinished?: BubblingEventHandler<{ finished: boolean }>;
|
20
20
|
onLoaded?: BubblingEventHandler<{}>;
|
21
|
+
onFrameChanged?: BubblingEventHandler<{ value: Double }>;
|
22
|
+
onPercentageChanged?: BubblingEventHandler<{ value: Double }>;
|
21
23
|
}
|
22
24
|
|
23
|
-
export type ComponentType = HostComponent<
|
25
|
+
export type ComponentType = HostComponent<SvgaPlayerProps>;
|
24
26
|
|
25
27
|
interface NativeCommands {
|
26
28
|
startAnimation: (viewRef: React.ElementRef<ComponentType>) => void;
|
27
|
-
// pauseAnimation: (viewRef: React.ElementRef<ComponentType>) => void;
|
28
29
|
stopAnimation: (viewRef: React.ElementRef<ComponentType>) => void;
|
30
|
+
pauseAnimation: (viewRef: React.ElementRef<ComponentType>) => void;
|
31
|
+
stepToFrame: (
|
32
|
+
viewRef: React.ElementRef<ComponentType>,
|
33
|
+
frame: Int32,
|
34
|
+
andPlay: boolean
|
35
|
+
) => void;
|
36
|
+
stepToPercentage: (
|
37
|
+
viewRef: React.ElementRef<ComponentType>,
|
38
|
+
percentage: Int32,
|
39
|
+
andPlay: boolean
|
40
|
+
) => void;
|
41
|
+
startAnimationWithRange: (
|
42
|
+
viewRef: React.ElementRef<ComponentType>,
|
43
|
+
location: Int32,
|
44
|
+
length: Int32,
|
45
|
+
reverse: boolean
|
46
|
+
) => void;
|
29
47
|
}
|
30
48
|
|
31
49
|
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
32
|
-
supportedCommands: [
|
50
|
+
supportedCommands: [
|
51
|
+
'startAnimation',
|
52
|
+
'pauseAnimation',
|
53
|
+
'stopAnimation',
|
54
|
+
'stepToFrame',
|
55
|
+
'stepToPercentage',
|
56
|
+
'startAnimationWithRange',
|
57
|
+
],
|
33
58
|
});
|
34
59
|
|
35
|
-
export default codegenNativeComponent<
|
60
|
+
export default codegenNativeComponent<SvgaPlayerProps>('RNSvgaPlayer');
|
package/readme.md
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
## **_这是一款使用 ReactNative 加载`Android/iOS` Svga 动画的播放器插件_** [三端 Svga 动画统一使用点击这里](https://github.com/yrjwcharm/react-native-ohos/tree/feature/rnoh/svgaplayer)
|
2
|
-
|
3
|
-
> ### 版本:latest
|
4
|
-
|
5
|
-
<p align="center">
|
6
|
-
<h1 align="center"> <code>rn-newarch-svga-player</code> </h1>
|
7
|
-
</p>
|
8
|
-
<p align="center">
|
9
|
-
<a href="https://github.com/wonday/react-native-pdf/blob/master/LICENSE">
|
10
|
-
<img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License" />
|
11
|
-
</a>
|
12
|
-
</p>
|
13
|
-
|
14
|
-
> [!TIP] [Github 地址](https://github.com/yrjwcharm/rn-newarch-svga-player)
|
15
|
-
|
16
|
-
## 安装与使用
|
17
|
-
|
18
|
-
> [!TIP] 注意 ⚠️ 本库 android/ios 仅给予 Fabric 新架构支持,旧架构不在跟进,若需旧架构支持请移步<https://github.com/yrjwcharm/react-native-svga-player>
|
19
|
-
|
20
|
-
**确保你的 Android/iOS 已经开启了新架构支持 <https://reactnative.cn/docs/0.72/the-new-architecture/use-app-template>**
|
21
|
-
|
22
|
-
#### **npm**
|
23
|
-
|
24
|
-
```bash
|
25
|
-
npm install rn-newarch-svga-player
|
26
|
-
```
|
27
|
-
|
28
|
-
#### **yarn**
|
29
|
-
|
30
|
-
```bash
|
31
|
-
yarn add rn-newarch-svga-player
|
32
|
-
```
|
33
|
-
|
34
|
-
> 若想更改库的别名 react-native-svga-player 来导入。你则需要把 rn-newarch-svga-player 库修改下,重新 yarn 执行
|
35
|
-
|
36
|
-
```diff
|
37
|
-
+ "dependencies": {
|
38
|
-
"@react-native-oh/react-native-harmony": "0.72.48",
|
39
|
-
"patch-package": "^8.0.0",
|
40
|
-
"postinstall-postinstall": "^2.1.0",
|
41
|
-
"react": "18.2.0",
|
42
|
-
"react-native": "0.72.5",
|
43
|
-
- "rn-newarch-svga-player":"^1.1.2"
|
44
|
-
+ "react-native-svga-player":"npm:rn-newarch-svga-player@1.1.2"
|
45
|
-
},
|
46
|
-
```
|
47
|
-
android 需要
|
48
|
-
|
49
|
-
```bash
|
50
|
-
./gradlew generateCodegenArtifactsFromSchema
|
51
|
-
```
|
52
|
-
|
53
|
-
ios 需要
|
54
|
-
|
55
|
-
```bash
|
56
|
-
cd ios
|
57
|
-
bundle install && bundle exec pod install
|
58
|
-
```
|
59
|
-
|
60
|
-
下面的代码展示了这个库的基本使用场景:
|
61
|
-
|
62
|
-
```js
|
63
|
-
import React, { useRef, useState } from "react";
|
64
|
-
import {
|
65
|
-
Button,
|
66
|
-
SafeAreaView,
|
67
|
-
ScrollView,
|
68
|
-
StatusBar,
|
69
|
-
StyleSheet,
|
70
|
-
Text,
|
71
|
-
View,
|
72
|
-
} from "react-native";
|
73
|
-
import { RNSvgaPlayer, SvgaPlayerRef } from "react-native-svga-player";
|
74
|
-
const App = () => {
|
75
|
-
const svgaPlayerRef = useRef < SvgaPlayerRef > null;
|
76
|
-
//播放网络资源
|
77
|
-
const [source, setSource] = useState(
|
78
|
-
"https://raw.githubusercontent.com/yyued/SVGAPlayer-iOS/master/SVGAPlayer/Samples/Goddess.svga"
|
79
|
-
);
|
80
|
-
//播放本地资源
|
81
|
-
// const [source, setSource] = useState(
|
82
|
-
// 'homePage_studyPlanner_computer_welcome.svga',
|
83
|
-
// );
|
84
|
-
return (
|
85
|
-
<SafeAreaView style={styles.container}>
|
86
|
-
<StatusBar barStyle={"dark-content"} />
|
87
|
-
<ScrollView showsVerticalScrollIndicator={false}>
|
88
|
-
<Text style={styles.welcome}>Svga</Text>
|
89
|
-
<RNSvgaPlayer
|
90
|
-
ref={svgaPlayerRef}
|
91
|
-
source={source}
|
92
|
-
autoPlay={true}
|
93
|
-
loops={1} // 循环次数,默认 0无限循环
|
94
|
-
clearsAfterStop={false} // 停止后清空画布,默认 true
|
95
|
-
style={styles.svgaStyle}
|
96
|
-
onFinished={() => {
|
97
|
-
console.log("播放完成");
|
98
|
-
}} // 播放完成回调
|
99
|
-
onLoaded={() => {
|
100
|
-
console.log("动画加载完成");
|
101
|
-
}}
|
102
|
-
/>
|
103
|
-
<View style={styles.flexAround}>
|
104
|
-
<Button
|
105
|
-
title="开始动画"
|
106
|
-
onPress={() => {
|
107
|
-
svgaPlayerRef.current?.startAnimation();
|
108
|
-
}}
|
109
|
-
/>
|
110
|
-
<Button
|
111
|
-
title="暂停动画"
|
112
|
-
onPress={() => {
|
113
|
-
// svgaPlayerRef.current?.pauseAnimation();
|
114
|
-
}}
|
115
|
-
/>
|
116
|
-
<Button
|
117
|
-
title="停止动画"
|
118
|
-
onPress={() => {
|
119
|
-
svgaPlayerRef.current?.stopAnimation();
|
120
|
-
}}
|
121
|
-
/>
|
122
|
-
</View>
|
123
|
-
<View style={[styles.flexAround, { marginTop: 20 }]}>
|
124
|
-
<Button
|
125
|
-
title="手动加载动画"
|
126
|
-
onPress={() => {
|
127
|
-
setSource(
|
128
|
-
"https://raw.githubusercontent.com/yyued/SVGAPlayer-iOS/master/SVGAPlayer/Samples/matteBitmap.svga"
|
129
|
-
);
|
130
|
-
}}
|
131
|
-
/>
|
132
|
-
<Button
|
133
|
-
title="指定帧开始"
|
134
|
-
onPress={() => {
|
135
|
-
// svgaPlayerRef.current?.stepToFrame(20, true);
|
136
|
-
}}
|
137
|
-
/>
|
138
|
-
<Button
|
139
|
-
title="指定百分比开始"
|
140
|
-
onPress={() => {
|
141
|
-
// svgaPlayerRef.current?.stepToPercentage(1, true);
|
142
|
-
}}
|
143
|
-
/>
|
144
|
-
</View>
|
145
|
-
</ScrollView>
|
146
|
-
</SafeAreaView>
|
147
|
-
);
|
148
|
-
};
|
149
|
-
export default App;
|
150
|
-
const styles = StyleSheet.create({
|
151
|
-
flexAround: { flexDirection: "row", justifyContent: "space-around" },
|
152
|
-
container: {
|
153
|
-
flex: 1,
|
154
|
-
},
|
155
|
-
svgaStyle: {
|
156
|
-
width: 150,
|
157
|
-
height: 150,
|
158
|
-
marginTop: 30,
|
159
|
-
},
|
160
|
-
welcome: {
|
161
|
-
fontSize: 20,
|
162
|
-
textAlign: "center",
|
163
|
-
margin: 10,
|
164
|
-
marginTop: 80,
|
165
|
-
},
|
166
|
-
instructions: {
|
167
|
-
textAlign: "center",
|
168
|
-
color: "#333333",
|
169
|
-
marginBottom: 5,
|
170
|
-
},
|
171
|
-
});
|
172
|
-
```
|
173
|
-
|
174
|
-
#### 新架构[Android/iOS]demo 请参考 <https://github.com/yrjwcharm/react-native-ohos/tree/feature/newarch/svgaplayer>
|
175
|
-
|
176
|
-
更多详情用法参考 [三端 Svga 动画统一使用点击这里](https://github.com/yrjwcharm/react-native-ohos/tree/feature/rnoh/svgaplayer)
|
177
|
-
|
178
|
-
#### 开源不易,希望您可以动一动小手点点小 ⭐⭐
|
179
|
-
|
180
|
-
#### 👴 希望大家如有好的需求踊跃提交,如有问题请提交 issue,空闲时间会扩充与修复优化
|
181
|
-
|
182
|
-
## 开源协议
|
183
|
-
|
184
|
-
本项目基于 [The MIT License (MIT)](https://github.com/yrjwcharm/react-native-ohos-svgaplayer/blob/master/LICENSE) ,请自由地享受和参与开源。
|