1# Shape 2 3绘制组件的父组件,父组件中会描述所有绘制组件均支持的通用属性。 4 51、绘制组件使用Shape作为父组件,实现类似SVG的效果。 6 72、绘制组件单独使用,用于在页面上绘制指定的图形。 8 9> **说明:** 10> 11> 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 12 13 14## 权限列表 15 16无 17 18 19## 子组件 20 21可以包含子组件。 22 23 24## 接口 25 26Shape(value?: PixelMap) 27 28**参数:** 29 30| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 | 31| -------- | -------- | -------- | -------- | -------- | 32| value | [PixelMap](../apis/js-apis-image.md#pixelmap7) | 否 | - | 绘制目标,可将图形绘制在指定的PixelMap对象中,若未设置,则在当前绘制目标中进行绘制。 | 33 34 35## 属性 36 37除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性: 38 39| 名称 | 类型 | 默认值 | 必填 | 描述 | 40| -------- | -------- | -------- | -------- | -------- | 41| viewPort | {<br/>x?: number \| string,<br/>y?: number \| string,<br/>width?: number \| string,<br/>height?: number \| string<br/>} | { x:0, y:0, width:0, height:0 } | 否 | 形状的视口。 | 42| fill | [ResourceColor](ts-types.md#resourcecolor8) | Color.Black | 否 | 设置填充区域颜色。 | 43| fillOpacity | number \| string \| [Resource](ts-types.md#resource) | 1 | 否 | 设置填充区域透明度。 | 44| stroke | [ResourceColor](ts-types.md#resourcecolor8) | - | 否 | 设置边框颜色,不设置时,默认没有边框线条。 | 45| strokeDashArray | Array<Length> | [] | 否 | 设置边框间隙。 | 46| strokeDashOffset | number \| string | 0 | 否 | 边框绘制起点的偏移量。 | 47| strokeLineCap | [LineCapStyle](ts-appendix-enums.md#linecapstyle) | LineCapStyle.Butt | 否 | 设置边框端点绘制样式。 | 48| strokeLineJoin | [LineJoinStyle](ts-appendix-enums.md#linejoinstyle) | LineJoinStyle.Miter | 否 | 设置边框拐角绘制样式。 | 49| strokeMiterLimit | number \| string | 4 | 否 | 设置斜接长度与边框宽度比值的极限值。斜接长度表示外边框外边交点到内边交点的距离,边框宽度即strokeWidth属性的值。<br/>**说明:**<br/>该属性取值需大于等于1,且在strokeLineJoin属性取值LineJoinStyle.Miter时生效。 | 50| strokeOpacity | number \| string \| [Resource](ts-types.md#resource) | 1 | 否 | 设置边框透明度。<br/>**说明:**<br/>该属性的取值范围是[0.0, 1.0],若给定值小于0.0,则取值为0.0;若给定值大于1.0,则取值为1.0。 | 51| strokeWidth | number \| string | 1 | 否 | 设置边框宽度。 | 52| antiAlias | boolean | true | 否 | 是否开启抗锯齿效果。 | 53| mesh<sup>8+</sup> | Array<number>,number,number | [],0,0 | 否 | 设置mesh效果。第一个参数为长度(column + 1)* (row + 1)* 2的数组,它记录了扭曲后的位图各个顶点位置,第二个参数为mesh矩阵列数column,第三个参数为mesh矩阵行数row。 | 54 55## 示例 56 57### 示例1 58 59```ts 60// xxx.ets 61@Entry 62@Component 63struct ShapeExample { 64 build() { 65 Column({ space: 10 }) { 66 Text('basic').fontSize(11).fontColor(0xCCCCCC).width(320) 67 // 在Shape的(-2, -2)点绘制一个 300 * 50 带边框的矩形,颜色0x317AF7,边框颜色黑色,边框宽度4,边框间隙20,向左偏移10,线条两端样式为半圆,拐角样式圆角,抗锯齿(默认开启) 68 // 在Shape的(-2, 58)点绘制一个 300 * 50 带边框的椭圆,颜色0x317AF7,边框颜色黑色,边框宽度4,边框间隙20,向左偏移10,线条两端样式为半圆,拐角样式圆角,抗锯齿(默认开启) 69 // 在Shape的(-2, 118)点绘制一个 300 * 10 直线路径,颜色0x317AF7,边框颜色黑色,宽度4,间隙20,向左偏移10,线条两端样式为半圆,拐角样式圆角,抗锯齿(默认开启) 70 Shape() { 71 Rect().width(300).height(50) 72 Ellipse().width(300).height(50).offset({ x: 0, y: 60 }) 73 Path().width(300).height(10).commands('M0 0 L900 0').offset({ x: 0, y: 120 }) 74 } 75 .viewPort({ x: -2, y: -2, width: 304, height: 130 }) 76 .fill(0x317AF7) 77 .stroke(Color.Black) 78 .strokeWidth(4) 79 .strokeDashArray([20]) 80 .strokeDashOffset(10) 81 .strokeLineCap(LineCapStyle.Round) 82 .strokeLineJoin(LineJoinStyle.Round) 83 .antiAlias(true) 84 // 分别在Shape的(0, 0)、(-5, -5)点绘制一个 300 * 50 带边框的矩形,可以看出之所以将视口的起始位置坐标设为负值是因为绘制的起点默认为线宽的中点位置,因此要让边框完全显示则需要让视口偏移半个线宽 85 Shape() { 86 Rect().width(300).height(50) 87 } 88 .viewPort({ x: 0, y: 0, width: 320, height: 70 }) 89 .fill(0x317AF7) 90 .stroke(Color.Black) 91 .strokeWidth(10) 92 93 Shape() { 94 Rect().width(300).height(50) 95 } 96 .viewPort({ x: -5, y: -5, width: 320, height: 70 }) 97 .fill(0x317AF7) 98 .stroke(Color.Black) 99 .strokeWidth(10) 100 101 Text('path').fontSize(11).fontColor(0xCCCCCC).width(320) 102 // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,线条间隙20 103 Shape() { 104 Path().width(300).height(10).commands('M0 0 L900 0') 105 } 106 .viewPort({ x: 0, y: -5, width: 300, height: 20 }) 107 .stroke(0xEE8443) 108 .strokeWidth(10) 109 .strokeDashArray([20]) 110 // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,线条间隙20,向左偏移10 111 Shape() { 112 Path().width(300).height(10).commands('M0 0 L900 0') 113 } 114 .viewPort({ x: 0, y: -5, width: 300, height: 20 }) 115 .stroke(0xEE8443) 116 .strokeWidth(10) 117 .strokeDashArray([20]) 118 .strokeDashOffset(10) 119 // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,透明度0.5 120 Shape() { 121 Path().width(300).height(10).commands('M0 0 L900 0') 122 } 123 .viewPort({ x: 0, y: -5, width: 300, height: 20 }) 124 .stroke(0xEE8443) 125 .strokeWidth(10) 126 .strokeOpacity(0.5) 127 // 在Shape的(0, -5)点绘制一条直线路径,颜色0xEE8443,线条宽度10,线条间隙20,线条两端样式为半圆 128 Shape() { 129 Path().width(300).height(10).commands('M0 0 L900 0') 130 } 131 .viewPort({ x: 0, y: -5, width: 300, height: 20 }) 132 .stroke(0xEE8443) 133 .strokeWidth(10) 134 .strokeDashArray([20]) 135 .strokeLineCap(LineCapStyle.Round) 136 // 在Shape的(-80, -5)点绘制一个封闭路径,颜色0x317AF7,线条宽度10,边框颜色0xEE8443,拐角样式锐角(默认值) 137 Shape() { 138 Path().width(200).height(60).commands('M0 0 L400 0 L400 150 Z') 139 } 140 .viewPort({ x: -80, y: -5, width: 310, height: 90 }) 141 .fill(0x317AF7) 142 .stroke(0xEE8443) 143 .strokeWidth(10) 144 .strokeLineJoin(LineJoinStyle.Miter) 145 .strokeMiterLimit(5) 146 }.width('100%').margin({ top: 15 }) 147 } 148} 149``` 150 151 152 153### 示例2 154 155```ts 156// xxx.ets 157@Entry 158@Component 159struct ShapeMeshExample { 160 @State columnVal: number = 0; 161 @State rowVal: number = 0; 162 @State count: number = 0; 163 @State verts: Array<number> = []; 164 @State shapeWidth: number = 600; 165 @State shapeHeight: number = 600; 166 167 build() { 168 Column() { 169 Shape() { 170 Rect() 171 .width('250px') 172 .height('250px') 173 .radiusWidth('10px') 174 .radiusHeight('10px') 175 .stroke('10px') 176 .margin({ left: '10px', top: '10px' }) 177 .strokeWidth('10px') 178 .fill(Color.Blue) 179 Rect() 180 .width('250px') 181 .height('250px') 182 .radiusWidth('10px') 183 .radiusHeight('10px') 184 .stroke('10px') 185 .margin({ left: '270px', top: '10px' }) 186 .strokeWidth('10px') 187 .fill(Color.Red) 188 } 189 .mesh(this.verts, this.columnVal, this.rowVal) 190 .width(this.shapeWidth + 'px') 191 .height(this.shapeHeight + 'px') 192 // 手指触摸Shape组件时会显示mesh扭曲效果 193 .onTouch((event: TouchEvent) => { 194 var touchX = event.touches[0].x * 2; 195 var touchY = event.touches[0].y * 2; 196 this.columnVal = 20; 197 this.rowVal = 20; 198 this.count = (this.columnVal + 1) * (this.rowVal + 1); 199 var orig = [this.count * 2]; 200 var index = 0; 201 for (var i = 0; i <= this.rowVal; i++) { 202 var fy = this.shapeWidth * i / this.rowVal; 203 for (var j = 0; j <= this.columnVal; j++) { 204 var fx = this.shapeWidth * j / this.columnVal; 205 orig[index * 2 + 0] = this.verts[index * 2 + 0] = fx; 206 orig[index * 2 + 1] = this.verts[index * 2 + 1] = fy; 207 index++; 208 } 209 } 210 for (var k = 0; k < this.count * 2; k += 2) { 211 var dx = touchX - orig[k + 0]; 212 var dy = touchY - orig[k + 1]; 213 var dd = dx * dx + dy * dy; 214 var d = Math.sqrt(dd); 215 var pull = 80000 / (dd * d); 216 if (pull >= 1) { 217 this.verts[k + 0] = touchX; 218 this.verts[k + 1] = touchY; 219 } else { 220 this.verts[k + 0] = orig[k + 0] + dx * pull; 221 this.verts[k + 1] = orig[k + 1] + dy * pull; 222 } 223 } 224 }) 225 } 226 .width('600px') 227 .height('600px') 228 .border({ width: 3, color: Color.Black }) 229 } 230} 231``` 232 233示意图: 234 235 236 237手指触摸Shape组件时会显示mesh扭曲效果: 238 239