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.<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>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
56
57
58```ts
59// xxx.ets
60@Entry
61@Component
62struct Index {
63  build() {
64    Row() {
65      Column() {
66        Text('This is gradient color.').textAlign(TextAlign.Center).height(50).width(200)
67          .borderImage({
68            source: {
69              angle: 90,
70              direction: GradientDirection.Left,
71              colors: [[0xAEE1E1, 0.0], [0xD3E0DC, 0.3], [0xFCD1D1, 1.0]]
72            },
73            slice: { top: 10, bottom: 10, left: 10, right: 10 },
74            width: { top: "10px", bottom: "10px", left: "10px", right: "10px" },
75            repeat: RepeatMode.Stretch,
76            fill: false
77          })
78      }
79      .width('100%')
80    }
81    .height('100%')
82  }
83}
84```
85
86![en-us_image_borderImageGradient](figures/borderImageGradient.png)
87
88### Example 2
89
90```ts
91// xxx.ets
92@Entry
93@Component
94struct BorderImage {
95  @State WidthValue: number = 0
96  @State SliceValue: number = 0
97  @State OutSetValue: number = 0
98  @State RepeatValue: RepeatMode[] = [RepeatMode.Repeat, RepeatMode.Stretch, RepeatMode.Round, RepeatMode.Space]
99  @State SelectIndex: number = 0
100  @State SelectText: string = 'Repeat'
101  @State FillValue: boolean = false
102
103  build() {
104    Row() {
105      Column({ space: 20 }) {
106        Row() {
107          Text('This is borderImage.').textAlign(TextAlign.Center).fontSize(50)
108        }
109        .borderImage({
110          source: $r('app.media.icon'),
111          slice: this.SliceValue,
112          width: this.WidthValue,
113          outset: this.OutSetValue,
114          repeat: this.RepeatValue[this.SelectIndex],
115          fill: this.FillValue
116        })
117
118        Column() {
119          Text(`borderImageSlice = ${this.SliceValue}px`)
120          Slider({
121            value: this.SliceValue,
122            min: 0,
123            max: 100,
124            style: SliderStyle.OutSet
125          })
126            .onChange((value: number, mode: SliderChangeMode) => {
127              this.SliceValue = value
128            })
129        }
130
131        Column() {
132          Text(`borderImageWidth = ${this.WidthValue}px`)
133          Slider({
134            value: this.WidthValue,
135            min: 0,
136            max: 100,
137            style: SliderStyle.OutSet
138          })
139            .onChange((value: number, mode: SliderChangeMode) => {
140              this.WidthValue = value
141            })
142        }
143
144        Column() {
145          Text(`borderImageOutSet = ${this.OutSetValue}px`)
146          Slider({
147            value: this.OutSetValue,
148            min: 0,
149            max: 100,
150            style: SliderStyle.OutSet
151          })
152            .onChange((value: number, mode: SliderChangeMode) => {
153              this.OutSetValue = value
154            })
155        }
156
157        Row() {
158          Text('borderImageRepeat: ')
159          Select([{ value: 'Repeat' }, { value: 'Stretch' }, { value: 'Round' }, { value: 'Space' }])
160            .value(this.SelectText)
161            .selected(this.SelectIndex)
162            .onSelect((index: number, value?: string) => {
163              this.SelectIndex = index
164              this.SelectText = value as string
165            })
166        }
167
168        Row() {
169          Text(`borderImageFill: ${this.FillValue} `)
170          Toggle({ type: ToggleType.Switch, isOn: this.FillValue })
171            .onChange((isOn: boolean) => {
172              this.FillValue = isOn
173            })
174        }
175
176      }
177      .width('100%')
178    }
179    .height('100%')
180  }
181}
182```
183
184![borderImage](figures/borderImage.gif)
185
186### Example 3
187
188```ts
189// xxx.ets
190// The slice, width, and outset attributes of borderImage use the LocalizedEdgeWidths type.
191
192import { LengthMetrics } from '@kit.ArkUI'
193
194@Entry
195@Component
196struct BorderImage {
197  @State WidthStartValue: number = 0
198  @State WidthEndValue: number = 0
199  @State SliceStartValue: number = 0
200  @State SliceEndValue: number = 0
201  @State OutSetStartValue: number = 0
202  @State OutSetEndValue: number = 0
203  @State RepeatValue: RepeatMode[] = [RepeatMode.Repeat, RepeatMode.Stretch, RepeatMode.Round, RepeatMode.Space]
204  @State SelectIndex: number = 0
205  @State SelectText: string = 'Repeat'
206  @State FillValue: boolean = false
207
208  build() {
209    Row() {
210      Column({ space: 20 }) {
211        Row() {
212          Text('This is borderImage.').textAlign(TextAlign.Center).fontSize(50)
213        }
214        .borderImage({
215          source: $r('app.media.icon'),
216          slice: {
217            top: LengthMetrics.px(10),
218            bottom: LengthMetrics.px(10),
219            start: LengthMetrics.px(this.SliceStartValue),
220            end: LengthMetrics.px(this.SliceEndValue) },
221          width: {
222            top: LengthMetrics.px(10),
223            bottom: LengthMetrics.px(10),
224            start: LengthMetrics.px(this.WidthStartValue),
225            end: LengthMetrics.px(this.WidthEndValue)
226          },
227          outset: {
228            top: LengthMetrics.px(10),
229            bottom: LengthMetrics.px(10),
230            start: LengthMetrics.px(this.OutSetStartValue),
231            end: LengthMetrics.px(this.OutSetEndValue)
232          },
233          repeat: this.RepeatValue[this.SelectIndex],
234          fill: this.FillValue
235        })
236
237        Column() {
238          Text(`borderImageSliceStart = ${this.SliceStartValue}px`)
239          Slider({
240            value: this.SliceStartValue,
241            min: 0,
242            max: 100,
243            style: SliderStyle.OutSet
244          })
245            .onChange((value: number, mode: SliderChangeMode) => {
246              this.SliceStartValue = value
247            })
248        }
249
250        Column() {
251          Text(`borderImageEndSliceStart = ${this.SliceEndValue}px`)
252          Slider({
253            value: this.SliceEndValue,
254            min: 0,
255            max: 100,
256            style: SliderStyle.OutSet
257          })
258            .onChange((value: number, mode: SliderChangeMode) => {
259              this.SliceEndValue = value
260            })
261        }
262
263        Column() {
264          Text(`borderImageWidthStart = ${this.WidthStartValue}px`)
265          Slider({
266            value: this.WidthStartValue,
267            min: 0,
268            max: 100,
269            style: SliderStyle.OutSet
270          })
271            .onChange((value: number, mode: SliderChangeMode) => {
272              this.WidthStartValue = value
273            })
274        }
275
276        Column() {
277          Text(`borderImageWidthEnd = ${this.WidthEndValue}px`)
278          Slider({
279            value: this.WidthEndValue,
280            min: 0,
281            max: 100,
282            style: SliderStyle.OutSet
283          })
284            .onChange((value: number, mode: SliderChangeMode) => {
285              this.WidthEndValue = value
286            })
287        }
288
289        Column() {
290          Text(`borderImageOutSetStart = ${this.OutSetStartValue}px`)
291          Slider({
292            value: this.OutSetStartValue,
293            min: 0,
294            max: 100,
295            style: SliderStyle.OutSet
296          })
297            .onChange((value: number, mode: SliderChangeMode) => {
298              this.OutSetStartValue = value
299            })
300        }
301
302        Column() {
303          Text(`borderImageOutSetEnd = ${this.OutSetEndValue}px`)
304          Slider({
305            value: this.OutSetEndValue,
306            min: 0,
307            max: 100,
308            style: SliderStyle.OutSet
309          })
310            .onChange((value: number, mode: SliderChangeMode) => {
311              this.OutSetEndValue = value
312            })
313        }
314
315        Row() {
316          Text('borderImageRepeat: ')
317          Select([{ value: 'Repeat' }, { value: 'Stretch' }, { value: 'Round' }, { value: 'Space' }])
318            .value(this.SelectText)
319            .selected(this.SelectIndex)
320            .onSelect((index: number, value?: string) => {
321              this.SelectIndex = index
322              this.SelectText = value as string
323            })
324        }
325
326        Row() {
327          Text(`borderImageFill: ${this.FillValue} `)
328          Toggle({ type: ToggleType.Switch, isOn: this.FillValue })
329            .onChange((isOn: boolean) => {
330              this.FillValue = isOn
331            })
332        }
333
334      }
335      .width('100%')
336    }
337    .height('100%')
338  }
339}
340```
341
342The following shows how the example is represented with left-to-right scripts.
343
344![borderImage](figures/borderImage_ltr.png)
345
346The following shows how the example is represented with right-to-left scripts.
347
348![borderImage](figures/borderImage_rtl.png)
349