文档管理中心

@AnimatableExtend装饰器:定义可动画属性

@AnimatableExtend装饰器用于自定义可动画的属性方法,在这个属性方法中修改组件不可动画的属性。在动画执行过程中,通过逐帧回调函数修改不可动画属性值,让不可动画属性也能实现动画效果。也可通过逐帧回调函数修改可动画属性的值,实现逐帧布局的效果。

  • 可动画属性:如果一个属性方法在animation属性前调用,改变这个属性的值可以使animation属性的动画效果生效,这个属性称为可动画属性。比如heightwidthbackgroundColortranslate属性,和Text组件的fontSize属性等。

  • 不可动画属性:如果一个属性方法在animation属性前调用,改变这个属性的值不能使animation属性的动画效果生效,这个属性称为不可动画属性。比如Polyline组件的points属性等。

说明

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

从API version 11开始,该装饰器支持在元服务中使用。

装饰器使用说明

语法

收起
自动换行
深色代码主题
复制
  1. @AnimatableExtend(UIComponentName) function functionName(value: typeName) {
  2. .propertyName(value)
  3. }
  • @AnimatableExtend仅支持定义在全局,不支持在组件内部定义。
  • @AnimatableExtend定义的函数参数类型必须为number类型或者实现 AnimatableArithmetic<T>接口的自定义类型。
  • @AnimatableExtend定义的函数体内只能调用@AnimatableExtend括号内组件的属性方法。

AnimatableArithmetic<T>接口说明

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

展开
名称 入参类型 返回值类型 说明
plus AnimatableArithmetic<T> AnimatableArithmetic<T> 定义该数据类型的加法运算规则
subtract AnimatableArithmetic<T> AnimatableArithmetic<T> 定义该数据类型的减法运算规则
multiply number AnimatableArithmetic<T> 定义该数据类型的乘法运算规则
equals AnimatableArithmetic<T> boolean 定义该数据类型的相等判断规则

使用场景

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

收起
自动换行
深色代码主题
复制
  1. @AnimatableExtend(Text)
  2. function animatableWidth(width: number) {
  3. // 在逐帧回调中将width写入Text的width属性
  4. .width(width)
  5. }
  6. @Entry
  7. @Component
  8. struct AnimatablePropertyText {
  9. @State textWidth: number = 80;
  10. build() {
  11. Column() {
  12. Text('AnimatableProperty')
  13. .animatableWidth(this.textWidth)
  14. .animation({ duration: 2000, curve: Curve.Ease })
  15. // 点击按钮切换textWidth,触发Text逐帧更新宽度并产生动画效果
  16. Button('Play')
  17. .onClick(() => {
  18. this.textWidth = this.textWidth == 80 ? 160 : 80;
  19. })
  20. }.width('100%')
  21. .padding(10)
  22. }
  23. }

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

收起
自动换行
深色代码主题
复制
  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(p => this.push(p));
  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(p => result.push([p.x, p.y]));
  64. return result;
  65. }
  66. }
  67. @AnimatableExtend(Polyline)
  68. function animatablePoints(points: PointVector) {
  69. .points(points.get())
  70. }
  71. @Entry
  72. @Component
  73. struct AnimatablePropertyExample {
  74. @State points: PointVector = new PointVector([
  75. new Point(50, Math.random() * 200),
  76. new Point(100, Math.random() * 200),
  77. new Point(150, Math.random() * 200),
  78. new Point(200, Math.random() * 200),
  79. new Point(250, Math.random() * 200),
  80. ])
  81. build() {
  82. Column() {
  83. Polyline()
  84. .animatablePoints(this.points)
  85. .animation({ duration: 1000, curve: Curve.Ease })// 设置动画参数
  86. .size({ height: 220, width: 300 })
  87. .fill(Color.Green)
  88. .stroke(Color.Red)
  89. .backgroundColor('#eeaacc')
  90. Button('Play')
  91. .onClick(() => {
  92. // points是实现了可动画协议的数据类型,points在动画过程中可按照定义的运算规则、动画参数从之前的PointVector变为新的PointVector数据,产生每一帧的PointVector数据,进而产生动画
  93. this.points = new PointVector([
  94. new Point(50, Math.random() * 200),
  95. new Point(100, Math.random() * 200),
  96. new Point(150, Math.random() * 200),
  97. new Point(200, Math.random() * 200),
  98. new Point(250, Math.random() * 200),
  99. ]);
  100. })
  101. }.width('100%')
  102. .padding(10)
  103. }
  104. }

在 指南 中进行搜索
请输入您想要搜索的关键词