OHOS Rive Project
This project has two parts:
- Native build backend — Used to compile the Rive engine native libraries
- Rive Integration with HarmonyOS ArkTS — A guide to integrating the Rive into HarmonyOS ArkTS applications
Part 1: Native build guide
Clone the repository
git clone git@gitcode.com:openharmony-tpc/openharmony_tpc_samples.git
git submodule update --init --recursive ohos_rive/submodules/rive-runtime
git submodule update --init --recursive ohos_rive/library/src/main/cpp/boundscheck/third_party_bounds_checking_function
Prerequisites
1. Set the OHOS_NDK environment variable
-
Install the OpenHarmony SDK.
-
Locate the
nativedirectory inside the SDK, typically similar toD:\OpenHarmonySDK\api_version\native. -
Configure the variable:
- Open System variables → New
- Name:
OHOS_NDK - Value: full path to the SDK
nativedirectory - Click OK to save
-
Verify:
- Open a new Command Prompt
- Run
echo %OHOS_NDK%and verify the path matches your SDK location
If your SDK is not in the default location, use your actual path.
After this, you can build the OHOS Rive native project.
2. Install MSYS2 and configure PATH
-
Download and install MSYS2 (default path recommended:
C:\msys64)- https://www.msys2.org/
- After installation, open the MSYS2 terminal
-
In MSYS2, install the required tools:
pacman -S mingw-w64-x86_64-ninja mingw-w64-x86_64-premake mingw-w64-x86_64-python-ply make --noconfirm -
Add to Path (example for default install):
C:\msys64\mingw64\binC:\msys64\usr\bin
-
Verify in a new Command Prompt:
premake5 --version,python3 --version,sh --version,ninja --version,make --version
Part 2: Rive animation library for HarmonyOS
Overview
This is the HarmonyOS-native Rive engine. It enables HarmonyOS to utilize Rive vector animations with interactive playback and control.
What is Rive?
Rive is a modern vector animation runtime. Compared with traditional formats, it offers:
- Small file sizes (often much smaller than GIF or Lottie)
- Runtime rendering at full resolution
- Rich interactive animations
- Runtime state and parameter control
- Multiple platforms (Web, iOS, Android, HMS, etc.)
Installation
Requirements
- DevEco Studio 5.1.1 Release or newer
- HarmonyOS SDK API 12 or newer
Steps
-
Install from OHPM
ohpm install @ohos/rive -
Initialize in the entry ability
onCreate// EntryAbility.ets import { initializeRive } from '@ohos/rive'; onCreate() { try { initializeRive(); } catch (error) { console.error("Failed to initialize Rive library:", error); } }
Basic usage
Show a Rive animation on a page
import { RiveAnimationView } from 'library';
@Entry
@Component
struct AnimationPage {
build() {
Column() {
RiveAnimationView({
riveResource: '@rawfile/example_animation.riv', // .riv under rawfile
riveFit: 'cover',
riveAutoPlay: false // default true
})
.width('100%')
.height('30%')
}
}
}
Advanced usage
Switch artboard
RiveAnimationView({
riveResource: '@rawfile/multi_artboard.riv',
riveArtboard: 'Circle',
})
Control playback from code
@State riveView: RiveAnimationView | null = null;
RiveAnimationView({
riveResource: '@rawfile/button.riv',
riveAutoPlay: false,
onReady: (view) => {
this.riveView = view;
}
})
this.riveView?.play()
this.riveView?.pause()
this.riveView?.reset()
Load from network
Option A: direct URL
RiveAnimationView({
riveUrl: 'https://cdn.rive.app/animations/vehicles.riv',
})
.width('100%')
.height('100%')
Option B: HTTP then bytes
// Add network permission in module.json5
"requestPermissions": [{
"name": "ohos.permission.INTERNET",
}],
// Page code
private riveUrl = "https://cdn.rive.app/animations/juice_v7.riv"
@State riveView: RiveAnimationView | null = null;
RiveAnimationView({
onReady: (view) => {
this.riveView = view
}
})
.width('100%')
.height('100%')
const httpRequest = http.createHttp();
httpRequest.request(this.riveUrl, {
method: http.RequestMethod.GET,
connectTimeout: 30000,
readTimeout: 30000
}).then((response) => {
if (response.responseCode === 200) {
const arrayBuffer = response.result as ArrayBuffer;
this.riveView?.setRiveBytes(arrayBuffer)
} else {
console.error(`HttpPage: Network request failed: ${response.responseCode}`);
}
}).catch((error: Error) => {
console.error(`HttpPage: Network request error: ${error}`);
}).finally(() => {
httpRequest.destroy();
});
Directory layout
ohos_rive/
├── entry/ # Entry module
│ ├── src/main/
│ │ ├── ets/ # ArkTS
│ │ │ ├── common/
│ │ │ ├── entryability/
│ │ │ └── pages/
│ │ └── resources/
│ │ └── rawfile/ # .riv assets
├── library/ # Rive library module
│ ├── src/main/
│ │ ├── ets/
│ │ ├── cpp/ # Native C++
│ │ └── resources/
├── README.md # This file (English)
└── README_zh.md # Chinese readme
API reference
RiveAnimationView
Primary element for rendering and managing Rive animations within the HarmonyOS framework.
Properties
| Name | Type | Required | Description |
|---|---|---|---|
riveResource |
string | No | Local resource path (mutually exclusive with riveUrl) |
riveUrl |
string | No | Remote URL (mutually exclusive with riveResource) |
riveLoop |
number | No | Loop mode |
rendererType |
RendererType | No | Renderer type |
riveArtboard |
string | No | Artboard name; default is first artboard |
riveStateMachine |
string | No | State machine name |
riveAnimation |
string | No | Animation name |
riveFit |
string | No | Fit: contain, cover, fill, fitWidth, fitHeight, none, scaleDown |
alignmentIndex |
number | No | Alignment |
riveAutoPlay |
boolean | No | Auto-play (default true) |
onReady |
(view: RiveAnimationView) => void | No | Called when the view is ready |
Methods
| Method | Description |
|---|---|
play(animationName?: string, loop?: Loop, direction?: Direction, isStateMachine?: boolean, settleInitialState?: boolean) |
Play; optional animation name and options |
pause() |
Pause |
stop() |
Stop |
reset() |
Reset to initial state |
isPlaying() |
Returns whether playing |
setRiveFile(file: File, artboardName?, animationName?, stateMachineName?, autoplay?, autoBind?, fit?, alignment?, loop?) |
Load from File |
setRiveBytes(bytes: ArrayBuffer, artboardName?, animationName?, stateMachineName?, autoplay?, autoBind?, fit?, alignment?, loop?) |
Load from bytes |
setNumberState(stateMachineName: string, inputName: string, value: number) |
Set numeric SM input |
pauseAnimation(animationName: string, isStateMachine?: boolean) |
Pause named animation |
stopAnimation(animationName: string, isStateMachine?: boolean) |
Stop named animation |
setBooleanState(stateMachineName: string, inputName: string, value: boolean) |
Set boolean SM input |
setBooleanStateAtPath(inputName: string, value: boolean, path: string) |
Set boolean at path |
setTextRunValue(textRunName: string, textValue: string, path?: string) |
Set text run |
setRiveResource(resId: number|string, artboardName?, animationName?, stateMachineName?, autoplay?, autoBind?, fit?, alignment?, loop?) |
Load by resource id |
setArtboardName(name: string) |
Set active artboard |
getFit() |
Get Fit |
setFit(value: Fit) |
Set Fit |
setAlignment(value: Alignment) |
Set alignment |
getLayoutScaleFactor() |
Get layout scale |
setLayoutScaleFactor(value: number) |
Set layout scale |
registerListener(listener: RiveFileControllerListener) |
Register controller listener |
unregisterListener(listener: RiveFileControllerListener) |
Unregister listener |
addEventListener(listener: RiveEventListener) |
Add event listener |
removeEventListener(listener: RiveEventListener) |
Remove event listener |
getRenderer() |
Get Renderer |
getArtboard() |
Get active Artboard |
Alignment.fromIndex(index: number) |
Alignment from index |
Fit.fromString(fitString: string) |
Fit from string |
RiveManager.getInstance() |
Singleton RiveManager |
RiveManager.getInstance().init(context: Context, defaultRenderer?: RendererType) |
Init manager |
RiveManager.getInstance().setFallbackFont(context: Context, byteArray?: Uint8Array, opts?: FontOpts) |
Set fallback font |
RiveRenderImage.fromEncoded(encodedBytes: Uint8Array, rendererType?, premultiplied?) |
Decode to image |
RiveRenderImage.fromARGBInts(pixels: Uint32Array, width, height, rendererType?, premultiplied?) |
From ARGB |
RiveRenderImage.fromRGBABytes(pixelBytes: Uint8Array, width, height, rendererType?, premultiplied?) |
From RGBA bytes |
artboardByName(name: string) |
Artboard by name from file |
animationIndex(index: number) |
LinearAnimationInstance by index |
restoreControllerState(state: ControllerState) |
Restore controller state |
saveControllerState() |
Save controller state |
release() |
Decrement ref count |
RiveFont.make(bytes: Uint8Array, rendererType?: RendererType) |
Create RiveFont |
initializeRive
One-time library initialization; call at app startup.
import { initializeRive } from '@ohos/rive';
initializeRive();
Notes
- Place
.rivfiles underresources/rawfile. - Very large animations can hurt performance; optimize assets when possible.
- State machine and input names must match the
.rivfile exactly (case-sensitive). - Call
initializeRive()only once at startup.
Code obfuscation
-
For code obfuscation, see the OpenHarmony source obfuscation guide.
-
To keep
@ohos/rivefrom being obfuscated, add rules such as:
-keep
./oh_modules/@ohos/rive
License
This project is licensed under the MIT License.
Contributing
Please open Issues or submit Pull Requests — contributions are welcome.