矩形与通用绘制容器是线性绘制的核心组成。Rect 用于绘制带或不带圆角的矩形,而 Shape 则作为所有绘制类组件的父容器,能够组合不同图形并应用统一的描边与填充样式。


1 Rect 组件

Rect 在自身坐标系内从 (0,0) 到 (width,height) 绘制一个矩形,支持统一或分角圆角,以及所有来自 CommonShapeMethod 的通用描边与填充属性。

1.1 定义

interface Rect extends RectAttribute<Rect> {
  (value?: {
    width?: number | string;
    height?: number | string;
    radius?: number | string | Array<any>;
  } | {
    width?: number | string;
    height?: number | string;
    radiusWidth?: number | string;
    radiusHeight?: number | string;
  }): Rect;
}

declare class RectAttribute<T> extends CommonShapeMethod<T> {
  radius(value: number | string | Array<any>): T;
  radiusWidth(value: number | string): T;
  radiusHeight(value: number | string): T;
}
  • width, height:矩形外框尺寸。
  • radius:统一或单独设置四个角的圆角半径(可传数组)。
  • radiusWidth / radiusHeight:分别设置水平与垂直圆角半径。

1.2 示例

TypeScript 版:

@Entry @Component
struct RectDemo {
  build() {
    Column({ space: 10, padding: 10, width: '100%', height: '100%' }) {
      // 普通矩形
      Rect()
        .width(220)
        .height(50)
        .fill(Color.Pink);

      // 四角圆角 10vp
      Rect()
        .width(220)
        .height(50)
        .radius(10)
        .fill(Color.Pink);

      // 水平/垂直半径均为 25vp
      Rect()
        .width(220)
        .height(50)
        .radiusWidth(25)
        .radiusHeight(25)
        .fill(Color.Pink);

      // 一侧圆角并加红色描边
      Rect()
        .width(220)
        .height(50)
        .radiusWidth(25)
        .fill(Color.Pink)
        .strokeWidth(3)
        .stroke("#ff0000");

      // 同时设置虚线描边
      Rect()
        .width(220)
        .height(50)
        .radiusWidth(25)
        .fill(Color.Pink)
        .strokeWidth(3)
        .stroke("#ff0000")
        .strokeDashArray([10]);
    }
  }
}

JavaScript/C++ 版:

@Entry @Component
class MyView {
  func build() {
    Column(10) {
      Rect()
        .width(220)
        .height(50)
        .fill(0xffc0cb);

      Rect()
        .width(220)
        .height(50)
        .radius(10)
        .fill(0xffc0cb);

      Rect()
        .width(220)
        .height(50)
        .radiusWidth(25)
        .radiusHeight(25)
        .fill(0xffc0cb);

      Rect()
        .width(220)
        .height(50)
        .radiusWidth(25)
        .fill(0xffc0cb)
        .strokeWidth(3)
        .stroke(0xff0000);

      Rect()
        .width(220)
        .height(50)
        .radiusWidth(25)
        .fill(0xffc0cb)
        .strokeWidth(3)
        .stroke(0xff0000)
        .strokeDashArray([10]);
    }
    .padding(10)
    .width(100.percent)
    .height(100.percent);
  }
}

2 Shape 容器

Shape 允许在同一坐标系下组合多个绘制组件(如 RectEllipsePath 等),并对整体应用统一的视窗裁剪、描边与填充属性。

1 定义

interface ShapeInterface {
  (value?: PixelMap): ShapeAttribute;
}

declare class ShapeAttribute extends CommonMethod<ShapeAttribute> {
  viewPort(value: { x?: number | string; y?: number | string; width?: number | string; height?: number | string }): T;
  mesh(value: Array<any>, column: number, row: number): T;
  // 以及所有 CommonShapeMethod 中的 stroke、fill、strokeDashArray 等方法
}
  • viewPort:定义 Shape 的可视区域,用于裁剪内部所有子图形。
  • value?: PixelMap:可传入位图作为填充。

2 示例

TypeScript 版:

@Entry @Component
struct ShapeDemo {
  build() {
    Column({ space: 10, padding: 10, width: '100%', height: '100%' }) {
      // 综合示例:矩形、椭圆与直线路径
      Shape()
        .viewPort({ x: -2, y: -2, width: 304, height: 130 })
        .fill(0x317Af7)
        .stroke(Color.Black)
        .strokeWidth(4)
        .strokeDashArray([20])
        .strokeDashOffset(10)
        .strokeLineCap(LineCapStyle.Round)
        .strokeLineJoin(LineJoinStyle.Round)
        .antiAlias(true)  
      {
        Rect().width(300).height(50);
        Ellipse().width(300).height(50).offset({ x: 0, y: 60 });
        Path()
          .width(300)
          .height(10)
          .commands('M0 0 L900 0')
          .offset({ x: 0, y: 120 });
      }

      // 单独矩形边框
      Shape()
        .viewPort({ x: -1, y: -1, width: 302, height: 52 })
        .fill(0x317Af7)
        .stroke(Color.Black)
        .strokeWidth(2)
      {
        Rect().width(300).height(50);
      }

      // 虚线直线
      Shape()
        .viewPort({ x: 0, y: -5, width: 300, height: 10 })
        .stroke(0xEE8443)
        .strokeWidth(20)
        .strokeDashArray([4])
      {
        Path().width(300).height(10).commands('M0 0 L900 0');
      }

      // 不透明度示例
      Shape()
        .viewPort({ x: 0, y: 0, width: 300, height: 20 })
        .stroke(0xEE8443)
        .strokeWidth(10)
        .strokeOpacity(0.5)
      {
        Path().width(300).height(10).commands('M0 0 L900 0');
      }

      // 圆角矩形组合
      Shape()
        .viewPort({ x: -5, y: -5, width: 310, height: 120 })
        .fill(0x317Af7)
        .stroke(0xEE8443)
        .strokeWidth(10)
        .strokeLineJoin(LineJoinStyle.Round)
      {
        Rect().width(300).height(100);
      }

      // 锐角剪裁示例
      Shape()
        .viewPort({ x: -80, y: -5, width: 310, height: 100 })
        .fill(0x317Af7)
        .stroke(0xEE8443)
        .strokeWidth(10)
        .strokeLineJoin(LineJoinStyle.Miter)
        .strokeMiterLimit(10)
      {
        Path().width(300).height(60).commands('M0 0 L400 0 L400 200 Z');
      }
    }
  }
}

JavaScript/C++ 版:

@Entry @Component
class MyView {
  func build() {
    Column(10) {
      Shape()
        .viewPort(x: -2, y: -2, width: 304, height: 130)
        .fill(0x317Af7)
        .stroke(0x000000)
        .strokeWidth(4)
        .strokeDashArray([20])
        .strokeDashOffset(10)
        .strokeLineCap(LineCapStyle.Round)
        .strokeLineJoin(LineJoinStyle.Round)
        .antiAlias(true)
      {
        Rect().width(300).height(50);
        Ellipse().width(300).height(50).offset(x: 0, y: 60);
        Path()
          .width(300)
          .height(10)
          .commands('M0 0 L900 0')
          .offset(x: 0, y: 120);
      }

      Shape()
        .viewPort(x: -1, y: -1, width: 302, height: 52)
        .fill(0x317Af7)
        .stroke(0x000000)
        .strokeWidth(2)
      {
        Rect().width(300).height(50);
      }

      Shape()
        .viewPort(x: 0, y: -5, width: 300, height: 10)
        .stroke(0xEE8443)
        .strokeWidth(20)
        .strokeDashArray([4])
      {
        Path().width(300).height(10).commands('M0 0 L900 0');
      }

      // 此处略:继续其他示例...
    }
    .padding(10)
    .width(100.percent)
    .height(100.percent);
  }
}

3 小结

  • Rect 适用于绘制标准或圆角矩形,通过 radiusradiusWidthradiusHeight 灵活控制边角;
  • Shape 可承载多种图形组件,为它们指定统一的视窗剪裁样式属性,非常适合复杂矢量组合与自定义边框、网格化渲染。

至此,ArkUI 提供的所有绘制容器组件均已详尽介绍过,读者可结合 EllipseCircleLinePath 等实现丰富的 UI 矢量效果。

Logo

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

更多推荐