博客 / 詳情

返回

HarmonyOS ArkTS 組件進階 - Polyline 自學指南

1. Polyline 是什麼?

Polyline 是 ArkUI 提供的 折線繪製組件,簡單説就是:給它一串點座標,它會按順序把這些點用線段連起來。

特點:

  • 支持 任意多個點,適合繪製路徑、折線圖、軌跡線等;
  • 可以控制:

    • 寬高(繪製區域);
    • 線條顏色、粗細、透明度;
    • 虛線樣式(線段長度/間隔長度);
    • 拐角樣式(圓角 / 斜接 / 斜切);
    • 端點樣式(方頭 / 圓頭等);
    • 抗鋸齒;
  • 支持 attributeModifier 動態更新屬性(API 18+);
  • 支持通過 AttributeUpdater.updateConstructorParams 更新構造參數(API 20+)。

基礎信息:

  • 組件名Polyline
  • 子組件:無(它就是繪製一條線,不是容器)
  • 支持版本

    • API 7 起支持;
    • ArkTS 卡片支持:API 9+;
    • 元服務 API:API 11+;
    • PolylineOptions 標準化:API 18+;
    • updateConstructorParams:API 20+。

適用場景舉例:

  • 簡單折線圖、趨勢線;
  • 地圖/路徑軌跡(示意);
  • 裝飾線條(例如波浪線、路線引導);
  • 連線類交互(比如“步驟 1→2→3”的可視化)。

2. 快速上手:畫兩條折線試試

image.png

先不想太多,把它畫出來再説。

// xxx.ets
@Entry
@Component
struct PolylineQuickStart {
  build() {
    Column({ space: 12 }) {
      // 第一條:藍色細折線
      Polyline({ width: 100, height: 100 })
        .points([[0, 0], [20, 60], [100, 100]])
        .fillOpacity(0)          // 不填充區域
        .stroke(Color.Blue)      // 線條顏色
        .strokeWidth(3)          // 線寬

      // 第二條:紅色粗折線,圓角+圓頭
      Polyline()
        .width(100)
        .height(100)
        .points([[20, 0], [0, 100], [100, 90]])
        .fillOpacity(0)
        .stroke(Color.Red)
        .strokeWidth(8)
        .strokeLineJoin(LineJoinStyle.Round)   // 拐角圓角
        .strokeLineCap(LineCapStyle.Round)     // 兩端圓頭
    }
    .width('100%')
    .margin({ top: 16 })
  }
}

你已經用到了幾個核心屬性:

  • 構造:Polyline({ width, height }) 或先構造再 .width() / .height()
  • points:折線經過的點;
  • stroke / strokeWidth:線條樣式;
  • strokeLineJoin / strokeLineCap:拐角和兩端的視覺風格。

3. 構造函數 & PolylineOptions

3.1 構造函數簽名

Polyline(options?: PolylineOptions)
  • options 可選;
  • 內部主要用於指定繪製區域的寬和高;
  • 適用於普通頁面、ArkTS 卡片、元服務。

3.2 PolylineOptions(API 18+)

官方把匿名對象規範了一次,現在是個標準對象:

interface PolylineOptions {
  width?: Length   // ≥ 0,默認 0vp
  height?: Length  // ≥ 0,默認 0vp
}

要點説明:

  • Length 支持:

    • 數字:100(vp)
    • 字符串:'100'
    • 資源:$r('app.string.PolylineWidth')
  • 異常值(undefinednullNaNInfinity)會退回默認值 0;
  • 如果忘記設寬/高,默認 0×0,什麼都看不到 —— 這是新手常見坑。

4. Polyline 核心屬性詳解

Polyline 支持通用屬性(比如 width / height / offset 等),重點關注的是折線繪製相關屬性。

4.1 points:折線經過的點

.points(value: Array<any>)
  • 必填,默認是 [](空數組,不畫任何東西);
  • 傳入二維數組,每個子數組表示 [x, y],單位是 vp;
  • 座標基於當前 Polyline 的寬高區域。

例子:

Polyline({ width: 120, height: 80 })
  .points([[0, 0], [30, 40], [80, 10], [120, 70]])

注意:

  • Polyline 不會自動閉合路徑——它只畫「從第一個點到最後一個點」的折線;
  • 如果你希望形成“封閉形狀”,可以手動把首尾座標設成一樣,但那時更適合用 Polygon

4.2 fill / fillOpacity:填充區域(理論上)

.fill(value: ResourceColor)
.fillOpacity(value: number | string | Resource)

雖然 Polyline 是折線組件,但也支持 fill / fillOpacity

  • fill:填充顏色,默認 Color.Black
  • fillOpacity:填充透明度,默認 1.0。

數值規則(和其他圖形組件一致):

  • 範圍 [0.0, 1.0];
  • <0 會被夾到 0;
  • >1 會被夾到 1;
  • NaN 用 0.0;
  • undefined/null/Infinity 用 1.0。
實戰經驗:
大多數時候你是把 Polyline 當成「線條」用,會設 fillOpacity(0) 或壓根不管填充;
如果你把折線首尾連成封閉區域,fill 才真正有意義——這時可考慮直接改成 Polygon,語義更清晰。

4.3 stroke / strokeWidth / strokeOpacity:線條樣式

.stroke(value: ResourceColor)
.strokeWidth(value: Length)
.strokeOpacity(value: number | string | Resource)
  • stroke:線條顏色;

    • 不設置時,默認透明度為 0,相當於“沒有線”;
  • strokeWidth:線寬,默認 1vp
  • strokeOpacity:線條透明度,默認繼承 stroke 的透明度。

strokeWidth 要點:

  • 取值 ≥ 0;
  • 異常值(undefined/null/NaN)使用默認值 1;
  • Infinity 按 0 處理(等效看不到線)。

strokeOpacity

  • 範圍 [0.0, 1.0];
  • 超出範圍會被鉗制到 0 或 1;
  • NaN → 0.0;
  • undefined/null/Infinity → 1.0。

4.4 虛線:strokeDashArray / strokeDashOffset

.strokeDashArray(value: Array<any>)
.strokeDashOffset(value: number | string)
  • strokeDashArray:描述虛線的「線段長度 / 間隔長度」週期;
  • strokeDashOffset:指定從哪裏開始繪製這條虛線。

規則總結:

  • 默認 []:實線;
  • 數組元素單位為 vp,要求 ≥ 0;
  • 偶數長度數組(例如 [a, b, c, d]):

    • 按順序循環:線段 a → 間隙 b → 線段 c → 間隙 d → 線段 a → …;
  • 奇數長度數組(例如 [a, b, c]):

    • 會被當成 [a, b, c, a, b, c],然後按上面的偶數規則使用。

strokeDashOffset

  • 默認 0;
  • 單位 vp;
  • 如果傳入 NaNInfinity,會導致 strokeDashArray 失效(退變回實線)。
小技巧:
做“流動光線”效果時,可以按照時間週期不斷改變 strokeDashOffset 的值,讓虛線看起來像在移動。

4.5 拐角 & 端點樣式:strokeLineJoin / strokeLineCap

.strokeLineJoin(value: LineJoinStyle)
.strokeLineCap(value: LineCapStyle)
  • strokeLineJoin 控制折線在轉折處的連接方式:

    • 常見枚舉:Miter(尖角)、Round(圓角)、Bevel(斜切角);
    • 默認:LineJoinStyle.Miter
  • strokeLineCap 控制折線末端的樣子:

    • 常見枚舉:Butt(平頭)、Round(圓頭)、Square(方頭);
    • 默認:LineCapStyle.Butt

常見組合:

  • 想要圓潤一點:strokeLineJoin(LineJoinStyle.Round).strokeLineCap(LineCapStyle.Round)
  • UI 比較硬朗:保持默認 Miter + Butt 即可。

4.6 strokeMiterLimit:尖角的“尖鋭程度”

.strokeMiterLimit(value: number | string)

這個屬性只有當 strokeLineJoin = LineJoinStyle.Miter 時才生效,用來控制:

外側尖角的長度 與 線寬 的最大比值。
  • 默認:4;
  • 合法值建議 ≥ 1.0:

    • [0,1) 會按 1.0 處理;
    • 其他異常值按默認 4 來處理;
    • Infinity 會直接讓 stroke 失效。

如果折線存在非常尖鋭的角,而 strokeWidth 又比較大,Miter + 大 strokeMiterLimit 會產生非常長的尖刺 —— 這時候可以:

  • 降低 strokeMiterLimit
  • 或者改用 LineJoinStyle.Round/Bevel

4.7 antiAlias:抗鋸齒開關

.antiAlias(value: boolean)
  • 默認:true
  • 作用:控制邊緣是否做抗鋸齒處理;
  • 通常 UI 場景下保持開啓,線條更柔和。

只有在極致追求性能、線條尺寸較大且對美觀不敏感時,才可能考慮關掉。


5. 實戰示例:把 Polyline 用到實際界面

5.1 迷你折線圖(趨勢展示)

image.png

用 Polyline 做一個簡單的“本週訪問量折線圖”。

@Entry
@Component
struct MiniChartExample {
  private points: number[] = [10, 40, 30, 60, 50, 80, 70]

  build() {
    Column({ space: 8 }) {
      Text('本週訪問趨勢')
        .fontSize(16)
        .fontWeight(FontWeight.Medium)

      // 簡陋版座標映射:假設高度 100,最大值 100
      Polyline({ width: 200, height: 100 })
        .points(this.toPolylinePoints(this.points))
        .fillOpacity(0) // 不填充
        .stroke('#FF2787D9')
        .strokeWidth(3)
        .strokeLineJoin(LineJoinStyle.Round)
        .strokeLineCap(LineCapStyle.Round)

      Text('數據僅供示意,實際繪製可結合座標軸、網格等組件。')
        .fontSize(12)
        .fontColor('#99000000')
    }
    .padding(16)
  }

  private toPolylinePoints(values: number[]): number[][] {
    if (values.length === 0) {
      return []
    }
    const width = 200
    const height = 100
    const step = width / (values.length - 1)
    const max = 100 // 簡化處理,假設最大值 100

    return values.map((v, index) => {
      const x = step * index
      const ratio = Math.min(Math.max(v / max, 0), 1)
      const y = height - ratio * height // 越大越靠上
      return [x, y]
    })
  }
}

這裏演示了兩件事:

  1. 如何將業務數據(數值數組)映射到 Polyline 的座標;
  2. 如何用 strokeLineJoin / strokeLineCap 做一條“圓潤的趨勢線”。

5.2 繪製路徑引導線(配合圖標)

比如在一個「設備連接」頁面畫一條連接兩端設備的線:

@Entry
@Component
struct ConnectLineExample {
  build() {
    Row()
      .width('100%')
      .height(120)
      .backgroundColor('#FFF5F7FA')
      .alignItems(VerticalAlign.Center)
      .justifyContent(FlexAlign.Center) {

      // 左側設備圖標
      Column() {
        Image($r('app.media.device_left'))
          .width(40)
          .height(40)
        Text('設備 A').fontSize(12)
      }
      .margin({ right: 8 })

      // 中間折線路徑
      Polyline({ width: 160, height: 40 })
        .points([[0, 20], [40, 0], [120, 40], [160, 20]])
        .fillOpacity(0)
        .stroke('#FF64BB5C')
        .strokeWidth(4)
        .strokeLineJoin(LineJoinStyle.Round)
        .strokeLineCap(LineCapStyle.Round)

      // 右側設備圖標
      Column() {
        Image($r('app.media.device_right'))
          .width(40)
          .height(40)
        Text('設備 B').fontSize(12)
      }
      .margin({ left: 8 })
    }
  }
}

這是典型的「Polyline 做連線 + 兩邊放組件」的佈局方式,適合用在流程、拓撲、引導類 UI 中。


5.3 attributeModifier:統一管理線條風格

image.png

當你有很多 Polyline 樣式是一致的,可以用 AttributeModifier 把線條風格收口。

// 統一定義一套“高亮軌跡”的樣式
class HighlightPolylineModifier implements AttributeModifier<PolylineAttribute> {
  applyNormalAttribute(instance: PolylineAttribute): void {
    instance.fill('#707070')        // 背景填充色(如果需要)
    instance.fillOpacity(0.4)
    instance.stroke('#FF2787D9')    // 高亮線條色
    instance.strokeDashArray([16])  // 簡單虛線:線段 16,間隔 16
    instance.strokeDashOffset('8')
    instance.strokeLineCap(LineCapStyle.Round)
    instance.strokeLineJoin(LineJoinStyle.Round)
    instance.strokeMiterLimit(5)
    instance.strokeOpacity(0.9)
    instance.strokeWidth(6)
    instance.antiAlias(true)
  }
}

@Entry
@Component
struct PolylineModifierExample {
  @State modifier: HighlightPolylineModifier = new HighlightPolylineModifier()

  build() {
    Column({ space: 12 }) {
      Text('統一樣式的高亮折線')
        .fontSize(16)
        .fontWeight(FontWeight.Medium)

      Polyline()
        .width(200)
        .height(80)
        .points([[0, 40], [60, 10], [140, 70], [200, 30]])
        .attributeModifier(this.modifier)
    }
    .padding(16)
  }
}

好處:

  • 樣式集中管理,主題切換/重塑風格只改一處;
  • 組件樹更乾淨,Polyline 上不會掛一長串鏈式樣式調用。

5.4 寬高的三種寫法對比

@Entry
@Component
struct PolylineLengthTypeExample {
  build() {
    Column({ space: 10 }) {
      // string 類型
      Polyline({ width: '100', height: '100' })
        .points([[0, 0], [20, 60], [100, 100]])
        .fillOpacity(0)
        .stroke(Color.Blue)
        .strokeWidth(3)

      // number 類型
      Polyline({ width: 100, height: 100 })
        .points([[0, 0], [20, 60], [100, 100]])
        .fillOpacity(0)
        .stroke('#FFE84026')
        .strokeWidth(3)

      // Resource 類型(需在資源中定義字符串)
      Polyline({
        width: $r('app.string.PolylineWidth'),
        height: $r('app.string.PolylineHeight')
      })
        .points([[0, 0], [20, 60], [100, 100]])
        .fillOpacity(0)
        .stroke(Color.Green)
        .strokeWidth(3)
    }
    .width('100%')
    .padding(16)
  }
}

如果你團隊習慣把尺寸參數都抽成資源,這種用法會更統一。


6. 常見坑與排查思路

  1. 什麼都沒畫出來?

    • 首先看 width / height 是否為 0(默認就是 0);
    • 再看 points 是否為空數組;
    • 最後確認 stroke 是否設置了,默認是“有顏色但透明度為 0”的效果。
  2. 虛線效果失效?

    • 檢查 strokeDashArray 是否為空;
    • 確認沒有傳 NaN/InfinitystrokeDashOffset,否則虛線配置會失效。
  3. 線條看起來太“硬”、拐角刺眼?

    • 考慮換成 strokeLineJoin(LineJoinStyle.Round)
    • 或者減小 strokeWidth,降低視覺衝擊。
  4. 某些折線角度下出現很長的尖角?

    • 典型是 LineJoinStyle.Miter + 大線寬;
    • 可以調小 strokeMiterLimit 或改用 Round/Bevel
  5. 邊緣有明顯鋸齒?

    • 確認是否誤關了 .antiAlias(false)
    • 大多 UI 場景建議一直開啓抗鋸齒。
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.