在 ArkUI 框架中,Shape 是所有几何图形组件的父组件(基类),它不仅自身支持通用属性,还可以作为容器包裹 Circle(圆形)、Rect(矩形)、Path(路径)等子组件,实现类似 SVG 的复合绘制效果。

以下梳理这三种核心绘制组件的高级用法与实战技巧:

一、 Shape 组件的高级特性

Shape 的核心优势在于组合绘制视口控制(viewPort)

  1. 组合绘制:可以在 Shape 内部放置多个基础图形,并通过统一的填充、描边属性控制外观。
  2. viewPort 缩放与平移:通过 viewPort({ x, y, width, height }) 属性,可以指定用户空间中的一个矩形映射到组件边界,从而实现绘制内容的放大、缩小或平移效果。
  3. 网格扭曲(Mesh):当传入 PixelMap 作为绘制目标时,可以使用 .mesh() 属性实现网格扭曲效果。

实战示例

Shape() {
  // 底层背景矩形
  Rect().width('100%').height('100%').fill('#0097D4')
  // 叠加圆形
  Circle({ width: 75, height: 75 }).fill('#E87361')
}
.viewPort({ x: 0, y: 0, width: 150, height: 150 }) // 视口控制
.width(300).height(300) // 组件实际尺寸,配合viewPort实现放大
.backgroundColor('#F5DC62')

二、 Rect 组件:灵活的圆角与渐变

Rect 除了基础的宽高和颜色设置,还支持高度定制化的圆角和渐变效果:

  1. 独立控制四角圆角:通过 .radius([[40, 40], [20, 20], [40, 40], [20, 20]]) 可以分别设置左上、右上、右下、左下四个角的圆角半径。
  2. 宽高分离的圆角:使用 .radiusWidth() 和 .radiusHeight() 可以绘制椭圆形的圆角。
  3. 裁剪与渐变结合:从 API 18 开始,结合 .linearGradient() 和 .clipShape(),可以绘制带有复杂倒角边界的渐变色矩形。

实战示例

Rect({ width: '90%', height: 80 })
  .radius([[40, 40], [20, 20], [40, 40], [20, 20]]) // 四角不同圆角
  .fill(Color.Pink)

三、 Path 组件:基于 SVG 规范的自由绘制

Path 是绘制复杂自定义图形(如心形、不规则曲线)的核心组件。它通过 .commands() 属性接收符合 SVG 路径描述规范的字符串。

常用命令速查:
  • M x y:移动画笔到指定起点。
  • L x y:画直线到指定点。
  • H x / V y:画水平/垂直线。
  • C x1 y1 x2 y2 x y:三次贝塞尔曲线(常用于绘制平滑的心形等)。
  • A rx ry ... x y:椭圆弧。
  • Z:闭合路径,自动连接终点与起点。

实战示例(绘制心形)

Path()
  .commands(
    'M150 80 ' +
    'C150 74 140 50 100 50 ' +
    'C40 50 40 125 40 125 ' +
    'C40 160 80 204 150 240 ' +
    'C220 204 260 160 260 125 ' +
    'C260 125 260 50 200 50 ' +
    'C170 50 150 74 150 80 Z'
  )
  .fill(Color.Red)
  .stroke(Color.Orange)
  .strokeWidth(3)

四、 通用高级属性

无论是 Shape 还是其子组件,都支持以下链式调用的渲染控制属性:

  • 填充与透明度.fill(color).fillOpacity(value)
  • 描边与样式.stroke(color).strokeWidth(value).strokeLineJoin()(拐角样式)、.strokeDashArray()(虚线样式)。
  • 抗锯齿.antiAlias(true),默认开启,保证图形边缘平滑。
1、 动态属性控制(AttributeModifier)

在复杂业务中,图形的颜色、透明度、边框等属性往往需要随状态动态变化。ArkUI 提供了 attributeModifier 机制,允许将多个图形属性封装在一个类中,实现统一管理,避免在组件上挂载大量零散的修饰符。

核心逻辑:实现 AttributeModifier<ShapeAttribute> 接口,在 applyNormalAttribute 中集中设置属性。

class MyShapeModifier implements AttributeModifier<ShapeAttribute> {
  applyNormalAttribute(instance: ShapeAttribute): void {
    instance.fill("#707070")
      .fillOpacity(0.5)
      .stroke("#2787D9")
      .strokeWidth(10)
      .strokeLineCap(LineCapStyle.Round)
      .antiAlias(true);
  }
}

@Entry
@Component
struct ShapeModifierDemo {
  @State modifier: MyShapeModifier = new MyShapeModifier();

  build() {
    Column() {
      Shape() {
        Rect().width(200).height(100)
      }
      .attributeModifier(this.modifier) // 统一应用属性
    }
  }
}
2、 Canvas 组件:面向复杂交互的 2D 画布

当需要实现手绘、签名、复杂图表或高频重绘场景时,Shape 的声明式渲染可能面临性能瓶颈。此时应使用 Canvas 组件配合 CanvasRenderingContext2D 进行命令式绘制。

核心逻辑

  1. 初始化 CanvasRenderingContext2D
  2. 在 onReady 中配置画笔属性。
  3. 绑定触摸事件(如 onTouch),在 onActionUpdate 中调用 context 的绘图 API(如 lineTostroke)并调用 context.invalidate() 触发重绘。
@Entry
@Component
struct CanvasDrawDemo {
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true));
  private path: Path2D = new Path2D();

  build() {
    Canvas(this.context)
      .width('100%')
      .height('100%')
      .onReady(() => {
        this.context.lineWidth = 3;
        this.context.strokeStyle = '#000000';
      })
      .onTouch((event: TouchEvent) => {
        if (event.type === TouchType.Down) {
          this.path.moveTo(event.touches[0].x, event.touches[0].y);
        } else if (event.type === TouchType.Move) {
          this.path.lineTo(event.touches[0].x, event.touches[0].y);
          this.context.stroke(this.path);
          this.context.invalidate(); // 关键:触发画布重绘
        }
      })
  }
}
3、 路径动画联动(MotionPath)

Path 组件中的 SVG 路径字符串不仅可以用于静态绘制,还可以作为组件运动的轨迹。通过 .motionPath() 属性,可以让任意 UI 组件沿着自定义的贝塞尔曲线或直线进行平滑动画。

核心逻辑:将 SVG 路径字符串传递给 motionPath 的 path 属性,并设置 rotatable: true 让组件在移动时自动跟随路径切线方向旋转。

Image($r('app.media.car'))
  .width(50)
  .height(50)
  .motionPath({
    path: 'M10 10 L100 10 C150 50 200 100 300 200', // 复用 Path 的 SVG 语法
    from: 0.0,
    to: 1.0,
    rotatable: true
  })
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐