文档管理中心
我的

您当前正在浏览HarmonyOS最新文档,覆盖已发布的所有API版本,可在API参考中筛选您使用的API版本。详细的版本配套关系请参考版本说明。

指南与API参考API参考应用框架ArkUI(方舟UI框架)ArkTS组件自定义组件组件扩展装饰器@AnimatableExtend:定义可动画属性

@AnimatableExtend:定义可动画属性

Phone12+PC/2in113+Tablet12+TV19+Wearable18+

@AnimatableExtend装饰器用于自定义可动画的属性方法,该装饰器内定义的函数需要配合animation属性使用,且必须在animation属性前调用,改变该属性值时才能使animation属性的动画效果生效。在动画过程中该函数会被逐帧调用,直到动画结束。该装饰器的常见用途有:

  1. 使不可动画属性变为可动画属性,自定义数据运算规则使得属性能进行插值运算(即在动画起始值与终止值之间,按一定规则计算每一帧的中间值),再由动画驱动属性从起点值逐渐过渡到终点值。

  2. 使属性逐帧变化,实现逐帧布局的效果。

  • 可动画属性:属性方法在animation属性前调用时,改变该属性的值可使animation属性的动画效果生效,产生动画过渡效果。例如height、width、backgroundColor、translate属性,以及Text组件的fontSize属性等。

  • 不可动画属性:属性方法在animation属性前调用时,改变该属性的值不能使animation属性的动画效果生效,属性突变无动画过渡效果。例如Polyline组件的points属性等。

说明
  • 该装饰器从API version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。

  • 本模块接口仅可在Stage模型下使用。

  • 使用@AnimatableExtend装饰的属性方法时,该方法需在同一组件的animation属性之前调用,动画过渡效果才能生效。

语法

收起
自动换行
深色代码主题
复制
  1. @AnimatableExtend(UIComponentName) function functionName(value: typeName) {
  2. .propertyName(value)
  3. }
  • @AnimatableExtend仅支持定义在全局,不支持在组件内部定义。
  • @AnimatableExtend定义的函数参数类型必须为number类型或者实现 AnimatableArithmetic<T>接口的自定义类型。
  • @AnimatableExtend定义的函数体内只能调用@AnimatableExtend括号内组件的属性方法。
  • @AnimatableExtend定义的函数必须在animation属性之前调用,才能使动画效果生效。若在animation属性之后调用或未配合animation属性使用,属性值变化时不会有动画过渡效果,而是直接突变到目标值。

AnimatableArithmetic<T>

Phone12+PC/2in113+Tablet12+TV19+Wearable18+

该接口定义非number数据类型的动画运算规则。对非number类型的数据(如数组、结构体、颜色等)做动画,需要实现AnimatableArithmetic<T>接口中加法、减法、乘法和判断相等函数,使得该数据能参与动画的插值运算和识别该数据是否发生改变。即定义它们为实现了AnimatableArithmetic<T>接口的类型。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

plus

Phone12+PC/2in113+Tablet12+TV19+Wearable18+

plus(rhs: AnimatableArithmetic<T>): AnimatableArithmetic<T>

定义该数据类型的加法运算规则。需与AnimatableArithmetic<T>接口的其他方法一同实现,才能使自定义数据类型参与动画的插值运算。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

展开
参数名 类型 必填 说明
rhs AnimatableArithmetic<T> 是 与自身进行加法运算的另一个数据对象,应与当前对象为相同的具体类型实例。

返回值:

展开
类型 说明
AnimatableArithmetic<T> 加法运算的结果,用于动画插值过程中计算两个数据之间的中间值。

subtract

Phone12+PC/2in113+Tablet12+TV19+Wearable18+

subtract(rhs: AnimatableArithmetic<T>): AnimatableArithmetic<T>

定义该数据类型的减法运算规则,在动画插值运算中用于计算起始值与目标值之间的差值,差值将作为乘法运算的输入。需与AnimatableArithmetic<T>接口的其他方法一同实现,才能使自定义数据类型参与动画的插值运算。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

展开
参数名 类型 必填 说明
rhs AnimatableArithmetic<T> 是 与自身进行减法运算的另一个数据对象,应与当前对象为相同的具体类型实例。

返回值:

展开
类型 说明
AnimatableArithmetic<T> 减法运算的结果,用于动画插值过程中计算数据差值以得到中间帧数据。

multiply

Phone12+PC/2in113+Tablet12+TV19+Wearable18+

multiply(scale: number): AnimatableArithmetic<T>

定义该数据类型的乘法运算规则,在动画插值运算中用于按动画进度比例(0到1之间)对差值进行缩放,缩放后的差值将通过plus运算加到起始值上。需与AnimatableArithmetic<T>接口的其他方法一同实现,才能使自定义数据类型参与动画的插值运算。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

展开
参数名 类型 必填 说明
scale number 是 乘法运算的系数,取值范围为[0, +∞),动画插值时典型取值范围为[0, 1]。

返回值:

展开
类型 说明
AnimatableArithmetic<T> 乘法运算的结果,用于动画插值过程中按系数缩放数据以计算中间帧数据。

equals

Phone12+PC/2in113+Tablet12+TV19+Wearable18+

equals(rhs: AnimatableArithmetic<T>): boolean

定义该数据类型的相等判断规则,在动画过程中用于识别数据是否发生改变,若当前值与目标值相等则不再触发动画过渡。需与AnimatableArithmetic<T>接口的其他方法一同实现,才能使自定义数据类型参与动画的插值运算。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

展开
参数名 类型 必填 说明
rhs AnimatableArithmetic<T> 是 与当前对象判断是否相等的另一个数据对象。

返回值:

展开
类型 说明
boolean 是否相等。返回true表示相等,返回false表示不相等。

示例

示例1(逐帧布局的效果)

以下示例通过改变Text组件宽度实现逐帧布局的效果。

收起
自动换行
深色代码主题
复制
  1. @AnimatableExtend(Text)
  2. function animatableWidth(width: number) {
  3. .width(width)
  4. }
  5. @Entry
  6. @Component
  7. struct AnimatablePropertyExample {
  8. @State textWidth: number = 80;
  9. build() {
  10. Column() {
  11. Text("AnimatableProperty")
  12. .animatableWidth(this.textWidth)
  13. .animation({ duration: 2000, curve: Curve.Ease })
  14. Button("Play")
  15. .onClick(() => {
  16. this.textWidth = this.textWidth === 80 ? 160 : 80;
  17. })
  18. }.width("100%")
  19. .padding(10)
  20. }
  21. }

示例2(折线的动画效果)

以下示例实现折线的动画效果。

收起
自动换行
深色代码主题
复制
  1. class Point {
  2. x: number
  3. y: number
  4. constructor(x: number, y: number) {
  5. this.x = x;
  6. this.y = y;
  7. }
  8. plus(rhs: Point): Point {
  9. return new Point(this.x + rhs.x, this.y + rhs.y);
  10. }
  11. subtract(rhs: Point): Point {
  12. return new Point(this.x - rhs.x, this.y - rhs.y);
  13. }
  14. multiply(scale: number): Point {
  15. return new Point(this.x * scale, this.y * scale);
  16. }
  17. equals(rhs: Point): boolean {
  18. return this.x === rhs.x && this.y === rhs.y;
  19. }
  20. }
  21. // PointVector实现了AnimatableArithmetic<T>接口
  22. class PointVector extends Array<Point> implements AnimatableArithmetic<PointVector> {
  23. constructor(value: Array<Point>) {
  24. super();
  25. value.forEach(point => this.push(point));
  26. }
  27. plus(rhs: PointVector): PointVector {
  28. let result = new PointVector([]);
  29. const len = Math.min(this.length, rhs.length);
  30. for (let i = 0; i < len; i++) {
  31. result.push((this as Array<Point>)[i].plus((rhs as Array<Point>)[i]));
  32. }
  33. return result;
  34. }
  35. subtract(rhs: PointVector): PointVector {
  36. let result = new PointVector([]);
  37. const len = Math.min(this.length, rhs.length);
  38. for (let i = 0; i < len; i++) {
  39. result.push((this as Array<Point>)[i].subtract((rhs as Array<Point>)[i]));
  40. }
  41. return result;
  42. }
  43. multiply(scale: number): PointVector {
  44. let result = new PointVector([]);
  45. for (let i = 0; i < this.length; i++) {
  46. result.push((this as Array<Point>)[i].multiply(scale));
  47. }
  48. return result;
  49. }
  50. equals(rhs: PointVector): boolean {
  51. if (this.length !== rhs.length) {
  52. return false;
  53. }
  54. for (let i = 0; i < this.length; i++) {
  55. if (!(this as Array<Point>)[i].equals((rhs as Array<Point>)[i])) {
  56. return false;
  57. }
  58. }
  59. return true;
  60. }
  61. get(): Array<Object[]> {
  62. let result: Array<Object[]> = [];
  63. this.forEach(point => result.push([point.x, point.y]));
  64. return result;
  65. }
  66. }
  67. @AnimatableExtend(Polyline)
  68. function animatablePoints(points: PointVector) {
  69. // 将PointVector转换为Polyline的points属性所需的数组格式
  70. .points(points.get())
  71. }
  72. @Entry
  73. @Component
  74. struct AnimatablePropertyExample {
  75. @State points: PointVector = new PointVector([
  76. new Point(50, Math.random() * 200),
  77. new Point(100, Math.random() * 200),
  78. new Point(150, Math.random() * 200),
  79. new Point(200, Math.random() * 200),
  80. new Point(250, Math.random() * 200),
  81. ])
  82. build() {
  83. Column() {
  84. Polyline()
  85. .animatablePoints(this.points)
  86. .animation({ duration: 1000, curve: Curve.Ease }) // 设置动画参数
  87. .size({ height: 220, width: 300 })
  88. .fill(Color.Green)
  89. .stroke(Color.Red)
  90. .backgroundColor('#eeaacc')
  91. Button("Play")
  92. .onClick(() => {
  93. // points是实现了可动画协议的数据类型,points在动画过程中可按照定义的运算规则、动画参数从之前的PointVector变为新的PointVector数据,产生每一帧的PointVector数据,进而产生动画
  94. this.points = new PointVector([
  95. new Point(50, Math.random() * 200),
  96. new Point(100, Math.random() * 200),
  97. new Point(150, Math.random() * 200),
  98. new Point(200, Math.random() * 200),
  99. new Point(250, Math.random() * 200),
  100. ]);
  101. })
  102. }.width("100%")
  103. .padding(10)
  104. }
  105. }