HarmonyOS《柚兔学伴》项目实战12-Lottie 动画集成

第12篇:Lottie 动画集成

Lottie 是 Airbnb 开源的高性能动画库,可以将 After Effects 导出的 JSON 动画文件直接在移动端渲染。在 HarmonyOS 生态中,Lottie 同样得到了支持。本篇详解"柚兔学伴"项目中 Lottie 动画的四个应用场景及集成要点。


一、Lottie 在 HarmonyOS 中的两种库

项目中使用了两个 Lottie 相关的库:

库名 作用
@ohos/lottie 核心渲染引擎,负责解析 JSON 并绘制动画
@jjr/lottie_component ArkUI 声明式封装,提供 Lottie 组件和 LottieController

@jjr/lottie_component 是对 @ohos/lottie 的 ArkUI 包装,让我们可以像使用原生组件一样在 build() 中声明 Lottie 动画,无需手动管理 Canvas。

导入方式

typescript 复制代码
import { Lottie, LottieController } from '@jjr/lottie_component';

二、LottieController 动画控制器

每个 Lottie 动画实例对应一个 LottieController,用于控制动画的播放、暂停等行为:

typescript 复制代码
controller: LottieController = new LottieController()
alarmController: LottieController = new LottieController()
finishController: LottieController = new LottieController()

控制器支持的主要操作:

方法 说明
play() 播放动画
pause() 暂停动画
stop() 停止并重置动画
setProgress(0~1) 跳转到指定进度

在项目中,大部分动画使用 autoPlay: true 自动播放,控制器主要用于在特定时机手动触发播放或停止。


三、四大应用场景

场景1:倒计时闹钟提醒(循环播放)

当番茄钟倒计时归零时,弹出闹钟动画:

typescript 复制代码
@State alarmVisible: boolean = false
alarmController: LottieController = new LottieController()

@Builder
alarmBuild() {
  Column({ space: 15 }) {
    Lottie({
      controller: this.alarmController,
      animationPath: 'lottie/lottie_alarm.json',
      autoPlay: true,
      loop: true,
    })
      .width(80)
      .height(80)

    Text('时间到')
      .fontColor($r('app.color.app_primary'))
      .fontWeight(FontWeight.Bold)
  }.padding(15)
}

IBestDialog({
  visible: $alarmVisible,
  defaultBuilder: (): void => this.alarmBuild(),
  onConfirm: (() => {
    this.alarmVisible = false
    this.timerController.reset()
  })
})

关键配置

  • autoPlay: true:弹窗出现时自动播放
  • loop: true:循环播放,直到用户点击确认关闭

这个场景中,Lottie 动画嵌套在 IBestDialogdefaultBuilder 中,形成"动画+弹窗"的组合提醒效果。闹钟动画的循环播放增强了紧迫感,用户必须主动确认才能关闭。

场景2:任务完成庆祝(单次播放)

当所有待办事项都完成时,播放庆祝动画:

typescript 复制代码
@State finishVisible: boolean = false
finishController: LottieController = new LottieController()

@Builder
finishBuild() {
  Column({ space: 15 }) {
    Lottie({
      controller: this.finishController,
      animationPath: 'lottie/lottie_done.json',
      autoPlay: true,
      loop: false,
    })
      .width(120)
      .height(120)

    Text('你真棒,完成所有任务,积分+1!')
      .fontColor($r('app.color.app_primary'))
      .fontWeight(FontWeight.Bold)
  }.padding(15)
}

关键配置

  • autoPlay: true:弹窗出现时自动播放
  • loop: false:只播放一次,完成感更强

触发逻辑:

typescript 复制代码
CustomImageToggle({
  isOn: item.isCompleted,
  onToggleChange: (value) => {
    item.isCompleted = value;
    this.finishVisible = this.arr.every(item => item.isCompleted === true);
  }
});

当最后一个任务被标记完成时,finishVisible 自动设为 true,弹窗弹出并播放庆祝动画。

场景3:汉字查询等待(StrokeView)

在练字功能中,查询汉字详情需要网络请求,等待期间播放 Lottie 动画替代传统 LoadingProgress:

typescript 复制代码
controller: LottieController = new LottieController()

Column({ space: 10 }) {
  if (this.strokeModel.loadingStatus == LoadingStatus.SUCCESS) {
    this.buildWordDetail()
  } else if (this.strokeModel.loadingStatus == LoadingStatus.FAILED) {
    this.buildEmptyView()
  } else {
    Lottie({
      controller: this.controller,
      animationPath: 'lottie/lottie_waiting.json',
      autoPlay: true,
      loop: true,
    })
      .width(90)
      .height(90)
  }
}

关键配置

  • autoPlay: true + loop: true:持续播放直到数据返回
  • 根据三种加载状态(加载中/成功/失败)切换不同 UI

这种"三态切换"模式将 Lottie 动画作为加载态的视觉表达,比系统默认的 LoadingProgress 更生动。

场景4:语音录制动画(ChatPage)

在 AI 对话页面,点击录音按钮后显示录制动画:

typescript 复制代码
controller: LottieController = new LottieController()
@State isShowRecord: boolean = false

Stack() {
  // 正常状态:显示录音按钮
  Row() {
    Button('点击 说话', { stateEffect: true, type: ButtonType.Normal })
      .linearGradient({ angle: 90, colors: [[0xFF33FF, 0.0], [0x1C55FF, 1]] })
      .borderRadius(30)
      .height(50)
      .width('100%')
      .onClick(async () => {
        grantPermission().then(async (isGranted: boolean) => {
          if (isGranted) {
            this.isShowRecord = true
            RecordUtils.getInstance().startRecordingProcess()
          } else {
            ToastUtil.showToast('录音权限未获取')
          }
        })
      })
  }
  .visibility(this.isShowRecord ? Visibility.None : Visibility.Visible)

  // 录制状态:显示动画 + 控制按钮
  Row() {
    Image($r('app.media.ic_record_close')).width(30)
      .onClick(() => {
        this.isShowRecord = false
      })
    Lottie({
      controller: this.controller,
      animationPath: 'lottie/lottie_record.json',
      autoPlay: true,
      loop: true,
    })
      .width(90)
      .height(90)

    Image($r('app.media.ic_record_send')).width(30)
      .onClick(() => {
        this.isShowRecord = false
        RecordUtils.getInstance().stopRecordingProcess().then((voicePath: string) => {
          // 上传录音并处理
        })
      })
  }
  .visibility(this.isShowRecord ? Visibility.Visible : Visibility.None)
}

关键配置

  • autoPlay: true + loop: true:录音期间持续播放
  • 通过 isShowRecord 切换正常/录制两种 UI 状态

录音动画布局为三段式:取消(左)+ 动画(中)+ 发送(右),Lottie 动画占据中心位置,视觉上传达"正在录音"的实时感。


四、动画资源文件管理

项目中的 Lottie JSON 文件统一存放在 rawfile/lottie/ 目录下:

复制代码
resources/rawfile/lottie/
├── lottie_alarm.json    # 闹钟提醒动画
├── lottie_done.json     # 完成庆祝动画
├── lottie_waiting.json  # 等待加载动画
└── lottie_record.json   # 录制中动画

引用时使用相对路径:

typescript 复制代码
animationPath: 'lottie/lottie_alarm.json'

Lottie 组件会自动从 rawfile 目录加载对应文件,无需手动读取。


五、Lottie + IBestDialog 组合模式

项目中两次使用了"Lottie 动画嵌入自定义弹窗"的组合:

typescript 复制代码
IBestDialog({
  visible: $$someVisible,
  defaultBuilder: (): void => someBuild(),  // Builder 中包含 Lottie 动画
  onConfirm: (() => {
    this.someVisible = false
  })
})

这种组合的优势:

  1. 视觉冲击力:纯文字弹窗容易忽略,动画弹窗吸引力强
  2. 情绪传达:闹钟动画传达"紧迫",庆祝动画传达"喜悦"
  3. 无需额外资源:Lottie JSON 文件体积小(通常 10-50KB),远低于 GIF 或视频

六、Lottie 组件核心参数

参数 类型 说明
controller LottieController 动画控制器
animationPath string rawfile 中的 JSON 路径
autoPlay boolean 是否自动播放
loop boolean 是否循环播放

autoPlayloop 的组合策略:

autoPlay loop 适用场景
true true 等待、录制、提醒等持续性动画
true false 庆祝、完成等一次性动画
false true/false 需要手动触发的动画

七、业务逻辑与动画的联动

项目中动画的触发与业务逻辑紧密耦合:

复制代码
倒计时归零 → alarmVisible = true → 闹钟动画循环播放 → 用户确认 → 动画消失 + 计时器重置
任务全部完成 → finishVisible = true → 庆祝动画单次播放 → 用户确认 → 动画消失 + 计时器重置
网络请求中 → loadingStatus != SUCCESS → 等待动画循环播放 → 数据返回 → 动画替换为内容
开始录音 → isShowRecord = true → 录制动画循环播放 → 发送/取消 → 动画消失

核心原则:动画是状态的视觉表达,而非独立存在。每个 Lottie 动画都有对应的状态变量控制其可见性,状态变化驱动动画的出现与消失。


八、小结

要点 说明
库选择 @jjr/lottie_component 提供声明式 API,比直接使用 @ohos/lottie 更简洁
autoPlay 弹窗/条件渲染中的动画建议设为 true,出现即播放
loop 策略 持续性状态用 true,一次性事件用 false
资源管理 JSON 文件放 rawfile/lottie/,用相对路径引用
状态联动 动画可见性由业务状态驱动,避免脱离上下文的动画
相关推荐
l134062082351 小时前
HarmonyOS应用开发实战:小事记 - 多媒体文件上传:@ohos.net.http 的 multipart/form-data 请求构造
后端·华为·harmonyos·鸿蒙系统
youtootech1 小时前
HarmonyOS《柚兔学伴》项目实战16-录音功能与权限管理
华为·harmonyos
xd1855785551 小时前
睡眠质量评估 —— 鸿蒙AI智能助手开发全流程解析
人工智能·华为·harmonyos·鸿蒙
Jcc2 小时前
鸿蒙 Navigation 模块化实践
harmonyos
woshihuanglaoshi2 小时前
参数验证_Flutter在鸿蒙平台确保路由参数类型安全
学习·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
绝世番茄2 小时前
鸿蒙原生 ArkTS 布局之 List 的单选与多选模式实战指南
华为·list·harmonyos·鸿蒙
胡琦博客2 小时前
HarmonyOS 智能工具箱(三):语音交互工具
交互·xcode·harmonyos
国服第二切图仔2 小时前
HarmonyOS7新特性之沉浸光感:新一代材质渲染技术解析
harmonyos
●VON3 小时前
鸿蒙 PC Markdown 编辑器链接补全与离线校验:中文路径、标题锚点与授权边界
华为·编辑器·harmonyos·鸿蒙