動畫的原理是在一個時間段內(nèi)督惰,多次改變UI外觀,由于人眼會產(chǎn)生視覺暫留若锁,所以最終看到的就是一個“連續(xù)”的動畫。UI的一次改變稱為一個動畫幀斧吐,對應(yīng)一次屏幕刷新又固,而決定動畫流暢度的一個重要指標就是幀率FPS(Frame Per Second)仲器,即每秒的動畫幀數(shù),幀率越高則動畫就會越流暢仰冠。
ArkUI中乏冀,產(chǎn)生動畫的方式是改變屬性值且指定動畫參數(shù)。動畫參數(shù)包含了如動畫時長洋只、變化規(guī)律(即曲線)等參數(shù)辆沦。當屬性值發(fā)生變化后,按照動畫參數(shù)识虚,從原來的狀態(tài)過渡到新的狀態(tài)肢扯,即形成一個動畫。
ArkUI提供的動畫能力按照頁面的分類方式担锤,可分為頁面內(nèi)的動畫和頁面間的動畫蔚晨。如下圖所示,頁面內(nèi)的動畫指在一個頁面內(nèi)即可發(fā)生的動畫肛循,頁面間的動畫指兩個頁面跳轉(zhuǎn)時才會發(fā)生的動畫铭腕。
圖1 按照頁面分類的動畫
如果按照基礎(chǔ)能力分,可分為屬性動畫多糠、顯式動畫谨履、轉(zhuǎn)場動畫三部分。如下圖所示熬丧。
圖2 按照基礎(chǔ)能力分類的動畫
使用顯式動畫產(chǎn)生布局更新動畫
顯式動畫的接口為:
animateTo(value: AnimateParam, event: () => void): void
第一個參數(shù)指定動畫參數(shù),第二個參數(shù)為動畫的閉包函數(shù)怀挠。
以下是使用顯式動畫產(chǎn)生布局更新動畫的示例析蝴。示例中,當Column組件的alignItems屬性改變后绿淋,其子組件的布局位置結(jié)果發(fā)生變化闷畸。只要該屬性是在animateTo的閉包函數(shù)中修改的,那么由其引起的所有變化都會按照animateTo的動畫參數(shù)執(zhí)行動畫過渡到終點值吞滞。
@Entry
@Component
struct LayoutChange {
// 用于控制Column的alignItems屬性
@State itemAlign: HorizontalAlign = HorizontalAlign.Start;
allAlign: HorizontalAlign[] = [HorizontalAlign.Start, HorizontalAlign.Center, HorizontalAlign.End];
alignIndex: number = 0;
build() {
Column() {
Column({ space: 10 }) {
Button("1").width(100).height(50)
Button("2").width(100).height(50)
Button("3").width(100).height(50)
}
.margin(20)
.alignItems(this.itemAlign)
.borderWidth(2)
.width("90%")
.height(200)
Button("click").onClick(() => {
// 動畫時長為1000ms佑菩,曲線為EaseInOut
animateTo({ duration: 1000, curve: Curve.EaseInOut }, () => {
this.alignIndex = (this.alignIndex + 1) % this.allAlign.length;
// 在閉包函數(shù)中修改this.itemAlign參數(shù),使Column容器內(nèi)部孩子的布局方式變化裁赠,使用動畫過渡到新位置
this.itemAlign = this.allAlign[this.alignIndex];
});
})
}
.width("100%")
.height("100%")
}
}
除直接改變布局方式外殿漠,也可直接修改組件的寬、高佩捞、位置绞幌。
@Entry
@Component
struct LayoutChange2 {
@State myWidth: number = 100;
@State myHeight: number = 50;
// 標志位,true和false分別對應(yīng)一組myWidth一忱、myHeight值
@State flag: boolean = false;
build() {
Column({ space: 10 }) {
Button("text")
.type(ButtonType.Normal)
.width(this.myWidth)
.height(this.myHeight)
.margin(20)
Button("area: click me")
.fontSize(12)
.margin(20)
.onClick(() => {
animateTo({ duration: 1000, curve: Curve.Ease }, () => {
// 動畫閉包中根據(jù)標志位改變控制第一個Button寬高的狀態(tài)變量莲蜘,使第一個Button做寬高動畫
if (this.flag) {
this.myWidth = 100;
this.myHeight = 50;
} else {
this.myWidth = 200;
this.myHeight = 100;
}
this.flag = !this.flag;
});
})
}
.width("100%")
.height("100%")
}
}
另一種方式是給第二個Button添加布局約束谭确,如position的位置約束,使其位置不被第一個Button的寬高影響票渠。核心代碼如下:
Column({ space: 10 }) {
Button("text")
.type(ButtonType.Normal)
.width(this.myWidth)
.height(this.myHeight)
.margin(20)
Button("area: click me")
.fontSize(12)
// 配置position屬性固定逐哈,使自己的布局位置不被第一個Button的寬高影響
.position({ x: "30%", y: 200 })
.onClick(() => {
animateTo({ duration: 1000, curve: Curve.Ease }, () => {
// 動畫閉包中根據(jù)標志位改變控制第一個Button寬高的狀態(tài)變量,使第一個Button做寬高動畫
if (this.flag) {
this.myWidth = 100;
this.myHeight = 50;
} else {
this.myWidth = 200;
this.myHeight = 100;
}
this.flag = !this.flag;
});
})
}
.width("100%")
.height("100%")
使用屬性動畫產(chǎn)生布局更新動畫
顯式動畫把要執(zhí)行動畫的屬性的修改放在閉包函數(shù)中觸發(fā)動畫问顷,而屬性動畫則無需使用閉包昂秃,把animation屬性加在要做屬性動畫的組件的屬性后即可。
屬性動畫的接口為:
animation(value: AnimateParam)
其入?yún)閯赢媴?shù)择诈。想要組件隨某個屬性值的變化而產(chǎn)生動畫械蹋,此屬性需要加在animation屬性之前。有的屬性變化不希望通過animation產(chǎn)生屬性動畫羞芍,可以放在animation之后哗戈。上面顯式動畫的示例很容易改為用屬性動畫實現(xiàn)。例如:
@Entry
@Component
struct LayoutChange2 {
@State myWidth: number = 100;
@State myHeight: number = 50;
@State flag: boolean = false;
@State myColor: Color = Color.Blue;
build() {
Column({ space: 10 }) {
Button("text")
.type(ButtonType.Normal)
.width(this.myWidth)
.height(this.myHeight)
// animation只對其上面的type荷科、width唯咬、height屬性生效,時長為1000ms畏浆,曲線為Ease
.animation({ duration: 1000, curve: Curve.Ease })
// animation對下面的backgroundColor胆胰、margin屬性不生效
.backgroundColor(this.myColor)
.margin(20)
Button("area: click me")
.fontSize(12)
.onClick(() => {
// 改變屬性值,配置了屬性動畫的屬性會進行動畫過渡
if (this.flag) {
this.myWidth = 100;
this.myHeight = 50;
this.myColor = Color.Blue;
} else {
this.myWidth = 200;
this.myHeight = 100;
this.myColor = Color.Pink;
}
this.flag = !this.flag;
})
}
}
}
上述示例中刻获,第一個button上的animation屬性蜀涨,只對寫在animation之前的type、width蝎毡、height屬性生效厚柳,而對寫在animation之后的backgroundColor、margin屬性無效沐兵。運行結(jié)果是width别垮、height屬性會按照animation的動畫參數(shù)執(zhí)行動畫,而backgroundColor會直接跳變扎谎,不會產(chǎn)生動畫