鸿蒙 6.1 API 23 开发坑系列篇 6:@ohos.animator 动画器坑——API 12 废弃 onframe/createAnimator 迁移 onFrame 驼峰 + getUIContext().createAnimator 根因

本文是「鸿蒙 6.1 API 23 开发坑系列」第 6 篇(ArkUI 系第 6 篇)。本篇讲 @kit.ArkUIAnimator as animator namespace(API 6+,鸿蒙 6.1 API 23 基座)——帧动画 AnimatorResult + onFrame/onFinish/onCancel/onRepeat 回调 + play/pause/resume/cancel/reverse 控制。鸿蒙坑根因:① import 真路径是 @kit.ArkUI 不是 @ohos.animator(鸿蒙 6.1 统一入口,Animator 是 namespace 必须 import { Animator as animator } 起 alias);② API 12 废弃全小写 onframe/onfinish/oncancel/onrepeat,迁移到驼峰 onFrame/onFinish/onCancel/onRepeat;③ animator.create()/createAnimator() 废弃,迁移到 this.getUIContext().createAnimator();④ AnimatorResult 必须持有引用避免析构,aboutToDisappearcancel() 释放避免循环依赖内存泄漏;⑤ iterations 支持 -1 无限播放(0 不播放,正数 NN 次)。

一、开篇:鸿蒙 animator 不是 React requestAnimationFrame,是「AnimatorResult 帧回调 + 持引用」

你写 React 时,帧动画用 requestAnimationFrame(回调传 timestamp,自己插值):

// React requestAnimationFrame:回调传 timestamp,自己算插值
let start: number
const animate = (ts: number) => {
  if (!start) start = ts
  const progress = (ts - start) / 2000  // 自己算 progress(0~1)
  element.style.width = `${progress * 300}px`  // 自己改 DOM
  if (progress < 1) requestAnimationFrame(animate)  // 自己递归下一帧
}
requestAnimationFrame(animate)  // ❌ React 自己管插值 + 递归 + 取消

你写鸿蒙 ArkTS 时,帧动画用 AnimatorResultgetUIContext().createAnimator() 造,onFrame 回调自动插值,play/cancel 控制):

// ArkTS AnimatorResult:onFrame 回调自动插值,play/cancel 控制
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'  // ✅ 真路径 @kit.ArkUI 不是 @ohos.animator

const options: AnimatorOptions = {
  duration: 2000, easing: 'ease', fill: 'forwards', direction: 'normal',
  iterations: 1, begin: 0, end: 300  // ✅ begin/end 定义插值范围,onFrame 自动算 progress
}
const result: AnimatorResult = this.getUIContext().createAnimator(options)  // ✅ 不是废弃的 animator.create()
result.onFrame = (progress: number) => {  // ✅ 驼峰 onFrame(API 12+),不是废弃的 onframe
  this.width = progress  // ✅ progress 自动从 begin 插到 end,不用自己算
}
result.play()  // ✅ play() 启动,cancel() 取消,不用自己递归
// 鸿蒙坑根因:onFrame 驼峰不是废弃 onframe,createAnimator 走 getUIContext() 不是 animator.create()

React requestAnimationFrame vs 鸿蒙 AnimatorResult 的区别:React 把帧动画当浏览器 API(requestAnimationFrame(cb),回调传 timestamp,自己算插值 + 递归下一帧 + 取消用 cancelAnimationFrame),ArkTS 把帧动画当 ArkUI 命名空间对象(getUIContext().createAnimator(options)AnimatorResultonFrame 回调自动从 begin 插到 endplay/pause/resume/cancel/reverse 控制)。根因不是浏览器 API 是 ArkUI 命名空间对象——鸿蒙 onFrame 回调的 progress 自动插值,不用自己算 timestamp;但要持有 AnimatorResult 引用避免析构,aboutToDisappearcancel() 释放避免循环依赖内存泄漏。

二、根因:鸿蒙 animator 的五个绑定机制

鸿蒙 @kit.ArkUIAnimator as animator namespace(API 6+)核心导出 AnimatorOptions/AnimatorResult/SimpleAnimatorOptions 类型 + 废弃 animator.create()/createAnimator() 顶层函数。绑定机制来自五重根因。

机制 1:import 真路径是 @kit.ArkUI 不是 @ohos.animator——Animator namespace as animator alias

鸿蒙坑根因:import 真路径是 @kit.ArkUI,不是旧文档的 @ohos.animator,且 Animator 是 namespace 必须 as animator 起 alias:

// ❌ 鸿蒙坑:import @ohos.animator 是旧文档路径(鸿蒙 6.1 统一 @kit.ArkUI 入口)
import animator from '@ohos.animator'  // ❌ @ohos.animator 是旧文档路径(鸿蒙 6.1 统一 @kit.ArkUI)
// ❌ import { animator } from '@kit.ArkUI'  // ❌ namespace 真名是 Animator 不是 animator

// ✅ 正确用法:import { Animator as animator } from '@kit.ArkUI'——namespace alias
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'  // ✅ 真路径 @kit.ArkUI
// 鸿蒙坑根因:真路径 @kit.ArkUI 不是 @ohos.animator,Animator namespace 必须 as animator alias

import 真路径坑根因:鸿蒙 6.1 把 ArkUI 所有子模块统一到 @kit.ArkUI 入口(animator/modifier/observer/node/UIContext 都从 @kit.ArkUI import),旧文档的 @ohos.animator 是废弃路径。Animator 是 namespace(不是 default export),直接 import { animator } 会报 has no exported member 'animator'(namespace 真名是 Animator 大写 A),必须 import { Animator as animator } 起 alias(小写 animator 跟旧文档习惯一致)。鸿蒙坑@ohos.animator 旧路径编译错 Cannot find module{ animator } 命名错 has no exported member 'animator'——真路径 @kit.ArkUI,namespace 真名 Animator,必须 as animator alias。

机制 2:API 12 废弃全小写 onframe/onfinish/oncancel/onrepeat——迁移到驼峰 onFrame/onFinish/onCancel/onRepeat

鸿蒙坑根因:API 12 废弃全小写回调名,迁移到驼峰:

// ❌ 鸿蒙坑:API 12 废弃全小写 onframe/onfinish/oncancel/onrepeat
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

const result: AnimatorResult = this.getUIContext().createAnimator({ duration: 2000, begin: 0, end: 300 })
// ❌ 废弃 API(API 6~11):全小写 onframe/onfinish/oncancel/onrepeat
result.onframe = (progress: number) => { }  // ❌ API 12 废弃(驼峰 onFrame)
result.onfinish = () => { }  // ❌ API 12 废弃(驼峰 onFinish)
result.oncancel = () => { }  // ❌ API 12 废弃(驼峰 onCancel)
result.onrepeat = () => { }  // ❌ API 12 废弃(驼峰 onRepeat)

// ✅ 正确用法:API 12+ 驼峰 onFrame/onFinish/onCancel/onRepeat
result.onFrame = (progress: number) => { }  // ✅ 驼峰 onFrame(API 12+)
result.onFinish = () => { }  // ✅ 驼峰 onFinish
result.onCancel = () => { }  // ✅ 驼峰 onCancel
result.onRepeat = () => { }  // ✅ 驼峰 onRepeat
// 鸿蒙坑根因:API 12 废弃全小写 onframe,迁移到驼峰 onFrame(首字母大写)

废弃回调名坑根因:鸿蒙 API 6~11 用全小写 onframe/onfinish/oncancel/onrepeat(跟 JS 习惯一致),API 12 废弃迁移到驼峰 onFrame/onFinish/onCancel/onRepeat(首字母大写,跟 ArkTS 其他回调统一)。鸿蒙坑:用废弃全小写 onframe 不会编译错(是 deprecated 不是 removed),但会有 IDE 警告 Since API version 12, use onFrame instead,且后续版本可能真 removed——新代码必须驼峰 onFrame。React onAnimationEnd/onTransitionEnd 本就是驼峰,鸿蒙 API 12 后跟前端习惯统一了。

机制 3:animator.create()/createAnimator() 废弃——迁移到 getUIContext().createAnimator()

鸿蒙坑根因:animator.create()/createAnimator() 顶层函数废弃,迁移到 this.getUIContext().createAnimator()

// ❌ 鸿蒙坑:animator.create()/createAnimator() 废弃(API 12 废弃)
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

const options: AnimatorOptions = { duration: 2000, begin: 0, end: 300 }
// ❌ 废弃 API(API 6~11):animator.create() / createAnimator() 顶层函数
const result1: AnimatorResult = animator.create(options)  // ❌ API 12 废弃(迁移到 getUIContext().createAnimator())
const result2: AnimatorResult = animator.createAnimator(options)  // ❌ API 12 废弃(同 create)

// ✅ 正确用法:this.getUIContext().createAnimator()——UI 上下文方法(API 12+)
const result: AnimatorResult = this.getUIContext().createAnimator(options)  // ✅ 走 UIContext 不是顶层函数
// 鸿蒙坑根因:animator.create() 废弃,迁移到 getUIContext().createAnimator()(UI 上下文方法)

废弃 create 坑根因:鸿蒙 API 6~11 用 animator.create(options)/animator.createAnimator(options) 顶层函数造 AnimatorResult,API 12 废弃迁移到 this.getUIContext().createAnimator(options)UIContext 的方法,跟 getUIContext().getKeyboardAvoidMode() 等统一走 UI 上下文)。鸿蒙坑:用废弃 animator.create() 不会编译错(deprecated),但 IDE 警告 Since API version 12, use getUIContext().createAnimator() instead,且废弃的顶层函数没有 UI 上下文绑定,无法走组件级 UI 线程安全——新代码必须 this.getUIContext().createAnimator()getUIContext()@Component 组件的内置方法(篇 4 讲过 UIContext 坑),返回当前组件的 UI 上下文。

机制 4:AnimatorResult 必须持有引用避免析构——aboutToDisappear 要 cancel() 释放

鸿蒙坑根因:AnimatorResult 必须持有引用避免动画过程中被析构,aboutToDisappearcancel() 释放避免循环依赖内存泄漏:

// ❌ 鸿蒙坑:AnimatorResult 不持引用会被析构,aboutToDisappear 不 cancel 内存泄漏
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

@Entry
@Component
struct Index {
  // ❌ 不持引用:局部变量造的 AnimatorResult 在方法结束后被析构,动画中断
  demonstrateBad() {
    const result: AnimatorResult = this.getUIContext().createAnimator({ duration: 2000, begin: 0, end: 300 })
    result.onFrame = (progress: number) => { this.width = progress }
    result.play()  // ❌ result 是局部变量,方法结束后被析构,动画中断
  }

  // ✅ 正确用法:持有 AnimatorResult 引用(@State 或 private 字段),aboutToDisappear cancel() 释放
  private animatorResult: AnimatorResult | null = null  // ✅ 持引用避免析构

  demonstrateGood() {
    this.animatorResult = this.getUIContext().createAnimator({ duration: 2000, begin: 0, end: 300 })
    this.animatorResult.onFrame = (progress: number) => { this.width = progress }
    this.animatorResult.play()  // ✅ this.animatorResult 持引用,动画不被析构
  }

  aboutToDisappear() {
    this.animatorResult?.cancel()  // ✅ cancel() 取消动画,释放 AnimatorResult
    this.animatorResult = null  // ✅ 清空引用避免循环依赖导致内存泄漏
  }
}
// 鸿蒙坑根因:AnimatorResult 必须持引用避免析构,aboutToDisappear cancel() 释放避免内存泄漏

持有引用坑根因:鸿蒙 AnimatorResult 对象通过回调捕获了自定义组件对象(onFramethis.width = progressthis 是组件),形成循环引用(组件 → AnimatorResult → 回调 → 组件)。如果不持有 AnimatorResult 引用(局部变量方法结束析构),动画中断;如果持有但 aboutToDisappearcancel() 释放,循环引用导致组件销毁后 AnimatorResult 仍持引用,内存泄漏。鸿蒙坑:React requestAnimationFrame 的回调也捕获 this 但浏览器 GC 能处理循环引用,鸿蒙 ArkTS 的 GC 对循环引用处理弱,必须手动 cancel() + 清空引用——跟 React cancelAnimationFramecomponentWillUnmount 清理同理。

机制 5:iterations 支持 -1 无限播放——0 不播放,正数 N 播 N 次

鸿蒙坑根因:AnimatorOptions.iterations 支持 -1 无限播放,0 不播放,正数 NN 次:

// ✅ iterations 语义:-1 无限播放,0 不播放,正数 N 播 N 次
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

const infinite: AnimatorOptions = { duration: 1000, iterations: -1, begin: 0, end: 200 }  // ✅ -1 无限播放
const once: AnimatorOptions = { duration: 1000, iterations: 1, begin: 0, end: 200 }  // ✅ 1 播 1 次
const twice: AnimatorOptions = { duration: 1000, iterations: 2, begin: 0, end: 200 }  // ✅ 2 播 2 次
const zero: AnimatorOptions = { duration: 1000, iterations: 0, begin: 0, end: 200 }  // ✅ 0 不播放(play() 无效)

// ✅ direction: 'alternate' 反向交替(跟 iterations=-1 配合无限来回)
const alternate: AnimatorOptions = {
  duration: 1000, iterations: -1, direction: 'alternate',  // ✅ alternate 反向交替无限来回
  begin: 0, end: 200
}
// 鸿蒙坑根因:iterations -1 无限播放,0 不播放,正数 N 播 N 次,alternate 反向交替

iterations 语义坑根因AnimatorOptions.iterationsnumber 类型,语义:-1 无限播放(直到 cancel() 或组件销毁),0 不播放(play() 调了也无效,相当于禁用),正数 NN 次(播完触发 onFinish)。配合 direction: 'alternate'(反向交替,奇数次正向偶数次反向)可做无限来回动画。鸿蒙坑:React CSS animation-iteration-count: infinite 是字符串 infinite,鸿蒙 iterations: -1 是数字 -1(不是字符串 'infinite');React 0 是播放 0 次(禁用),鸿蒙 0 也是不播放,但鸿蒙 -1 是无限(React CSS 不支持负数)。

三、真机配图:鸿蒙 @ohos.animator 动画器坑——import 真路径 + onFrame 驼峰 + createAnimator

animator 初始态 import 真路径态 onFrame 驼峰新 API 态 iterations=-1 无限播放态 cancel + reverse 态

真机配图展示鸿蒙 @ohos.animator 动画器坑:

  • 初始态:鸿蒙 6.1 @ohos.animator 动画器坑标题,4 个验证按钮(① import 路径真名 / ② onFrame 驼峰新 API / ③ iterations=-1 无限播放 / ④ cancel + reverse),动画状态(animatorStatus 未跑 + frameValue/frameCount/finish/repeat/cancel 计数),要点说明 7 条
  • import 真路径态:点击「① 验证 import 路径真名」按钮,显示「✅ import { Animator as animator } from @kit.ArkUI——真路径不是 @ohos.animator」——import 真路径 @kit.ArkUI 验证
  • onFrame 驼峰新 API 态:点击「② 验证 onFrame 驼峰新 API」按钮,显示「✅ onFrame 驼峰 API 验证:getUIContext().createAnimator() + onFrame(不是废弃 onframe)」+ 动画状态 frameValue 在变化 + frameCount 在累加——onFrame 驼峰 + getUIContext().createAnimator() 验证
  • iterations=-1 无限播放态:点击「③ 验证 iterations=-1 无限播放」按钮,显示「✅ iterations=-1 无限播放验证:alternate 反向交替 + play/pause/resume」+ frameValue 在变化——iterations=-1 无限播放 + alternate 反向交替验证
  • cancel + reverse 态:点击「④ 验证 cancel + reverse」按钮,显示「✅ cancel + reverse 验证:cancel() 取消 + reverse() 反向播放方法」+ 动画状态——cancel() 取消 + reverse() 反向播放验证

四、真解法:鸿蒙 @ohos.animator 的四个场景

场景 1:import { Animator as animator } from @kit.ArkUI + onFrame 驼峰——90% 场景首选

基础帧动画用 import { Animator as animator } from '@kit.ArkUI' + this.getUIContext().createAnimator() + 驼峰 onFrame

// ✅ 场景 1:import { Animator as animator } from @kit.ArkUI + onFrame 驼峰(API 12,90% 场景首选)
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'  // ✅ 真路径 + namespace alias

@Entry
@Component
struct Index {
  @State width: number = 0
  private animatorResult: AnimatorResult | null = null  // ✅ 持引用避免析构

  startAnimation() {
    const options: AnimatorOptions = {
      duration: 2000, easing: 'ease', delay: 0, fill: 'forwards',
      direction: 'normal', iterations: 1, begin: 0, end: 300  // ✅ begin/end 定义插值范围
    }
    // ✅ this.getUIContext().createAnimator()——不是废弃的 animator.create()
    this.animatorResult = this.getUIContext().createAnimator(options)
    // ✅ 驼峰 onFrame(API 12+)——不是废弃的 onframe(全小写)
    this.animatorResult.onFrame = (progress: number) => {
      this.width = progress  // ✅ progress 自动从 begin(0) 插到 end(300)
    }
    this.animatorResult.onFinish = () => {  // ✅ 驼峰 onFinish
      console.info('动画完成')
    }
    this.animatorResult.play()  // ✅ play() 启动动画
  }

  aboutToDisappear() {
    this.animatorResult?.cancel()  // ✅ cancel() 释放避免循环依赖内存泄漏
    this.animatorResult = null
  }

  build() { Column({ space: 8 }) { Text('demo').width(this.width) } }
}
// import @kit.ArkUI + onFrame 驼峰 + getUIContext().createAnimator():90% 场景首选

鸿蒙 @ohos.animator API 真名坑import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'(真路径 @kit.ArkUI 不是 @ohos.animatorAnimator namespace 必须 as animator alias);this.getUIContext().createAnimator(options: AnimatorOptions): AnimatorResultUIContext 方法,不是废弃的 animator.create() 顶层函数);AnimatorResult.onFrame/onFinish/onCancel/onRepeat(驼峰,API 12+,不是废弃的全小写 onframe/onfinish/oncancel/onrepeat);AnimatorResult.play()/pause()/resume()/cancel()/reverse()(运行时控制方法);SysCap SystemCapability.ArkUI.ArkUI.Full@crossplatform 跨平台;@atomicservice 原子化服务。

场景 2:iterations=-1 无限播放 + direction=‘alternate’ 反向交替

无限来回动画用 iterations: -1 + direction: 'alternate'

// ✅ 场景 2:iterations=-1 无限播放 + direction='alternate' 反向交替(API 6)
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

const options: AnimatorOptions = {
  duration: 1000, easing: 'linear', delay: 0, fill: 'forwards',
  direction: 'alternate',  // ✅ alternate 反向交替(奇数次正向,偶数次反向)
  iterations: -1,  // ✅ -1 无限播放(直到 cancel() 或组件销毁)
  begin: 0, end: 200
}
this.animatorResult = this.getUIContext().createAnimator(options)
this.animatorResult.onFrame = (progress: number) => {
  this.translateX = progress  // ✅ 0→200→0→200 无限来回
}
this.animatorResult.play()
// iterations=-1 无限播放 + alternate 反向交替:0→200→0→200 无限来回

鸿蒙 iterations + direction API 真名坑AnimatorOptions.iterations: number-1 无限播放,0 不播放,正数 NN 次);AnimatorOptions.direction: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse'normal 正向,reverse 反向,alternate 奇正偶反交替,alternate-reverse 奇反偶正交替);鸿蒙坑:React CSS animation-iteration-count: infinite 是字符串 infinite,鸿蒙 iterations: -1 是数字 -1;React CSS animation-direction: alternate 跟鸿蒙 direction: 'alternate' 语义一致但鸿蒙是字符串字面量不是 CSS 关键字。

场景 3:pause()/resume() 暂停恢复 + cancel() 取消触发 onCancel

暂停恢复用 pause()/resume(),取消用 cancel() 触发 onCancel

// ✅ 场景 3:pause()/resume() 暂停恢复 + cancel() 取消触发 onCancel(API 6)
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

this.animatorResult = this.getUIContext().createAnimator({ duration: 5000, iterations: -1, begin: 0, end: 300 })
this.animatorResult.onFrame = (progress: number) => { this.width = progress }
this.animatorResult.onCancel = () => {  // ✅ 驼峰 onCancel(cancel() 触发)
  console.info('动画被取消')
}
this.animatorResult.play()

// ✅ pause() 暂停(onFrame 停止触发,progress 停在当前值)
this.animatorResult.pause()
// ✅ resume() 恢复(从暂停处继续,onFrame 恢复触发)
this.animatorResult.resume()
// ✅ cancel() 取消(触发 onCancel,动画终止,progress 不再变化)
this.animatorResult.cancel()
// pause/resume 暂停恢复 + cancel 取消触发 onCancel 驼峰回调

鸿蒙 pause/resume/cancel API 真名坑AnimatorResult.pause(): void(暂停,onFrame 停止触发,progress 停在当前值);AnimatorResult.resume(): void(恢复,从暂停处继续);AnimatorResult.cancel(): void(取消,触发 onCancel 回调,动画终止);鸿蒙坑:React cancelAnimationFrame 取消后无法恢复(要重新 requestAnimationFrame),鸿蒙 pause()/resume() 可暂停恢复不丢进度——鸿蒙 AnimatorResult 是有状态的对象,React requestAnimationFrame 是无状态的浏览器 API。

场景 4:reverse() 运行时反向播放 + fill=‘forwards’ 保持终态

运行时反向用 reverse(),保持终态用 fill: 'forwards'

// ✅ 场景 4:reverse() 运行时反向播放 + fill='forwards' 保持终态(API 6)
import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'

const options: AnimatorOptions = {
  duration: 3000, easing: 'ease', delay: 0,
  fill: 'forwards',  // ✅ forwards 动画完成后保持终态(progress 停在 end 不归零)
  direction: 'normal', iterations: 1, begin: 0, end: 300
}
this.animatorResult = this.getUIContext().createAnimator(options)
this.animatorResult.onFrame = (progress: number) => { this.width = progress }
this.animatorResult.play()  // ✅ 正向播放 0→300,完成后保持 300(fill: 'forwards')

// ✅ reverse() 运行时反向播放(不是 direction:'reverse',是运行时方法)
this.animatorResult.reverse()  // ✅ 反向播放 300→0
// reverse() 运行时反向 + fill='forwards' 保持终态:progress 停在 end 不归零

鸿蒙 reverse + fill API 真名坑AnimatorResult.reverse(): void(运行时反向播放,不是 AnimatorOptions.direction: 'reverse' 那个配置项——direction 是播放前配置,reverse() 是播放中运行时调用);AnimatorOptions.fill: 'none' | 'forwards' | 'backwards' | 'both'none 归零,forwards 保持终态,backwards 保持起始态,both 两端都保持);鸿蒙坑:React CSS animation-fill-mode: forwards 跟鸿蒙 fill: 'forwards' 语义一致但鸿蒙是字符串字面量;reverse() 是运行时方法不是配置项,跟 pause()/resume()/cancel() 同级控制方法。

五、一句话哲学

写鸿蒙 ArkUI 记住:animator 不是 React requestAnimationFrame 是「AnimatorResult 帧回调 + 持引用」——鸿蒙 6.1 API 23 @kit.ArkUIAnimator as animator namespace(API 6+,鸿蒙 6.1 API 23 基座,AnimatorOptions/AnimatorResult/SimpleAnimatorOptions 类型 + 废弃 animator.create()/createAnimator() 顶层函数,SysCap SystemCapability.ArkUI.ArkUI.Full,@crossplatform @atomicservice)。根因不是浏览器 API 是 ArkUI 命名空间对象——import 真路径是 @kit.ArkUI 不是 @ohos.animator(✅ import { Animator as animator, AnimatorOptions, AnimatorResult } from '@kit.ArkUI'——Animator namespace 必须 as animator alias,❌ import animator from '@ohos.animator' 旧文档路径编译错 Cannot find module,❌ import { animator } 命名错 has no exported member 'animator'),API 12 废弃全小写回调名迁移到驼峰(✅ onFrame/onFinish/onCancel/onRepeat 驼峰 API 12+,❌ onframe/onfinish/oncancel/onrepeat 全小写废弃 deprecated 有 IDE 警告),animator.create()/createAnimator() 废弃迁移到 UI 上下文方法(✅ this.getUIContext().createAnimator(options)UIContext,❌ animator.create(options) 废弃顶层函数无 UI 上下文绑定),AnimatorResult 必须持有引用避免析构(✅ private animatorResult: AnimatorResult | null 持引用,❌ 局部变量方法结束析构动画中断),aboutToDisappearcancel() 释放避免循环依赖内存泄漏(✅ this.animatorResult?.cancel(); this.animatorResult = null,❌ 不 cancel 组件销毁后 AnimatorResult 仍持引用内存泄漏),onFrame 回调的 progress 自动从 begin 插到 end(不用自己算 timestamp,React requestAnimationFrame 回调传 timestamp 要自己算插值),iterations 语义是数字不是字符串(✅ -1 无限播放 / 0 不播放 / 正数 NN 次,❌ React CSS animation-iteration-count: infinite 是字符串),direction: 'alternate' 反向交替(配合 iterations: -1 做无限来回),运行时控制 play()/pause()/resume()/cancel()/reverse()pause/resume 可暂停恢复不丢进度,cancel 触发 onCancelreverse 是运行时方法不是配置项),fill: 'forwards' 保持终态(progress 停在 end 不归零)。import @kit.ArkUI + onFrame 驼峰 + getUIContext().createAnimator + 持引用 + aboutToDisappear cancel 是鸿蒙 6.1 @ohos.animator 动画器坑核心!

能力系列回链

  • 鸿蒙 7.0 新特性篇 1~17(沉浸式毛玻璃/Component3D/智能体框架/方舟引擎/星盾安全/星河互联/空间音频/可变字体/游戏快启/分布式数据盾/LTPO 可变帧率/AI 文档识别/多形态服务窗口/AI 反诈/机密计算/空间计算/小艺全面进化)
  • 鸿蒙 6.1 API 23 开发坑系列篇 1「ArkUI.modifier 装饰器坑」——attributeModifier + AttributeModifier 状态化节点修改器
  • 鸿蒙 6.1 API 23 开发坑系列篇 2「arkui.componentSnapshot 组件截图坑」——get/getSync/createFromBuilder 返回 image.PixelMap 像素图
  • 鸿蒙 6.1 API 23 开发坑系列篇 3「arkui.node 节点坑」——NodeController abstract class makeNode override + BuilderNode WrappedBuilder
  • 鸿蒙 6.1 API 23 开发坑系列篇 4「arkui.UIContext UI 上下文坑」——runScopedTask 不是 runScopedOnUiThread + 11 个子管理器
  • 鸿蒙 6.1 API 23 开发坑系列篇 5「arkui.observer UI 观察器坑」——uiObserver namespace 真名不是 observer + on type string literal
  • 鸿蒙 6.1 API 23 开发坑系列篇 6「@ohos.animator 动画器坑」——import @kit.ArkUI 不是 @ohos.animator + onFrame 驼峰不是废弃 onframe + getUIContext().createAnimator 不是废弃 animator.create + 持引用 + aboutToDisappear cancel(本文)
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐