ts-drawing-components-shape.md 8.7 KB
Newer Older
Z
zengyawen 已提交
1 2
# Shape

Z
zengyawen 已提交
3 4
绘制组件的父组件,父组件中会描述所有绘制组件均支持的通用属性。

Z
zengyawen 已提交
5

Z
zengyawen 已提交
6 7 8 9
1、绘制组件使用Shape作为父组件,实现类似SVG的效果。

2、绘制组件单独使用,用于在页面上绘制指定的图形。

T
third  
tianyu 已提交
10 11 12
>  **说明:**
>
>  该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
Z
zengyawen 已提交
13

Z
zengyawen 已提交
14

Z
zengyawen 已提交
15
## 子组件
Z
zengyawen 已提交
16

Z
zengyawen 已提交
17
可以包含子组件。
Z
zengyawen 已提交
18 19


Z
zengyawen 已提交
20
## 接口
Z
zengyawen 已提交
21

T
third  
tianyu 已提交
22 23
Shape(value?: PixelMap)

24 25 26 27 28
**参数:**

| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 | 
| -------- | -------- | -------- | -------- | -------- |
| value | PixelMap | 否 | - | 绘制目标,可将图形绘制在指定的PixelMap对象中,若未设置,则在当前绘制目标中进行绘制。 | 
Z
zengyawen 已提交
29 30


Z
zengyawen 已提交
31
## 属性
Z
zengyawen 已提交
32

L
luoying_ace_admin 已提交
33 34
除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性:

Z
zengyawen 已提交
35 36
| 参数名称 | 参数类型 | 默认值 | 必填 | 参数描述 |
| -------- | -------- | -------- | -------- | -------- |
L
luoying_ace_admin 已提交
37
| viewPort | {<br/>x?:&nbsp;number \| string,<br/>y?:&nbsp;number \| string,<br/>width?:&nbsp;number \| string,<br/>height?:&nbsp;number \| string<br/>} | { x:0, y:0, width:0, height:0 } | 否 | 形状的视口。 |
H
HelloCrease 已提交
38 39 40
| fill | [ResourceColor](ts-types.md) | Color.Black | 否 | 设置填充区域颜色。 |
| fillOpacity | number&nbsp;\|&nbsp;string&nbsp;\|&nbsp;[Resource](ts-types.md#resource类型) | 1 | 否 | 设置填充区域透明度。 |
| stroke | [ResourceColor](ts-types.md) | Color.Black | 否 | 设置线条颜色。 |
L
luoying_ace_admin 已提交
41 42 43 44 45
| strokeDashArray | Array&lt;Length&gt; | [] | 否 | 设置线条间隙。 |
| strokeDashOffset | number&nbsp;\|&nbsp;string | 0 | 否 | 线条绘制起点的偏移量。 |
| strokeLineCap | [LineCapStyle](ts-appendix-enums.md#linecapstyle) | LineCapStyle.Butt | 否 | 设置线条端点绘制样式。 |
| strokeLineJoin | [LineJoinStyle](ts-appendix-enums.md#linejoinstyle) | LineJoinStyle.Miter | 否 | 设置线条拐角绘制样式。 |
| strokeMiterLimit | number&nbsp;\|&nbsp;string | 4 | 否 | 设置锐角绘制成斜角的极限值。 |
H
HelloCrease 已提交
46
| strokeOpacity | number&nbsp;\|&nbsp;string&nbsp;\|&nbsp;[Resource](ts-types.md#resource类型) | 1 | 否 | 设置线条透明度。 |
L
luoying_ace_admin 已提交
47 48 49
| strokeWidth | number&nbsp;\|&nbsp;string | 1 | 否 | 设置线条宽度。 |
| antiAlias | boolean | true | 否 | 是否开启抗锯齿效果。 |
| mesh<sup>8+</sup> | Array&lt;number&gt;,number,number | [],0,0 | 否 | 设置mesh效果。第一个参数为长度(column + 1)* (row + 1)* 2的数组,它记录了扭曲后的位图各个顶点位置,第二个参数为mesh矩阵列数column,第三个参数为mesh矩阵行数row。 |
Z
zengyawen 已提交
50

51
## 示例1
Z
zengyawen 已提交
52

H
geshi  
HelloCrease 已提交
53 54
```ts
// xxx.ets
Z
zengyawen 已提交
55 56 57 58
@Entry
@Component
struct ShapeExample {
  build() {
59 60 61 62 63
    Column({ space: 10 }) {
      Text('basic').fontSize(11).fontColor(0xCCCCCC).width(320)
      // 在Shape的(-2, -2)点绘制一个 300 * 50 带边框的矩形,颜色0x317AF7,边框颜色黑色,边框宽度4,边框间隙20,向左偏移10,线条两端样式为半圆,拐角样式圆角,抗锯齿(默认开启)
      // 在Shape的(-2, 58)点绘制一个 300 * 50 带边框的椭圆,颜色0x317AF7,边框颜色黑色,边框宽度4,边框间隙20,向左偏移10,线条两端样式为半圆,拐角样式圆角,抗锯齿(默认开启)
      // 在Shape的(-2, 118)点绘制一个 300 * 10 直线路径,颜色0x317AF7,边框颜色黑色,宽度4,间隙20,向左偏移10,线条两端样式为半圆,拐角样式圆角,抗锯齿(默认开启)
Z
zengyawen 已提交
64 65 66 67 68
      Shape() {
        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 })
      }
Z
zengyawen 已提交
69
      .viewPort({ x: -2, y: -2, width: 304, height: 130 })
70 71 72 73 74 75 76 77 78
      .fill(0x317AF7)
      .stroke(Color.Black)
      .strokeWidth(4)
      .strokeDashArray([20])
      .strokeDashOffset(10)
      .strokeLineCap(LineCapStyle.Round)
      .strokeLineJoin(LineJoinStyle.Round)
      .antiAlias(true)
      // 分别在Shape的(0, 0)、(-5, -5)点绘制一个 300 * 50 带边框的矩形,可以看出之所以将视口的起始位置坐标设为负值是因为绘制的起点默认为线宽的中点位置,因此要让边框完全显示则需要让视口偏移半个线宽
Z
zengyawen 已提交
79 80
      Shape() {
        Rect().width(300).height(50)
81 82 83 84 85
      }
      .viewPort({ x: 0, y: 0, width: 320, height: 70 })
      .fill(0x317AF7)
      .stroke(Color.Black)
      .strokeWidth(10)
Z
zengyawen 已提交
86 87

      Shape() {
88 89 90 91 92 93 94 95 96
        Rect().width(300).height(50)
      }
      .viewPort({ x: -5, y: -5, width: 320, height: 70 })
      .fill(0x317AF7)
      .stroke(Color.Black)
      .strokeWidth(10)

      Text('path').fontSize(11).fontColor(0xCCCCCC).width(320)
      // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,线条间隙20
Z
zengyawen 已提交
97 98 99
      Shape() {
        Path().width(300).height(10).commands('M0 0 L900 0')
      }
Z
zengyawen 已提交
100
      .viewPort({ x: 0, y: -5, width: 300, height: 20 })
101 102 103 104
      .stroke(0xEE8443)
      .strokeWidth(10)
      .strokeDashArray([20])
      // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,线条间隙20,向左偏移10
Z
zengyawen 已提交
105 106
      Shape() {
        Path().width(300).height(10).commands('M0 0 L900 0')
107 108 109 110 111 112 113
      }
      .viewPort({ x: 0, y: -5, width: 300, height: 20 })
      .stroke(0xEE8443)
      .strokeWidth(10)
      .strokeDashArray([20])
      .strokeDashOffset(10)
      // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,透明度0.5
Z
zengyawen 已提交
114 115 116
      Shape() {
        Path().width(300).height(10).commands('M0 0 L900 0')
      }
Z
zengyawen 已提交
117
      .viewPort({ x: 0, y: -5, width: 300, height: 20 })
118 119 120 121
      .stroke(0xEE8443)
      .strokeWidth(10)
      .strokeOpacity(0.5)
      // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,线条间隙20,线条两端样式为半圆
Z
zengyawen 已提交
122
      Shape() {
123
        Path().width(300).height(10).commands('M0 0 L900 0')
Z
zengyawen 已提交
124
      }
125 126 127 128 129 130
      .viewPort({ x: 0, y: -5, width: 300, height: 20 })
      .stroke(0xEE8443)
      .strokeWidth(10)
      .strokeDashArray([20])
      .strokeLineCap(LineCapStyle.Round)
      // 在Shape的(-80, -5)点绘制一个封闭路径,颜色0x317AF7,线条宽度10,边框颜色0xEE8443,拐角样式锐角(默认值)
Z
zengyawen 已提交
131
      Shape() {
132
        Path().width(200).height(60).commands('M0 0 L400 0 L400 150 Z')
Z
zengyawen 已提交
133
      }
134 135 136 137 138 139
      .viewPort({ x: -80, y: -5, width: 310, height: 90 })
      .fill(0x317AF7)
      .stroke(0xEE8443)
      .strokeWidth(10)
      .strokeLineJoin(LineJoinStyle.Miter)
      .strokeMiterLimit(5)
Z
zengyawen 已提交
140 141 142 143 144
    }.width('100%').margin({ top: 15 })
  }
}
```

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

## 示例2

```ts
// xxx.ets
@Entry
@Component
struct ShapeMeshExample {
  @State columnVal: number = 0;
  @State rowVal: number = 0;
  @State count: number = 0;
  @State verts: Array<number> = [];
  @State shapeWidth: number = 600;
  @State shapeHeight: number = 600;

  build() {
    Column() {
      Shape() {
        Rect()
          .width('250px')
          .height('250px')
          .radiusWidth('10px')
          .radiusHeight('10px')
          .stroke('10px')
          .margin({ left: '10px', top: '10px' })
          .strokeWidth('10px')
          .fill(Color.Blue)
        Rect()
          .width('250px')
          .height('250px')
          .radiusWidth('10px')
          .radiusHeight('10px')
          .stroke('10px')
          .margin({ left: '270px', top: '10px' })
          .strokeWidth('10px')
          .fill(Color.Red)
      }
      .mesh(this.verts, this.columnVal, this.rowVal)
      .width(this.shapeWidth + 'px')
      .height(this.shapeHeight + 'px')
      // 手指触摸Shape组件时会显示mesh扭曲效果
      .onTouch((event: TouchEvent) => {
        var touchX = event.touches[0].x * 2;
        var touchY = event.touches[0].y * 2;
        this.columnVal = 20;
        this.rowVal = 20;
        this.count = (this.columnVal + 1) * (this.rowVal + 1);
        var orig = [this.count * 2];
        var index = 0;
        for (var i = 0; i <= this.rowVal; i++) {
          var fy = this.shapeWidth * i / this.rowVal;
          for (var j = 0; j <= this.columnVal; j++) {
            var fx = this.shapeWidth * j / this.columnVal;
            orig[index * 2 + 0] = this.verts[index * 2 + 0] = fx;
            orig[index * 2 + 1] = this.verts[index * 2 + 1] = fy;
            index++;
          }
        }
        for (var k = 0; k < this.count * 2; k += 2) {
          var dx = touchX - orig[k + 0];
          var dy = touchY - orig[k + 1];
          var dd = dx * dx + dy * dy;
          var d = Math.sqrt(dd);
          var pull = 80000 / (dd * d);
          if (pull >= 1) {
            this.verts[k + 0] = touchX;
            this.verts[k + 1] = touchY;
          } else {
            this.verts[k + 0] = orig[k + 0] + dx * pull;
            this.verts[k + 1] = orig[k + 1] + dy * pull;
          }
        }
      })
    }
    .width('600px')
    .height('600px')
    .border({ width: 3, color: Color.Black })
  }
}
```