HarmonyOS NEXT應(yīng)用開發(fā)—使用繪制組件實(shí)現(xiàn)自定義進(jìn)度動畫

介紹

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

效果預(yù)覽圖

使用說明

  1. 加載完成后初始顯示進(jìn)度為0%,顏色為紅色,且有充電、放電兩個按鈕。
  2. 點(diǎn)擊充電按鈕,進(jìn)度會持續(xù)增長,直到100%時綠色填充滿整個圓形,當(dāng)?shù)竭_(dá)20%以上和80%以上時,顏色動態(tài)變化。
  3. 點(diǎn)擊耗電按鈕,進(jìn)度會持續(xù)下降,直到0%恢復(fù)1中的初始效果,當(dāng)?shù)竭_(dá)20%以下和80%以下時,顏色動態(tài)變化。

實(shí)現(xiàn)思路

  1. 使用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"))
  1. 繪制中間的進(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"))
  1. 計(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}`;
  }
  1. 繪制最上層的百分比顯示。源碼參考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                            // 視圖層-繪制組件頁面 

模塊依賴

本場景依賴了路由模塊來注冊路由。

參考資料

Circle組件

Path組件

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

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

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