HarmonyOS:@AnimatableExtend 裝飾器自學(xué)指南

在最近的項目開發(fā)中,我遇到了需要實現(xiàn)復(fù)雜動畫效果的需求。在探索解決方案的過程中,我發(fā)現(xiàn)了 @AnimatableExtend 裝飾器,它為實現(xiàn)動畫效果提供了一種非常靈活且強大的方式。然而,在學(xué)習(xí)這個裝飾器的過程中,我發(fā)現(xiàn)相關(guān)的資料并不是特別豐富,而且很多資料都缺乏系統(tǒng)性的講解。因此,我決定寫這篇博客,將自己的學(xué)習(xí)經(jīng)驗和理解分享出來,希望能幫助更多的開發(fā)者快速掌握 @AnimatableExtend 裝飾器的使用。

1. @AnimatableExtend 裝飾器概述

@AnimatableExtend 裝飾器從 API Version 10 開始支持,為動畫效果的實現(xiàn)提供了一種便捷的方式。從 API version 11 開始,它支持在元服務(wù)中使用。這個裝飾器允許我們自定義動畫屬性,使得我們可以對不同類型的數(shù)據(jù)進行動畫處理。

1.1 裝飾器使用規(guī)則

  • 定義位置@AnimatableExtend 僅支持定義在全局,不支持在組件內(nèi)部定義。
  • 參數(shù)類型@AnimatableExtend 定義的函數(shù)參數(shù)類型必須為 number 類型或者實現(xiàn) AnimatableArithmetic<T> 接口的自定義類型。
  • 函數(shù)體限制@AnimatableExtend 定義的函數(shù)體內(nèi)只能調(diào)用 @AnimatableExtend 括號內(nèi)組件的屬性方法。

1.2 AnimatableArithmetic<T> 接口說明

AnimatableArithmetic<T> 接口定義了非 number 數(shù)據(jù)類型的動畫運算規(guī)則。對于非 number 類型的數(shù)據(jù)(如數(shù)組、結(jié)構(gòu)體、顏色等)做動畫,需要實現(xiàn)該接口中的加法、減法、乘法和判斷相等函數(shù),使得該數(shù)據(jù)能參與動畫的插值運算和識別該數(shù)據(jù)是否發(fā)生改變。

名稱 入?yún)㈩愋?/th> 返回值類型 說明
plus AnimatableArithmetic<T> AnimatableArithmetic<T> 定義該數(shù)據(jù)類型的加法運算規(guī)則
subtract AnimatableArithmetic<T> AnimatableArithmetic<T> 定義該數(shù)據(jù)類型的減法運算規(guī)則
multiply number AnimatableArithmetic<T> 定義該數(shù)據(jù)類型的乘法運算規(guī)則
equals AnimatableArithmetic<T> boolean 定義該數(shù)據(jù)類型的相等判斷規(guī)則

2. 使用場景示例

2.1 改變 Text 組件寬度實現(xiàn)逐幀布局效果

下面的示例通過改變 Text 組件的寬度實現(xiàn)逐幀布局的效果。

@AnimatableExtend(Text)
function animatableWidth(width: number) {
  .width(width)
}

@Entry
@Component
struct AnimatablePropertyExample {
  @State textWidth: number = 100;

  build() {
    Column() {
      Text("AnimatableProperty")
        .animatableWidth(this.textWidth)
        .animation({ duration: 3000, curve: Curve.EaseInOut })
      Button("Play")
        .onClick(() => {
          this.textWidth = this.textWidth == 100 ? 200 : 100;
        })
    }.width("100%")
    .padding(20)
  }
}

在這個示例中,我們定義了一個 animatableWidth 函數(shù),通過 @AnimatableExtend 裝飾器將其應(yīng)用到 Text 組件上。點擊按鈕時,textWidth 的值會在 100 和 200 之間切換,從而觸發(fā)動畫效果。

2.2 實現(xiàn)折線的動畫效果

為了實現(xiàn)折線的動畫效果,我們需要定義一個自定義類型 PointPointVector,并讓 PointVector 實現(xiàn) AnimatableArithmetic<T> 接口。

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
  }
}

// PointVector實現(xiàn)了AnimatableArithmetic<T>接口
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(30, Math.random() * 250),
    new Point(80, Math.random() * 250),
    new Point(130, Math.random() * 250),
    new Point(180, Math.random() * 250),
    new Point(230, Math.random() * 250),
  ])

  build() {
    Column() {
      Polyline()
        .animatablePoints(this.points)
        .animation({ duration: 1500, curve: Curve.EaseOut })// 設(shè)置動畫參數(shù)
        .size({ height: 250, width: 350 })
        .fill(Color.Blue)
        .stroke(Color.Yellow)
        .backgroundColor('#aaccff')
      Button("Play")
        .onClick(() => {
          // points是實現(xiàn)了可動畫協(xié)議的數(shù)據(jù)類型,points在動畫過程中可按照定義的運算規(guī)則、動畫參數(shù)從之前的PointVector變?yōu)樾碌腜ointVector數(shù)據(jù),產(chǎn)生每一幀的PointVector數(shù)據(jù),進而產(chǎn)生動畫
          this.points = new PointVector([
            new Point(30, Math.random() * 250),
            new Point(80, Math.random() * 250),
            new Point(130, Math.random() * 250),
            new Point(180, Math.random() * 250),
            new Point(230, Math.random() * 250),
          ])
        })
    }.width("100%")
    .padding(20)
  }
}
圖片動圖

在這個示例中,我們定義了 Point 類表示二維平面上的點,PointVector 類表示點的數(shù)組。通過實現(xiàn) AnimatableArithmetic<T> 接口,我們?yōu)?PointVector 定義了加法、減法、乘法和相等判斷規(guī)則。然后,我們使用 @AnimatableExtend 裝飾器將 animatablePoints 函數(shù)應(yīng)用到 Polyline 組件上,點擊按鈕時,折線的頂點位置會隨機變化,從而實現(xiàn)動畫效果。

3. 總結(jié)

@AnimatableExtend 裝飾器為實現(xiàn)復(fù)雜動畫效果提供了一種強大而靈活的方式。通過自定義動畫屬性和實現(xiàn) AnimatableArithmetic<T> 接口,我們可以對不同類型的數(shù)據(jù)進行動畫處理。在實際開發(fā)中,我們可以根據(jù)具體需求靈活運用這個裝飾器,實現(xiàn)各種炫酷的動畫效果。希望這篇博客能幫助你快速掌握 @AnimatableExtend 裝飾器的使用,讓你的應(yīng)用更加生動有趣。

通過以上的學(xué)習(xí)和實踐,你可以逐步掌握 @AnimatableExtend 裝飾器的使用方法,并且在實際項目中靈活運用,為用戶帶來更加豐富的動畫體驗。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容