ArkUI Path:想画不规则图形,就别再硬拼布局了

举报
蓝瘦的蜕变 发表于 2026/10/10 18:18:13 2026/10/10
【摘要】 这一篇我们看 Path。如果一个图形已经不是圆、线、矩形能舒服表达的样子,就别再用一堆布局硬拼了,直接写路径会更干净。 commands 是重点 Path 的核心是 commands。你可以先记住几个常用字母: M:移动到某个点。 L:连线到某个点。 C:画三次贝塞尔曲线。 Z:闭合当前路径。 Demo 第一块用 M

ArkUI Path:想画不规则图形,就别再硬拼布局了

这一篇我们看 Path。如果一个图形已经不是圆、线、矩形能舒服表达的样子,就别再用一堆布局硬拼了,直接写路径会更干净。

commands 是重点

Path 的核心是 commands。你可以先记住几个常用字母:

  • M:移动到某个点。
  • L:连线到某个点。
  • C:画三次贝塞尔曲线。
  • Z:闭合当前路径。

Demo 第一块用 M + L + Z 画三角形。第二块用 C 画曲线封闭图形。第三块加上 strokeDashArray 做虚线。最后一块把 Path 放进 Stack,做一个轻微倾斜的标签底。

先别急着解析外部 SVG

很多人第一次看到 Path,会马上想到把 SVG 字符串塞进来。这个方向没错,但入门时先手写一小段更有价值。你知道每个点怎么影响形状之后,再看外部 SVG 的路径数据才不会发懵。

Path()
  .commands('M26 104 L90 24 L154 104 Z')
  .fill('#DBEAFE')
  .stroke('#2563EB')
  .strokeWidth(4)

这段代码画的是一个闭合三角形。fill 决定内部颜色,stroke 决定边线,strokeWidth 决定边线粗细。

虚线别靠多个短线拼

如果要做路线感、流程感、提示边界,用 strokeDashArray 比手写一堆短线更省心。

Path()
  .commands('M18 90 C54 24 96 138 150 56 C168 30 186 34 204 52')
  .stroke('#7C3AED')
  .strokeWidth(5)
  .strokeDashArray([12, 8])

这里的 [12, 8] 可以先理解成:画一段,再空一段。数字变大,节奏就会变稀。

你自己做页面时,哪些地方最想用不规则底形?角标、标签、流程线,还是卡片装饰?这个问题可以留到动手时顺便试一下。

参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-geometric-shape-drawing

完整示例代码

文件位置:entry/src/main/ets/pages/arkUI/drawing/ArkUIPathDemo.ets

@Entry
@Component
struct ArkUIPathDemo {
  @Builder
  sectionTitle(title: string, desc: string) {
    Column({ space: 4 }) {
      Text(title)
        .width('100%')
        .fontSize(16)
        .fontWeight(700)
        .fontColor('#0F172A')

      Text(desc)
        .width('100%')
        .fontSize(13)
        .fontColor('#64748B')
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 18 }) {
        Text('ArkUI Path')
          .width('100%')
          .fontSize(24)
          .fontWeight(700)
          .fontColor('#0F172A')

        Text('想画不规则图形,就别再硬拼布局了')
          .width('100%')
          .fontSize(22)
          .fontWeight(700)
          .fontColor('#111827')

        Text('Path 的核心是 commands。它适合画几何组件不好表达的图形,比如弧线、异形底、路线感装饰。')
          .width('100%')
          .fontSize(14)
          .fontColor('#64748B')
          .lineHeight(22)

        Column({ space: 12 }) {
          this.sectionTitle('M 和 L 能画出最朴素的封闭图形', 'M 表示移动到某个点,L 表示连线到某个点,Z 表示闭合。先从三角形看,最容易建立坐标感。')

          Shape() {
            Path()
              .commands('M26 104 L90 24 L154 104 Z')
              .fill('#DBEAFE')
              .stroke('#2563EB')
              .strokeWidth(4)
          }
          .width('100%')
          .height(130)
          .viewPort({ x: 0, y: 0, width: 180, height: 130 })
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#EFF6FF')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('C 可以画曲线', '如果图形开始有弧度,就别再用多个圆角矩形硬凑。曲线路径更轻,也更好调。')

          Shape() {
            Path()
              .commands('M22 78 C42 18 116 18 146 78 C116 126 52 126 22 78 Z')
              .fill('#DCFCE7')
              .stroke('#0F766E')
              .strokeWidth(4)
          }
          .width('100%')
          .height(142)
          .viewPort({ x: 0, y: 0, width: 170, height: 142 })
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#F0FDF4')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('strokeDashArray 让线条有节奏', '虚线适合路线、流程和强调边界。这里不解析外部 SVG,只手写一条足够小的命令。')

          Shape() {
            Path()
              .commands('M18 90 C54 24 96 138 150 56 C168 30 186 34 204 52')
              .stroke('#7C3AED')
              .strokeWidth(5)
              .strokeDashArray([12, 8])
          }
          .width('100%')
          .height(132)
          .viewPort({ x: 0, y: 0, width: 220, height: 132 })
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#F5F3FF')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('Path 也能做小标签底形', '这种轻微倾斜的底形,用 Stack 拼也能做,但 Path 更干净。你只要关心几个点的位置。')

          Stack() {
            Shape() {
              Path()
                .commands('M0 18 L176 0 L196 58 L20 76 Z')
                .fill('#FFEDD5')
                .stroke('#C2410C')
                .strokeWidth(3)
            }
            .width(210)
            .height(86)
            .viewPort({ x: 0, y: 0, width: 210, height: 86 })

            Text('Path Badge')
              .fontSize(18)
              .fontWeight(700)
              .fontColor('#9A3412')
          }
          .width('100%')
          .height(100)
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#FFF7ED')
        .borderRadius(8)
      }
      .width('100%')
      .padding(20)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。