Skip to content

limuyang2/pag-cmp

Repository files navigation

lib-pag-cmp

Maven Central Context7

lib-pag-cmp is a Compose Multiplatform wrapper for Tencent libpag. It provides a common PagView composable and platform implementations for rendering PAG animation files.

中文说明

Android and iOS targets use Tencent libpag 4.5.75.

Status

Platform Status Rendering path
Android Supported Native org.libpag.PAGView through AndroidView
iOS Supported Native PAGView through UIKitView
JVM Desktop Supported on macOS arm64 and x64 libpag offscreen render -> pixels -> Compose ImageBitmap
JS Supported libpag Web SDK canvas integration
WasmJS Supported libpag Web SDK canvas integration

The JVM artifact currently bundles native runtime files for macos-arm64 and macos-x64. Linux and Windows JVM native packages are not included yet.

Installation

Add the repository that contains the published artifacts, then depend on the common KMP artifact:

repositories {
    mavenCentral()
}

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("io.github.limuyang2:lib-pag-cmp:0.1.6")
        }
    }
}

Platform publications are produced as:

  • io.github.limuyang2:lib-pag-cmp
  • io.github.limuyang2:lib-pag-cmp-android
  • io.github.limuyang2:lib-pag-cmp-jvm
  • io.github.limuyang2:lib-pag-cmp-js
  • io.github.limuyang2:lib-pag-cmp-wasm-js
  • io.github.limuyang2:lib-pag-cmp-ios-arm64
  • io.github.limuyang2:lib-pag-cmp-ios-simulator-arm64

Basic Usage

Load a PAG file as bytes and pass it to PagView:

import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.github.limuyang2.libpag.cmp.PagScaleMode
import io.github.limuyang2.libpag.cmp.PagView

@Composable
fun LoadingAnimation(bytes: ByteArray) {
    PagView(
        bytes = bytes,
        modifier = Modifier.size(160.dp),
        isPlaying = true,
        repeatCount = 0,
        scaleMode = PagScaleMode.LetterBox,
    )
}

The example above receives raw bytes. This is the most portable loading mode and works on all supported targets.

To play a local .pag file, drop it under src/commonMain/composeResources/files/ and read it with the Compose Multiplatform resource API (org.jetbrains.compose.components:components-resources) — the same path works on every target:

import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.github.limuyang2.libpag.cmp.PagScaleMode
import io.github.limuyang2.libpag.cmp.PagView
import org.jetbrains.compose.resources.ExperimentalResourceApi
// `Res` is generated by the Compose resources plugin; its package follows your module setup.
import your.module.generated.resources.Res

@OptIn(ExperimentalResourceApi::class)
@Composable
fun LocalAnimation() {
    var bytes by remember { mutableStateOf<ByteArray?>(null) }
    LaunchedEffect(Unit) {
        bytes = Res.readBytes("files/loading.pag")
    }
    bytes?.let {
        PagView(
            bytes = it,
            modifier = Modifier.size(160.dp),
            scaleMode = PagScaleMode.LetterBox,
        )
    }
}

Alternatively, pass a local file path, Compose resource URI, or network URL directly with PagView(path). The library loads it asynchronously (nothing renders until ready; a load failure is logged, not thrown):

import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.github.limuyang2.libpag.cmp.PagScaleMode
import io.github.limuyang2.libpag.cmp.PagView

@Composable
fun RemoteAnimation(url: String) {
    PagView(
        path = url,
        modifier = Modifier.size(160.dp),
        scaleMode = PagScaleMode.LetterBox,
    )
}

For .pag files stored in src/commonMain/composeResources/files/, pass the URI returned by Res.getUri("files/name.pag"):

@Composable
fun ResourcePathAnimation() {
    PagView(
        path = Res.getUri("files/loading_bmp.pag"),
        modifier = Modifier.size(160.dp),
        scaleMode = PagScaleMode.LetterBox,
    )
}

Do not pass the raw resource-relative path ("files/loading_bmp.pag") to PagView(path). path must be either a platform-accessible local path/URI from Res.getUri(...), or an http/https URL.

Network URL behavior is platform-dependent:

  • Android uses libpag's native path loader.
  • JVM downloads through the JDK and then renders from bytes.
  • JS and WasmJS use browser fetch, so the remote server must be reachable from the browser and allow cross-origin access.
  • iOS uses libpag's native path loader; network loading is best-effort.

For GitHub-hosted PAG files, prefer raw.githubusercontent.com URLs. The Web implementation also normalizes common github.com/.../raw/... links before fetching.

On Android, iOS, and JVM, repeated rendering of the same file can load a composition once and pass it to PagView:

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import io.github.limuyang2.libpag.cmp.Pag
import io.github.limuyang2.libpag.cmp.PagView

@Composable
fun ReusedAnimation(bytes: ByteArray) {
    val composition = remember(bytes) { Pag.load(bytes) }

    DisposableEffect(composition) {
        onDispose { composition.close() }
    }

    PagView(composition = composition)
}

JS and WasmJS support both PagView(bytes) and PagView(path). PagView(composition) is not supported on Web targets yet.

Demo

The demo app validates three loading paths:

  • ByteArray: Res.readBytes("files/8.pag") -> PagView(bytes).
  • Local path: Res.getUri("files/loading_bmp.pag") -> PagView(path).
  • Network URL: remote PAG URL -> PagView(path).

Samples are displayed in a scrollable FlowRow, so adding more cases only requires appending a new PagSample entry in the demo data.

Parameters

PagView exposes the same common parameters on every supported platform:

  • isPlaying: starts or pauses playback.
  • progress: optional manual progress in 0.0..1.0. When set while paused, the current frame is flushed.
  • repeatCount: native libpag repeat count. 0 means infinite repeat.
  • scaleMode: controls how PAG content fits inside the render area.
  • cacheEnabled: enables libpag render cache.
  • videoEnabled: enables video sequence rendering when the PAG file contains video content.
  • useDiskCache: enables libpag disk cache on platforms that expose it.

scaleMode only affects the content transform inside the native PAG renderer. It does not measure, resize, or otherwise affect the Compose PagView layout bounds.

Scale Modes

  • None: keeps the composition at its original size and position.
  • Stretch: scales width and height independently to fill the render area. Content may be distorted.
  • LetterBox: scales uniformly until the whole composition is visible. Empty space may remain on one axis.
  • Zoom: scales uniformly until the render area is fully covered. Content may be cropped on one axis.

Web Runtime

The JS and WasmJS implementations render through the libpag Web SDK on an overlay canvas. The demo bundles the SDK files under webApp/src/webMain/resources/pag/ and loads pag/libpag-bootstrap.js on demand.

If your app hosts the library differently, make sure the libpag Web SDK JavaScript and wasm runtime are available at the paths used by your app. Browser network loading is subject to normal web rules: the URL must be reachable from the page and must pass CORS checks.

JVM Runtime

The JVM implementation uses a JNI bridge and bundled native libpag runtime files. At runtime, the library extracts those files from the jar and loads them with System.load().

For local debugging, external native files can be supplied with JVM system properties:

-Dlibpag.cmp.libpag=/path/to/libpag
-Dlibpag.cmp.bridge=/path/to/libpag_cmp_jvm.dylib

See BUILD.md for details about rebuilding and replacing JVM native artifacts.

Build Checks

Useful verification commands:

./gradlew :lib-pag-cmp:compileAndroidMain
./gradlew :lib-pag-cmp:compileKotlinIosArm64
./gradlew :lib-pag-cmp:compileKotlinIosSimulatorArm64
./gradlew :lib-pag-cmp:compileKotlinJvm
./gradlew :lib-pag-cmp:compileKotlinJs
./gradlew :lib-pag-cmp:compileKotlinWasmJs

Publication metadata can be checked with:

./gradlew :lib-pag-cmp:generatePomFileForWasmJsPublication

About

基于 Tencent libpag 的 Compose Multiplatform 封装库,提供统一的 PagView API,用于在 Android、iOS、JVM Desktop、JS 和 WasmJS 中渲染 PAG 动画,支持 bytes、本地路径和网络 URL 等多种加载方式。

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors