介紹
本示例介紹使用繪制組件中的Circle組件以及Path組件實(shí)現(xiàn)實(shí)時進(jìn)度效果。該場景多用于手機(jī)電池電量、汽車油量、水位變化等動態(tài)變化中。
效果預(yù)覽圖

使用說明
- 加載完成后初始顯示進(jìn)度為0%,顏色為紅色,且有充電、放電兩個按鈕。
- 點(diǎn)擊充電按鈕,進(jìn)度會持續(xù)增長,直到100%時綠色填充滿整個圓形,當(dāng)?shù)竭_(dá)20%以上和80%以上時,顏色動態(tài)變化。
- 點(diǎn)擊耗電按鈕,進(jìn)度會持續(xù)下降,直到0%恢復(fù)1中的初始效果,當(dāng)?shù)竭_(dá)20%以下和80%以下時,顏色動態(tài)變化。
實(shí)現(xiàn)思路
- 使用Circle組件繪制外層的圓環(huán)。 源碼參考PaintComponent.ets。
// 外框圓環(huán)
Circle({ width: Constants.BIG_DIAMETER, height: Constants.BIG_DIAMETER })
.fill(Constants.COLOR_TRANSPARENT)
.stroke(this.colorBackgroundFill)
.strokeWidth($r("app.integer.outer_circle_stroke_width"))
- 繪制中間的進(jìn)度的填充。中間的填充有兩個狀態(tài):1、在進(jìn)度100%時是填充顏色的圓形;2、在進(jìn)度不足100%時,使用Path組件繪制閉合曲線實(shí)現(xiàn)。源碼參考PaintComponent.ets。
// 進(jìn)度展示
Circle({ width: Constants.DIAMETER, height: Constants.DIAMETER })
.fill(this.bgColor)
// TODO:知識點(diǎn):使用Path組件繪制封閉曲線,實(shí)現(xiàn)水位線效果
Path()
.width(Constants.DIAMETER)
.height(Constants.DIAMETER)
.commands(this.pathCommands)
.fill(this.colorBackgroundFill)
.antiAlias(true)
.stroke(this.colorBackgroundFill)
.strokeWidth($r("app.integer.path_stroke_width"))
- 計(jì)算封閉曲線。水位線的端點(diǎn)的縱坐標(biāo)y與進(jìn)度k的關(guān)系為:y=(1-k)*2r,而圓心坐標(biāo)為(r,r),以此確定水位線的坐標(biāo),然后拼接成繪制封閉曲線的commands。源碼參考PaintComponent.ets。
/**
* 根據(jù)進(jìn)度拿到水位線的端點(diǎn)的縱坐標(biāo)
*
* @param progressPercent 進(jìn)度百分比
* @returns 水位線的端點(diǎn)的縱坐標(biāo)
*/
getOrdinate(progressPercent: number): number {
return (Constants.UNIT_ONE - progressPercent) * (Constants.RADIUS_IN_PX + Constants.RADIUS_IN_PX);
}
/**
* 根據(jù)圓心,以及縱坐標(biāo)拿到水位線兩個端點(diǎn)的距離的平方
*
* @param ordinate 縱坐標(biāo)
* @returns 端點(diǎn)間距離的平方
*/
getDistanceSquare(ordinate: number): number {
return Constants.RADIUS_IN_PX * Constants.RADIUS_IN_PX - (ordinate - Constants.RADIUS_IN_PX) * (ordinate - Constants.RADIUS_IN_PX);
}
/**
* 計(jì)算閉合曲線
*
* @param progressNum 進(jìn)度
* @returns 繪制閉合曲線的commands
*/
getPathCommands(progressNum: number): string {
// 拿到水位線的端點(diǎn)的縱坐標(biāo)
const ordinate: number = this.getOrdinate(progressNum / Constants.PERCENT_RATE);
// 拿到端點(diǎn)之間的距離的平方
const distanceSquare: number = this.getDistanceSquare(ordinate);
if (distanceSquare >= Constants.ZERO) {
// 開平方得到端點(diǎn)間的距離
const distance: number = Math.sqrt(distanceSquare);
// 計(jì)算得出第一個端點(diǎn)的橫坐標(biāo)
const firstAbscissa: number = Constants.RADIUS_IN_PX - distance;
// 計(jì)算得到第二個端點(diǎn)的橫坐標(biāo)
const secondAbscissa: number = Constants.RADIUS_IN_PX + distance;
return this.formatPathCommands(firstAbscissa, secondAbscissa, ordinate, Constants.RADIUS_IN_PX);
}
return "";
}
/**
* 拼接繪制閉合曲線的commands
*
* @param firstAbscissa
* @param secondAbscissa
* @param ordinate
* @param radius
* @returns
*/
formatPathCommands(firstAbscissa: number, secondAbscissa: number, ordinate: number, radius: number): string {
return `M${firstAbscissa} ${ordinate} A${radius} ${radius} 0 ${ordinate > Constants.RADIUS_IN_PX ? 0 : 1} 0 ${secondAbscissa} ${ordinate}`
+ `Q${(firstAbscissa + 3 * secondAbscissa) / 4} ${ordinate + 12.5 * (secondAbscissa - firstAbscissa) / radius}, ${(firstAbscissa + secondAbscissa) / 2} ${ordinate} T${firstAbscissa} ${ordinate}`;
}
- 繪制最上層的百分比顯示。源碼參考PaintComponent.ets。
// 進(jìn)度百分比
Row() {
Text($r("app.string.progress_percentage_symbol_name"))
.fontColor(Constants.COLOR_NORMAL)
.fontSize($r("app.integer.progress_percentage_symbol_font_size"))
Text(this.progressNum.toFixed(Constants.ZERO) + Constants.PERCENTAGE_STR)
.fontSize($r("app.integer.progress_percentage_font_size"))
高性能知識點(diǎn)
不涉及
工程結(jié)構(gòu)&模塊類型
paintcomponent // har類型
|---constants
| |---Constants.ets // 常量類
|---view
| |---PaintComponent.ets // 視圖層-繪制組件頁面
模塊依賴
本場景依賴了路由模塊來注冊路由。