1# Border Image 2 3You can draw an image around a component. 4 5> **NOTE** 6> 7> The APIs of this module are supported since API version 9. Updates will be marked with a superscript to indicate their earliest API version. 8 9## borderImage 10 11borderImage(value: BorderImageOption) 12 13Sets the border image of the component. 14 15**Widget capability**: Since API version 9, this feature is supported in ArkTS widgets. 16 17**Atomic service API**: This API can be used in atomic services since API version 11. 18 19**System capability**: SystemCapability.ArkUI.ArkUI.Full 20 21**Parameters** 22 23| Name | Type | Mandatory| Description | 24| ----------- | ----------------------------------------------- | ---- | -------------------------------- | 25| value | [BorderImageOption](#borderimageoption) | Yes | Border image or border gradient.| 26 27## BorderImageOption 28 29**Widget capability**: Since API version 9, this feature is supported in ArkTS widgets. 30 31| Name | Type | Mandatory| Description | 32| ------ | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 33| source | string \| [Resource](ts-types.md#resource) \| [linearGradient](ts-universal-attributes-gradient-color.md) | No| Source or gradient color of the border image. When the type is string, this parameter sets the border image source. For details about how to reference image resources, see [Loading Image Resources ](../../../ui/arkts-graphics-display.md#loading-image-resources).<br>**NOTE**<br>The border image source applies only to container components, such as [Row](ts-container-row.md), [Column](ts-container-column.md), and [Flex](ts-container-flex.md).<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 34| slice | [Length](ts-types.md#length) \| [EdgeWidths](ts-types.md#edgewidths9) \| [LocalizedEdgeWidths](ts-types.md#localizededgewidths12)<sup>12+</sup>| No| Slice width of the upper left corner, upper right corner, lower left corner, and lower right corner of the border image.<br>Default value: **0**<br>**NOTE**<br>If this parameter is set to a negative value, the default value is used.<br>When this parameter is set to a value of the [Length](ts-types.md#length) type, the value applies to the four corners in a unified manner.<br>When this parameter is set to a value of the [EdgeWidths](ts-types.md#edgewidths9) type:<br>- **Top**: slice height of the upper left or upper right corner of the image.<br>- **Bottom**: slice height of the lower left or lower right corner of the image.<br>- **Left**: slice width of the upper left or lower left corner of the image.<br>- **Right**: slice width of the upper right or lower right corner of the image.<br>When the parameter type is [LocalizedEdgeWidths](ts-types.md#localizededgewidths12)<sup>12+</sup>:<br>- **Top**: slice height of the upper left or upper right corner of the image.<br>- **Bottom**: slice height of the lower left or lower right corner of the image.<br>- **Start**: slice width of the upper left or lower left corner of the image for left-to-right scripts;<br>slice width of the upper right or lower right corner of the image for right-to-left scripts.<br>- **End**: slice width of the upper right or lower right corner of the image for left-to-right scripts; slice width of the upper left or lower left corner of the image for right-to-left scripts.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 35| width | [Length](ts-types.md#length) \| [EdgeWidths](ts-types.md#edgewidths9) \| [LocalizedEdgeWidths](ts-types.md#localizededgewidths12)<sup>12+</sup> | No| Width of the border image.<br>Default value: **0**<br>**NOTE**<br>If this parameter is set to a negative value, the default value is used.<br>When this parameter is set to a value of the [Length](ts-types.md#length) type, the value applies to the four corners in a unified manner.<br>When this parameter is set to a value of the [EdgeWidths](ts-types.md#edgewidths9) type:<br>- **Top**: width of the top edge of the border image.<br>- **Bottom**: width of the bottom edge of the border image.<br>- **Left**: width of the left edge of the border image.<br>- **Right**: width of the right edge of the border image.<br>When the parameter type is [LocalizedEdgeWidths](ts-types.md#localizededgewidths12)<sup>12+</sup>:<br>- **Top**: width of the top edge of the border image.<br>- **Bottom**: width of the bottom edge of the border image.<br>- **Start**: width of the left edge of the border image for left-to-right scripts;<br>width of the right edge of the border image for right-to-left scripts.<br>- **End**: width of the right edge of the border image for left-to-right scripts;<br>width of the left edge of the border image for right-to-left scripts.<br>If this parameter is set to a negative value, the value **1** is used.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 36| outset | [Length](ts-types.md#length) \| [EdgeWidths](ts-types.md#edgewidths9) \| [LocalizedEdgeWidths](ts-types.md#localizededgewidths12)<sup>12+</sup> | No| Amount by which the border image is extended beyond the border box.<br>Default value: **0**<br>**NOTE**<br>If this parameter is set to a negative value, the default value is used.<br>When this parameter is set to a value of the [Length](ts-types.md#length) type, the value applies to the four corners in a unified manner.<br>When this parameter is set to a value of the [EdgeWidths](ts-types.md#edgewidths9) type:<br>- **Top**: amount by which the top edge of the border image is extended beyond the border box.<br>- **Bottom**: amount by which the bottom edge of the border image is extended beyond the border box.<br>- **Left**: amount by which the left edge of the border image is extended beyond the border box.<br>- **Right**: amount by which the right edge of the border image is extended beyond the border box.<br>When the parameter type is [LocalizedEdgeWidths](ts-types.md#localizededgewidths12)<sup>12+</sup>:<br>- **Top**: amount by which the top edge of the border image is extended beyond the border box.<br>- **Bottom**: amount by which the bottom edge of the border image is extended beyond the border box.<br>- **Start**: amount by which the left edge of the border image is extended beyond the border box for left-to-right scripts;<br>amount by which the right edge of the border image is extended beyond the border box for right-to-left scripts.<br>- **End**: amount by which the right edge of the border image is extended beyond the border box for left-to-right scripts;<br>amount by which the left edge of the border image is extended beyond the border box for right-to-left scripts.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 37| repeat | [RepeatMode](#repeatmode) | No| Repeat mode of the source image's slices on the border.<br>Default value: **RepeatMode.Stretch**<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 38| fill | boolean | No| Whether to fill the center of the border image.<br>**true**: Fill the center of the border image.<br>**false**: Do not fill the center of the border image.<br>Default value: **false**<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 39 40## RepeatMode 41 42**Widget capability**: Since API version 9, this feature is supported in ArkTS widgets. 43 44**Atomic service API**: This API can be used in atomic services since API version 11. 45 46| Name | Description | 47| ------- | ----------------------------------- | 48| Repeat | The source image's slices are tiled. Tiles beyond the border box will be clipped. | 49| Stretch | The source image's slices are stretched to fill the border box. | 50| Round | The source image's slices are tiled to fill the border box. Tiles may be compressed when needed.| 51| Space | The source image's slices are tiled to fill the border box. Extra space will be distributed in between tiles. | 52 53## Example 54 55### Example 1: Setting a Gradient Border 56 57This example demonstrates how to set a gradient border for a component using the **borderImage** API. 58 59```ts 60// xxx.ets 61@Entry 62@Component 63struct Index { 64 build() { 65 Row() { 66 Column() { 67 Text('This is gradient color.').textAlign(TextAlign.Center).height(50).width(200) 68 .borderImage({ 69 source: { 70 angle: 90, 71 direction: GradientDirection.Left, 72 colors: [[0xAEE1E1, 0.0], [0xD3E0DC, 0.3], [0xFCD1D1, 1.0]] 73 }, 74 slice: { top: 10, bottom: 10, left: 10, right: 10 }, 75 width: { top: "10px", bottom: "10px", left: "10px", right: "10px" }, 76 repeat: RepeatMode.Stretch, 77 fill: false 78 }) 79 } 80 .width('100%') 81 } 82 .height('100%') 83 } 84} 85``` 86 87 88 89### Example 2: Dynamically Adjusting Property Values 90 91This example demonstrates how to dynamically adjust the properties of the **borderImage** API using the [slider](../../apis-arkui/arkui-js/js-components-basic-slider.md) component. 92 93```ts 94// xxx.ets 95@Entry 96@Component 97struct BorderImage { 98 @State WidthValue: number = 0 99 @State SliceValue: number = 0 100 @State OutSetValue: number = 0 101 @State RepeatValue: RepeatMode[] = [RepeatMode.Repeat, RepeatMode.Stretch, RepeatMode.Round, RepeatMode.Space] 102 @State SelectIndex: number = 0 103 @State SelectText: string = 'Repeat' 104 @State FillValue: boolean = false 105 106 build() { 107 Row() { 108 Column({ space: 20 }) { 109 Row() { 110 Text('This is borderImage.').textAlign(TextAlign.Center).fontSize(50) 111 } 112 .borderImage({ 113 source: $r('app.media.icon'), 114 slice: this.SliceValue, 115 width: this.WidthValue, 116 outset: this.OutSetValue, 117 repeat: this.RepeatValue[this.SelectIndex], 118 fill: this.FillValue 119 }) 120 121 Column() { 122 Text(`borderImageSlice = ${this.SliceValue}px`) 123 Slider({ 124 value: this.SliceValue, 125 min: 0, 126 max: 100, 127 style: SliderStyle.OutSet 128 }) 129 .onChange((value: number, mode: SliderChangeMode) => { 130 this.SliceValue = value 131 }) 132 } 133 134 Column() { 135 Text(`borderImageWidth = ${this.WidthValue}px`) 136 Slider({ 137 value: this.WidthValue, 138 min: 0, 139 max: 100, 140 style: SliderStyle.OutSet 141 }) 142 .onChange((value: number, mode: SliderChangeMode) => { 143 this.WidthValue = value 144 }) 145 } 146 147 Column() { 148 Text(`borderImageOutSet = ${this.OutSetValue}px`) 149 Slider({ 150 value: this.OutSetValue, 151 min: 0, 152 max: 100, 153 style: SliderStyle.OutSet 154 }) 155 .onChange((value: number, mode: SliderChangeMode) => { 156 this.OutSetValue = value 157 }) 158 } 159 160 Row() { 161 Text('borderImageRepeat: ') 162 Select([{ value: 'Repeat' }, { value: 'Stretch' }, { value: 'Round' }, { value: 'Space' }]) 163 .value(this.SelectText) 164 .selected(this.SelectIndex) 165 .onSelect((index: number, value?: string) => { 166 this.SelectIndex = index 167 this.SelectText = value as string 168 }) 169 } 170 171 Row() { 172 Text(`borderImageFill: ${this.FillValue} `) 173 Toggle({ type: ToggleType.Switch, isOn: this.FillValue }) 174 .onChange((isOn: boolean) => { 175 this.FillValue = isOn 176 }) 177 } 178 179 } 180 .width('100%') 181 } 182 .height('100%') 183 } 184} 185``` 186 187 188 189### Example 3: Using LocalizedEdgeWidths Type Values 190 191This example demonstrates how to use the [LocalizedEdgeWidths](ts-types.md#localizededgewidths12) type for the **slice**, **width**, and **outset** properties in the **borderImage** API. 192 193```ts 194// xxx.ets 195import { LengthMetrics } from '@kit.ArkUI' 196 197@Entry 198@Component 199struct BorderImage { 200 @State WidthStartValue: number = 0 201 @State WidthEndValue: number = 0 202 @State SliceStartValue: number = 0 203 @State SliceEndValue: number = 0 204 @State OutSetStartValue: number = 0 205 @State OutSetEndValue: number = 0 206 @State RepeatValue: RepeatMode[] = [RepeatMode.Repeat, RepeatMode.Stretch, RepeatMode.Round, RepeatMode.Space] 207 @State SelectIndex: number = 0 208 @State SelectText: string = 'Repeat' 209 @State FillValue: boolean = false 210 211 build() { 212 Row() { 213 Column({ space: 20 }) { 214 Row() { 215 Text('This is borderImage.').textAlign(TextAlign.Center).fontSize(50) 216 } 217 .borderImage({ 218 source: $r('app.media.icon'), 219 slice: { 220 top: LengthMetrics.px(10), 221 bottom: LengthMetrics.px(10), 222 start: LengthMetrics.px(this.SliceStartValue), 223 end: LengthMetrics.px(this.SliceEndValue) }, 224 width: { 225 top: LengthMetrics.px(10), 226 bottom: LengthMetrics.px(10), 227 start: LengthMetrics.px(this.WidthStartValue), 228 end: LengthMetrics.px(this.WidthEndValue) 229 }, 230 outset: { 231 top: LengthMetrics.px(10), 232 bottom: LengthMetrics.px(10), 233 start: LengthMetrics.px(this.OutSetStartValue), 234 end: LengthMetrics.px(this.OutSetEndValue) 235 }, 236 repeat: this.RepeatValue[this.SelectIndex], 237 fill: this.FillValue 238 }) 239 240 Column() { 241 Text(`borderImageSliceStart = ${this.SliceStartValue}px`) 242 Slider({ 243 value: this.SliceStartValue, 244 min: 0, 245 max: 100, 246 style: SliderStyle.OutSet 247 }) 248 .onChange((value: number, mode: SliderChangeMode) => { 249 this.SliceStartValue = value 250 }) 251 } 252 253 Column() { 254 Text(`borderImageEndSliceStart = ${this.SliceEndValue}px`) 255 Slider({ 256 value: this.SliceEndValue, 257 min: 0, 258 max: 100, 259 style: SliderStyle.OutSet 260 }) 261 .onChange((value: number, mode: SliderChangeMode) => { 262 this.SliceEndValue = value 263 }) 264 } 265 266 Column() { 267 Text(`borderImageWidthStart = ${this.WidthStartValue}px`) 268 Slider({ 269 value: this.WidthStartValue, 270 min: 0, 271 max: 100, 272 style: SliderStyle.OutSet 273 }) 274 .onChange((value: number, mode: SliderChangeMode) => { 275 this.WidthStartValue = value 276 }) 277 } 278 279 Column() { 280 Text(`borderImageWidthEnd = ${this.WidthEndValue}px`) 281 Slider({ 282 value: this.WidthEndValue, 283 min: 0, 284 max: 100, 285 style: SliderStyle.OutSet 286 }) 287 .onChange((value: number, mode: SliderChangeMode) => { 288 this.WidthEndValue = value 289 }) 290 } 291 292 Column() { 293 Text(`borderImageOutSetStart = ${this.OutSetStartValue}px`) 294 Slider({ 295 value: this.OutSetStartValue, 296 min: 0, 297 max: 100, 298 style: SliderStyle.OutSet 299 }) 300 .onChange((value: number, mode: SliderChangeMode) => { 301 this.OutSetStartValue = value 302 }) 303 } 304 305 Column() { 306 Text(`borderImageOutSetEnd = ${this.OutSetEndValue}px`) 307 Slider({ 308 value: this.OutSetEndValue, 309 min: 0, 310 max: 100, 311 style: SliderStyle.OutSet 312 }) 313 .onChange((value: number, mode: SliderChangeMode) => { 314 this.OutSetEndValue = value 315 }) 316 } 317 318 Row() { 319 Text('borderImageRepeat: ') 320 Select([{ value: 'Repeat' }, { value: 'Stretch' }, { value: 'Round' }, { value: 'Space' }]) 321 .value(this.SelectText) 322 .selected(this.SelectIndex) 323 .onSelect((index: number, value?: string) => { 324 this.SelectIndex = index 325 this.SelectText = value as string 326 }) 327 } 328 329 Row() { 330 Text(`borderImageFill: ${this.FillValue} `) 331 Toggle({ type: ToggleType.Switch, isOn: this.FillValue }) 332 .onChange((isOn: boolean) => { 333 this.FillValue = isOn 334 }) 335 } 336 337 } 338 .width('100%') 339 } 340 .height('100%') 341 } 342} 343``` 344 345The following shows how the example is represented with left-to-right scripts. 346 347 348 349The following shows how the example is represented with right-to-left scripts. 350 351 352