• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# \@AnimatableExtend装饰器:定义可动画属性
2
3@AnimatableExtend装饰器用于自定义可动画的属性方法,在这个属性方法中修改组件不可动画的属性。在动画执行过程时,通过逐帧回调函数修改不可动画属性值,让不可动画属性也能实现动画效果。
4
5- 可动画属性:如果一个属性方法在animation属性前调用,改变这个属性的值可以生效animation属性的动画效果,这个属性称为可动画属性。比如height、width、backgroundColor、translate属性,Text组件的fontSize属性等。
6
7- 不可动画属性:如果一个属性方法在animation属性前调用,改变这个属性的值不能生效animation属性的动画效果,这个属性称为不可动画属性。比如Polyline组件的points属性等。
8
9>  **说明:**
10>
11>  该装饰器从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
12
13## 装饰器使用说明
14
15
16### 语法
17
18
19```ts
20@AnimatableExtend(UIComponentName) function functionName(value: typeName) {
21  .propertyName(value)
22}
23```
24
25- \@AnimatableExtend仅支持定义在全局,不支持在组件内部定义。
26- \@AnimatableExtend定义的函数参数类型必须为number类型或者实现 AnimtableArithmetic\<T\>接口的自定义类型。
27- \@AnimatableExtend定义的函数体内只能调用\@AnimatableExtend括号内组件的属性方法。
28
29### AnimtableArithmetic\<T\>接口说明
30对复杂数据类型做动画,需要实现AnimtableArithmetic\<T\>接口中加法、减法、乘法和判断相等函数。
31| 名称 | 入参类型 | 返回值类型 | 说明
32| -------- | -------- |-------- |-------- |
33| plus | AnimtableArithmetic\<T\> | AnimtableArithmetic\<T\> | 加法函数 |
34| subtract | AnimtableArithmetic\<T\> | AnimtableArithmetic\<T\> | 减法函数 |
35| multiply | number | AnimtableArithmetic\<T\> | 乘法函数 |
36| equals | AnimtableArithmetic\<T\> | boolean | 相等判断函数 |
37
38## 使用场景
39
40以下示例实现字体大小的动画效果。
41
42
43```ts
44@AnimatableExtend(Text) function animatableFontSize(size: number) {
45  .fontSize(size)
46}
47
48@Entry
49@Component
50struct AnimatablePropertyExample {
51  @State fontSize: number = 20
52  build() {
53    Column() {
54      Text("AnimatableProperty")
55        .animatableFontSize(this.fontSize)
56        .animation({duration: 1000, curve: "ease"})
57      Button("Play")
58        .onClick(() => {
59          this.fontSize = this.fontSize == 20 ? 36 : 20
60        })
61    }.width("100%")
62    .padding(10)
63  }
64}
65```
66![image](figures/animatable-font-size.gif)
67
68
69以下示例实现折线的动画效果。
70
71
72```ts
73class Point {
74  x: number
75  y: number
76
77  constructor(x: number, y: number) {
78    this.x = x
79    this.y = y
80  }
81  plus(rhs: Point): Point {
82    return new Point(this.x + rhs.x, this.y + rhs.y)
83  }
84  subtract(rhs: Point): Point {
85    return new Point(this.x - rhs.x, this.y - rhs.y)
86  }
87  multiply(scale: number): Point {
88    return new Point(this.x * scale, this.y * scale)
89  }
90  equals(rhs: Point): boolean {
91    return this.x === rhs.x && this.y === rhs.y
92  }
93}
94
95class PointVector extends Array<Point> implements AnimatableArithmetic<PointVector> {
96  constructor(value: Array<Point>) {
97    super();
98    value.forEach(p => this.push(p))
99  }
100  plus(rhs: PointVector): PointVector {
101    let result = new PointVector([])
102    const len = Math.min(this.length, rhs.length)
103    for (let i = 0; i < len; i++) {
104      result.push((this as Array<Point>)[i].plus((rhs as Array<Point>)[i]))
105    }
106    return result
107  }
108  subtract(rhs: PointVector): PointVector {
109    let result = new PointVector([])
110    const len = Math.min(this.length, rhs.length)
111    for (let i = 0; i < len; i++) {
112      result.push((this as Array<Point>)[i].subtract((rhs as Array<Point>)[i]))
113    }
114    return result
115  }
116  multiply(scale: number): PointVector {
117    let result = new PointVector([])
118    for (let i = 0; i < this.length; i++) {
119      result.push((this as Array<Point>)[i].multiply(scale))
120    }
121    return result
122  }
123  equals(rhs: PointVector): boolean {
124    if (this.length != rhs.length) {
125      return false
126    }
127    for (let i = 0; i < this.length; i++) {
128      if (!(this as Array<Point>)[i].equals((rhs as Array<Point>)[i])) {
129        return false
130      }
131    }
132    return true
133  }
134  get(): Array<Object[]> {
135    let result: Array<Object[]> = []
136    this.forEach(p => result.push([p.x, p.y]))
137    return result
138  }
139}
140
141@AnimatableExtend(Polyline) function animatablePoints(points: PointVector) {
142  .points(points.get())
143}
144
145@Entry
146@Component
147struct AnimatablePropertyExample {
148  @State points: PointVector = new PointVector([
149    new Point(50, Math.random() * 200),
150    new Point(100, Math.random() * 200),
151    new Point(150, Math.random() * 200),
152    new Point(200, Math.random() * 200),
153    new Point(250, Math.random() * 200),
154  ])
155  build() {
156    Column() {
157      Polyline()
158        .animatablePoints(this.points)
159        .animation({duration: 1000, curve: "ease"})
160        .size({height:220, width:300})
161        .fill(Color.Green)
162        .stroke(Color.Red)
163        .backgroundColor('#eeaacc')
164      Button("Play")
165        .onClick(() => {
166          this.points = new PointVector([
167            new Point(50, Math.random() * 200),
168            new Point(100, Math.random() * 200),
169            new Point(150, Math.random() * 200),
170            new Point(200, Math.random() * 200),
171            new Point(250, Math.random() * 200),
172          ])
173        })
174    }.width("100%")
175    .padding(10)
176  }
177}
178```
179![image](figures/animatable-points.gif)