HarmonyOS 應(yīng)用開發(fā)之@AnimatableExtend裝飾器:定義可動(dòng)畫屬性

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

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

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