@AnimatableExtend裝飾器用于自定義可動(dòng)畫的屬性方法,在這個(gè)屬性方法中修改組件不可動(dòng)畫的屬性。在動(dòng)畫執(zhí)行過程時(shí),通過逐幀回調(diào)函數(shù)修改不可動(dòng)畫屬性值,讓不可動(dòng)畫屬性也能實(shí)現(xiàn)動(dòng)畫效果。
可動(dòng)畫屬性:如果一個(gè)屬性方法在animation屬性前調(diào)用,改變這個(gè)屬性的值可以生效animation屬性的動(dòng)畫效果,這個(gè)屬性稱為可動(dòng)畫屬性。比如height、width、backgroundColor、translate屬性,Text組件的fontSize屬性等。
不可動(dòng)畫屬性:如果一個(gè)屬性方法在animation屬性前調(diào)用,改變這個(gè)屬性的值不能生效animation屬性的動(dòng)畫效果,這個(gè)屬性稱為不可動(dòng)畫屬性。比如Polyline組件的points屬性等。
說明:
該裝飾器從API Version 10開始支持。后續(xù)版本如有新增內(nèi)容,則采用上角標(biāo)單獨(dú)標(biāo)記該內(nèi)容的起始版本。
裝飾器使用說明
語法
@AnimatableExtend(UIComponentName) function functionName(value: typeName) {
.propertyName(value)
}
- @AnimatableExtend僅支持定義在全局,不支持在組件內(nèi)部定義。
- @AnimatableExtend定義的函數(shù)參數(shù)類型必須為number類型或者實(shí)現(xiàn) AnimtableArithmetic<T>接口的自定義類型。
- @AnimatableExtend定義的函數(shù)體內(nèi)只能調(diào)用@AnimatableExtend括號(hào)內(nèi)組件的屬性方法。
AnimtableArithmetic<T>接口說明
對(duì)復(fù)雜數(shù)據(jù)類型做動(dòng)畫,需要實(shí)現(xiàn)AnimtableArithmetic<T>接口中加法、減法、乘法和判斷相等函數(shù)。
| 名稱 | 入?yún)㈩愋?/th> | 返回值類型 | 說明 |
|---|---|---|---|
| plus | AnimtableArithmetic<T> | AnimtableArithmetic<T> | 加法函數(shù) |
| subtract | AnimtableArithmetic<T> | AnimtableArithmetic<T> | 減法函數(shù) |
| multiply | number | AnimtableArithmetic<T> | 乘法函數(shù) |
| equals | AnimtableArithmetic<T> | boolean | 相等判斷函數(shù) |
使用場(chǎng)景
以下示例實(shí)現(xiàn)字體大小的動(dòng)畫效果。
@AnimatableExtend(Text) function animatableFontSize(size: number) {
.fontSize(size)
}
@Entry
@Component
struct AnimatablePropertyExample {
@State fontSize: number = 20
build() {
Column() {
Text("AnimatableProperty")
.animatableFontSize(this.fontSize)
.animation({duration: 1000, curve: "ease"})
Button("Play")
.onClick(() => {
this.fontSize = this.fontSize == 20 ? 36 : 20
})
}.width("100%")
.padding(10)
}
}

以下示例實(shí)現(xiàn)折線的動(dòng)畫效果。
class Point {
x: number
y: number
constructor(x: number, y: number) {
this.x = x
this.y = y
}
plus(rhs: Point): Point {
return new Point(this.x + rhs.x, this.y + rhs.y)
}
subtract(rhs: Point): Point {
return new Point(this.x - rhs.x, this.y - rhs.y)
}
multiply(scale: number): Point {
return new Point(this.x * scale, this.y * scale)
}
equals(rhs: Point): boolean {
return this.x === rhs.x && this.y === rhs.y
}
}
class PointVector extends Array<Point> implements AnimatableArithmetic<PointVector> {
constructor(value: Array<Point>) {
super();
value.forEach(p => this.push(p))
}
plus(rhs: PointVector): PointVector {
let result = new PointVector([])
const len = Math.min(this.length, rhs.length)
for (let i = 0; i < len; i++) {
result.push((this as Array<Point>)[i].plus((rhs as Array<Point>)[i]))
}
return result
}
subtract(rhs: PointVector): PointVector {
let result = new PointVector([])
const len = Math.min(this.length, rhs.length)
for (let i = 0; i < len; i++) {
result.push((this as Array<Point>)[i].subtract((rhs as Array<Point>)[i]))
}
return result
}
multiply(scale: number): PointVector {
let result = new PointVector([])
for (let i = 0; i < this.length; i++) {
result.push((this as Array<Point>)[i].multiply(scale))
}
return result
}
equals(rhs: PointVector): boolean {
if (this.length != rhs.length) {
return false
}
for (let i = 0; i < this.length; i++) {
if (!(this as Array<Point>)[i].equals((rhs as Array<Point>)[i])) {
return false
}
}
return true
}
get(): Array<Object[]> {
let result: Array<Object[]> = []
this.forEach(p => result.push([p.x, p.y]))
return result
}
}
@AnimatableExtend(Polyline) function animatablePoints(points: PointVector) {
.points(points.get())
}
@Entry
@Component
struct AnimatablePropertyExample {
@State points: PointVector = new PointVector([
new Point(50, Math.random() * 200),
new Point(100, Math.random() * 200),
new Point(150, Math.random() * 200),
new Point(200, Math.random() * 200),
new Point(250, Math.random() * 200),
])
build() {
Column() {
Polyline()
.animatablePoints(this.points)
.animation({duration: 1000, curve: "ease"})
.size({height:220, width:300})
.fill(Color.Green)
.stroke(Color.Red)
.backgroundColor('#eeaacc')
Button("Play")
.onClick(() => {
this.points = new PointVector([
new Point(50, Math.random() * 200),
new Point(100, Math.random() * 200),
new Point(150, Math.random() * 200),
new Point(200, Math.random() * 200),
new Point(250, Math.random() * 200),
])
})
}.width("100%")
.padding(10)
}
}

寫在最后
- 如果你覺得這篇內(nèi)容對(duì)你還蠻有幫助,我想邀請(qǐng)你幫我三個(gè)小忙:
- 點(diǎn)贊,轉(zhuǎn)發(fā),有你們的 『點(diǎn)贊和評(píng)論』,才是我創(chuàng)造的動(dòng)力。
- 關(guān)注小編,同時(shí)可以期待后續(xù)文章ing??,不定期分享原創(chuàng)知識(shí)。
- 想要獲取更多完整鴻蒙最新學(xué)習(xí)知識(shí)點(diǎn),請(qǐng)移步前往小編:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu
