HarmonyOS APP开发---"动效君"UI动效素材库App,需要用到这个库

HarmonyOS APP开发---"动效君"UI动效素材库App,需要用到这个库

素材库要一屏展示 20 个 Lottie 动画同时播放,还要准确还原 AE 的 Tint、阴影、遮罩特效。一代 Lottie 库在这种场景直接卡死主线程------@ohos/lottie-turbo 的子线程渲染能扛住,但 controller 管理不当会内存泄漏。
📦 仓库地址 | ohpm install @ohos/lottie-turbo


场景

"动效君"是给设计师和开发者用的动效素材库:

  • 素材瀑布流:一屏 12~20 个动画缩略预览,全部同时播放
  • 特效分类:按 AE 特效分(着色 Tint、阴影 Drop Shadow、遮罩 Set Matte、文字动画)
  • 详情预览:全屏播放,可调速度、逐帧查看、片段播放
  • 代码导出:展示该动画在鸿蒙上的接入代码

三个极限要求:

  1. 多动画同屏:20 个动画同时渲染,主线程方案必然卡死
  2. 特效还原准:Tint 不生效、阴影位置错,设计师一眼就看出来
  3. 内存不泄漏:用户浏览几百个素材,controller 管理不当内存持续涨

为什么是 lottie-turbo

需求 @ohos/lottie @ohos/lottie-turbo
20 个动画同屏 ❌ 主线程卡死 ✅ 子线程渲染
多动画加载 ⚠️ 排队 ✅ 并行加载
滑回已看过的 ❌ 重新解析 ✅ 内存缓存
滑出屏幕的 ⚠️ 继续渲染 ✅ 自动跳过绘制
逐帧/片段播放 ⚠️ ✅ 完整控制

关键实现

controller 生命周期管理(不泄漏的关键)

规则:一个 LottieView 配一个独立 controller。 多个 View 共享同一个 controller 时,销毁只处理单个动画,其余的会泄漏。

typescript 复制代码
import { LottieController, LottieView } from '@ohos/lottie-turbo'

@Entry
@Component
struct AssetLibraryPage {
  @State assets: AnimAsset[] = loadAssets()

  // ✅ 用 Map 管理:一个素材一个 controller,可精确清理
  private controllers: Map<string, LottieController> = new Map()

  private getController(id: string): LottieController {
    if (!this.controllers.has(id)) {
      this.controllers.set(id, new LottieController())
    }
    return this.controllers.get(id)!
  }

  // ✅ 页面销毁时统一停止并清理
  aboutToDisappear() {
    this.controllers.forEach((c, id) => {
      try { c.stop() } catch (err) { console.warn(`停止 ${id} 失败`) }
    })
    this.controllers.clear()
  }

  build() {
    WaterFlow() {
      ForEach(this.assets, (asset: AnimAsset) => {
        FlowItem() {
          Column() {
            LottieView({
              lottieId: asset.id,                              // 唯一 id
              resource: asset.resource,
              loop: true,
              autoplay: true,
              controller: this.getController(asset.id),        // ✅ 独立 controller
            })
              .width('100%').aspectRatio(1)

            Text(asset.name).fontSize(13).margin({ top: 6 }).maxLines(1)
          }.padding(8)
        }
        .onClick(() => router.pushUrl({ url: 'pages/Detail', params: { id: asset.id } }))
      }, (a: AnimAsset) => a.id)
    }
    .columnsTemplate('1fr 1fr 1fr')    // 三列,一屏约 12~15 个动画
    .columnsGap(8).rowsGap(8)
  }
}

为什么这里能扛住 20 个动画同屏:

机制 作用
并行加载 JSON 解析不排队,20 个同时开始
子线程渲染 帧计算不占主线程,主线程只合成
内存缓存 滑回去的动画不重新解析
不可见跳过绘制 滑出屏幕的自动停渲染

列表快速滑动的启停优化

typescript 复制代码
private visibleIds: Set<string> = new Set()

onVisibleAreaChange(visibleIds: string[]) {
  // 新进入可见区 → 播放
  visibleIds.forEach((id) => {
    if (!this.visibleIds.has(id)) this.controllers.get(id)?.start()
  })
  // 滑出可见区 → 暂停省资源
  this.visibleIds.forEach((id) => {
    if (!visibleIds.includes(id)) this.controllers.get(id)?.pause()
  })
  this.visibleIds = new Set(visibleIds)
}

onPageHide() { this.controllers.forEach((c) => c.pause()) }        // 页面切走全停
onPageShow() { this.visibleIds.forEach((id) => this.controllers.get(id)?.start()) }

详情页:逐帧与片段播放

typescript 复制代码
@Entry
@Component
struct AssetDetailPage {
  private controller: LottieController = new LottieController()   // ✅ 独立
  @State speed: number = 1.0
  @State progress: number = 0

  aboutToDisappear() { this.controller.stop() }   // ✅ 先停再销毁,避免时序问题

  build() {
    Column() {
      LottieView({
        lottieId: this.assetId,
        resource: $rawfile(`assets/${this.assetId}.json`),
        loop: true, autoplay: true,
        controller: this.controller,
        contentMode: 'AdaptiveHeight',
      }).width('100%').height(400)

      Row({ space: 12 }) {
        Button('上一帧').onClick(() => {
          this.controller.pause()
          this.progress = Math.max(0, this.progress - 0.01)
          this.controller.setProgress(this.progress)
        })
        Button('下一帧').onClick(() => {
          this.controller.pause()
          this.progress = Math.min(1, this.progress + 0.01)
          this.controller.setProgress(this.progress)
        })
      }

      Slider({ value: this.progress * 100 })
        .onChange((v: number) => {
          this.progress = v / 100
          this.controller.setProgress(this.progress)
        })

      // ✅ 片段播放:嵌套数组格式,不是平铺参数
      Button('播放前 30 帧').onClick(() => {
        this.controller.playSegments([[0, 30]])
      })
      Button('多段播放').onClick(() => {
        this.controller.playSegments([[0, 30], [60, 90]])
      })
    }
  }
}

特效验收清单(素材库的命门)

素材库的核心价值是"所见即所得"。社区修过一批 AE 特效还原问题------Tint 对描边不生效、Drop Shadow 位置不对、Set Matte 异常、天城文渲染错乱。

这类问题肉眼很难自查(动画"在动",只是细节不对),必须建验收清单:

typescript 复制代码
const EFFECT_CATEGORIES = [
  {
    key: 'tint', name: '着色 Tint',
    testAssets: ['tint_fill.json', 'tint_stroke.json'],   // ⚠️ 描边着色要单独测
    checkpoints: ['填充着色生效', '描边着色生效', '颜色值准确'],
  },
  {
    key: 'shadow', name: '阴影 Drop Shadow',
    testAssets: ['shadow_basic.json', 'shadow_blur.json'],
    checkpoints: ['阴影位置正确', '模糊半径准确', '透明度正确'],
  },
  {
    key: 'matte', name: '遮罩 Set Matte',
    testAssets: ['matte_alpha.json', 'matte_luma.json'],
    checkpoints: ['Alpha 遮罩生效', 'Luma 遮罩生效', 'Stroke All Masks 正常'],
  },
  {
    key: 'text', name: '文字动画',
    testAssets: ['text_chinese.json', 'text_emoji.json', 'text_devanagari.json'],
    checkpoints: ['中文字体正常', 'Emoji 不缺字', '特殊字符正常', '逐字时序正确'],
  },
]

升级 lottie-turbo 版本后,这套清单要重跑一遍------渲染细节的修复只有肉眼验收能确认。

同理,GIF 类素材建议准备已知帧率的标准文件做回归(如 10fps 每帧 100ms),帧时序错位这种问题靠感觉发现不了。


小结

"动效君"这个场景里,@ohos/lottie-turbo 解决了三件事:并行加载 + 子线程渲染扛住 20 个动画同屏、独立 controller + Map 管理 + 页面销毁清理保证不泄漏、完整的播放控制让设计师能逐帧验收细节。

动效素材库是 Lottie 库的极限压力测试场。如果你的 App 有多动画同屏、复杂 AE 特效、长时间浏览的场景,选它不会错------但记得建那份特效验收清单。

相关推荐
行者-全栈开发2 小时前
【鸿蒙心迹】三方库移植(一)——NAPI 把 C/C++ 库桥接到 ArkTS 的完整链路(HarmonyOS 7.x)
harmonyos·arkts·交叉编译·c/c++·napi·三方库移植
2601_949480062 小时前
开源鸿蒙平台 CMP 三方库「reveal」适配全流程
华为·开源·harmonyos
2401_zq136y032 小时前
开源鸿蒙平台 CMP 三方库「KToast」适配全流程
华为·开源·harmonyos
AI2中文网2 小时前
App Inventor 2 构建纯血鸿蒙 HarmonyOS NEXT App:证书、签名、真机安装到上架全流程
华为·harmonyos
贾伟康2 小时前
【共创稿事节】@State与@Prop的单向流
harmonyos·arkts·状态管理·state·prop
大雷神3 小时前
HarmonyOS7应用《拼棋派对》实战:模拟器回归验证与签名打包
harmonyos·arkui·harmonyos 7.0·玩转 arkts
贾伟康4 小时前
【共创稿事节】@Link双向绑定的适用边界
性能优化·实战·harmonyos·arkts·arkui
熊猫钓鱼>_>4 小时前
上架审核常见驳回与隐私合规清单:过审前先自查这 8 条【鸿蒙心迹】
开发语言·前端·华为·华为云·harmonyos·openharmony·ai制作
贾伟康4 小时前
【共创稿事节】布局审查工具与边界调试
harmonyos·arkui·inspector·性能排查·布局调试