• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Image
2
3图片组件,支持本地图片和网络图片的渲染展示。
4
5> **说明:**
6>
7> 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8
9
10## 需要权限
11
12使用网络图片时,需要申请权限ohos.permission.INTERNET。具体申请方式请参考[权限申请声明](../../security/accesstoken-guidelines.md)。
13
14
15## 子组件
16
1718
19
20## 接口
21
22Image(src: string | PixelMap | Resource)
23
24通过图片数据源获取图片,用于后续渲染展示。
25
26从API version 9开始,该接口支持在ArkTS卡片中使用。
27
28**参数:**
29
30| 参数名  | 参数类型                                     | 必填   | 参数描述                                     |
31| ---- | ---------------------------------------- | ---- | ---------------------------------------- |
32| src  | string\|&nbsp;[PixelMap](../apis/js-apis-image.md#pixelmap7)&nbsp;\|&nbsp;[Resource](ts-types.md#resource类型) | 是    | 图片的数据源,支持本地图片和网络图片。<br/>当使用相对路径引用图片资源时,例如`Image("common/test.jpg")`,不支持跨包/跨模块调用该Image组件,建议使用`$r`方式来管理需全局使用的图片资源。<br/>\- 支持的图片格式包括png、jpg、bmp、svg和gif。<br/>\- 支持`Base64`字符串。格式`data:image/[png\|jpeg\|bmp\|webp];base64,[base64 data]`, 其中`[base64 data]`为`Base64`字符串数据。<br/>\- 支持`datashare://`路径前缀的字符串,用于访问通过data&nbsp;ability提供的图片路径。<br/>\- 支持file:///data/storage路径前缀的字符串,用于读取本应用安装目录下files文件夹下的图片资源。需要保证目录包路径下的文件有可读权限。<br/>**说明:**<br/>- ArkTS卡片上支持gif图片格式动效,但仅在显示时播放一次。<br/>- ArkTS卡片上不支持`http://`等网络相关路径前缀、`datashare://`路径前缀以及`file://data/storage`路径前缀的字符串<br/>- ArkTS卡片上不支持&nbsp;[PixelMap](../apis/js-apis-image.md#pixelmap7)类型 |
33
34## 属性
35
36除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性:
37
38| 名称                       | 参数类型                                     | 描述                                       |
39| ------------------------ | ---------------------------------------- | ---------------------------------------- |
40| alt                      | string \| [Resource](ts-types.md#resource类型) | 加载时显示的占位图,支持本地图片。<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
41| objectFit                | [ImageFit](ts-appendix-enums.md#imagefit) | 设置图片的缩放类型。<br/>默认值:ImageFit.Cover<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
42| objectRepeat             | [ImageRepeat](ts-appendix-enums.md#imagerepeat) | 设置图片的重复样式。<br/>默认值:ImageRepeat.NoRepeat<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**说明:**<br/>svg类型图源不支持该属性。 |
43| interpolation            | [ImageInterpolation](#imageinterpolation) | 设置图片的插值效果,即减轻低清晰度图片在放大显示的时候出现的锯齿问题,仅针对图片放大插值。<br/>默认值:ImageInterpolation.None<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**说明:**<br/>svg类型图源不支持该属性。<br/>PixelMap资源不支持该属性。 |
44| renderMode               | [ImageRenderMode](#imagerendermode)      | 设置图片渲染的模式。<br/>默认值:ImageRenderMode.Original<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**说明:**<br/>svg类型图源不支持该属性。 |
45| sourceSize               | {<br/>width:&nbsp;number,<br/>height:&nbsp;number<br/>} | 设置图片裁剪尺寸,将原始图片解码成pixelMap,指定尺寸的图片,单位为px。<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**说明:**<br/>PixelMap资源和SVG图片不支持该属性。 |
46| matchTextDirection       | boolean                                  | 设置图片是否跟随系统语言方向,在RTL语言环境下显示镜像翻转显示效果。<br/>默认值:false<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
47| fitOriginalSize          | boolean                                  | 图片组件尺寸未设置时,其显示尺寸是否跟随图源尺寸。<br/>默认值:false<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
48| fillColor                | [ResourceColor](ts-types.md#resourcecolor) | 填充颜色。设置的填充颜色会覆盖在图片上。仅对svg图源生效,设置后会替换svg图片的fill颜色。<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
49| autoResize               | boolean                                  | 是否需要在图片解码过程中对图源做resize操作,该操作会根据显示区域的尺寸决定用于绘制的图源尺寸,有利于减少内存占用。<br/>默认值:true<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
50| syncLoad<sup>8+</sup>    | boolean                                  | 设置是否同步加载图片,默认是异步加载。同步加载时阻塞UI线程,不会显示占位图。<br/>默认值:false<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
51| copyOption<sup>9+</sup>  | [CopyOptions](ts-appendix-enums.md#copyoptions9) | 设置图片是否可复制(SVG图片不支持复制)。<br/>当copyOption设置为非CopyOptions.None时,支持使用长按、鼠标右击、快捷组合键'CTRL+C'等方式进行复制。<br/>默认值:CopyOptions.None<br/>该接口支持在ArkTS卡片中使用。 |
52| colorFilter<sup>9+</sup> | [ColorFilter](ts-types.md#colorfilter9)  | 给图像设置颜色滤镜效果。<br/>该接口支持在ArkTS卡片中使用。       |
53
54>  **说明:**
55>
56>  使用快捷组合键对Image组件复制的前提是,该组件必须处于获焦状态。将Image组件的属性focusable设置为true,即可使用TAB键将焦点切换到Image组件上,再将Image组件的focusOnTouch属性设置为true,即可实现点击获焦。
57>  图片设置svg图源时,支持的标签范围有限,目前支持的svg标签包括svg、rect、circle、ellipse、path、line、polyline、polygon。
58
59### ImageInterpolation
60
61从API version 9开始,该接口支持在ArkTS卡片中使用。
62
63| 名称     | 描述                        |
64| ------ | ------------------------- |
65| None   | 不使用插值图片数据。                |
66| High   | 插值图片数据的使用率高,可能会影响图片渲染的速度。 |
67| Medium | 插值图片数据的使用率中。              |
68| Low    | 插值图片数据的使用率低。              |
69
70### ImageRenderMode
71
72从API version 9开始,该接口支持在ArkTS卡片中使用。
73
74| 名称       | 描述                    |
75| -------- | --------------------- |
76| Original | 按照原图进行渲染,包括颜色。        |
77| Template | 将图片渲染为模板图片,忽略图片的颜色信息。 |
78
79## 事件
80
81除支持[通用事件](ts-universal-events-click.md)外,还支持以下事件:
82
83| 名称                                       | 功能描述                                     |
84| ---------------------------------------- | ---------------------------------------- |
85| onComplete(callback:&nbsp;(event?:&nbsp;{&nbsp;width:&nbsp;number,&nbsp;height:&nbsp;number,&nbsp;componentWidth:&nbsp;number,<br>&nbsp;componentHeight:&nbsp;number,&nbsp;loadingStatus:&nbsp;number&nbsp;})&nbsp;=&gt;&nbsp;void) | 图片成功加载时触发该回调,返回成功加载的图片尺寸。<br>- width:图片的宽,单位为像素。<br/>- height:图片的高,单位为像素。<br/>- componentWidth:组件的宽,单位为像素。<br/>- componentHeight:组件的高,单位为像素。<br/>- loadingStatus:图片加载成功的状态。<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。<br/>**说明:** <br/>loadingStatus返回的状态值为0时,代表图片加载失败;返回的状态值为1时,代表图片加载成功。 |
86| onError(callback:&nbsp;(event?:&nbsp;{&nbsp;componentWidth:&nbsp;number,&nbsp;componentHeight:&nbsp;number&nbsp;, message<sup>9+</sup>: string })&nbsp;=&gt;&nbsp;void) | 图片加载出现异常时触发该回调。<br>- componentWidth:组件的宽,单位为像素。<br/>- componentHeight:组件的高,单位为像素。<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
87| onFinish(event:&nbsp;()&nbsp;=&gt;&nbsp;void) | 当加载的源文件为带动效的svg图片时,当svg动效播放完成时会触发这个回调,如果动效为无限循环动效,则不会触发这个回调。<br/>从API version 9开始,该接口支持在ArkTS卡片中使用。 |
88
89## 示例
90
91### 图片加载
92
93加载显示不同类型的图片,并设置图片的缩放类型。
94
95```ts
96@Entry
97@Component
98struct ImageExample1 {
99  private on: string = 'www.example.com'
100  @State src: string = this.on
101
102  build() {
103    Column() {
104      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
105        Text('default').fontSize(16).fontColor(0xcccccc).height(30)
106        Row({ space: 5 }) {
107          Image($r('app.media.ic_png'))
108            .width(110).height(110).border({ width: 1 })
109            .overlay('png', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
110          Image($r('app.media.ic_gif'))
111            .width(110).height(110).border({ width: 1 })
112            .overlay('gif', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
113          Image($r('app.media.ic_svg'))
114            .width(110).height(110).border({ width: 1 })
115            .overlay('svg', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
116        }
117        Row({ space: 5 }) {
118          Image($r('app.media.img_example'))
119            .width(110).height(110).border({ width: 1 })
120            .overlay('jpg', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
121          Image(this.src)
122            .width(110).height(110).border({ width: 1 })
123            .overlay('network', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
124        }.margin({ top: 25, bottom: 10 })
125      }
126
127      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
128        Text('objectFit').fontSize(16).fontColor(0xcccccc).height(30)
129        Row({ space: 5 }) {
130          Image($r('app.media.img_example'))
131            .border({ width: 1 })
132            .objectFit(ImageFit.None).width(110).height(110)
133            .overlay('None', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
134          Image($r('app.media.img_example'))
135            .border({ width: 1 })
136            .objectFit(ImageFit.Fill).width(110).height(110)
137            .overlay('Fill', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
138          Image($r('app.media.img_example'))
139            .border({ width: 1 })
140            .objectFit(ImageFit.Cover).width(110).height(110)
141            .overlay('Cover', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
142        }
143        Row({ space: 5 }) {
144          Image($r('app.media.img_example_w250'))
145            .border({ width: 1 })
146            .objectFit(ImageFit.Contain).width(110).height(110)
147            .overlay('Contain', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
148          Image($r('app.media.img_example_w250'))
149            .border({ width: 1 })
150            .objectFit(ImageFit.ScaleDown).width(110).height(110)
151            .overlay('ScaleDown', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
152        }.margin({ top: 25 })
153      }
154    }.height(320).width(360).padding({ right: 10, top: 10 })
155  }
156}
157```
158
159![zh-cn_image_0000001250492613](figures/zh-cn_image_0000001250492613.gif)
160
161
162
163### 网络图片
164
165加载网络图片时,默认网络超时是5分钟,建议使用alt配置加载时的占位图。如果需要更灵活的网络配置,可以使用SDK中提供的[HTTP](../../connectivity/http-request.md)工具包发送网络请求,接着将返回的数据解码为Image组件中的`PixelMap`,图片开发可参考[图片处理](../../media/image-overview.md)。代码如下。
166
167```tsx
168// @ts-nocheck
169import http from '@ohos.net.http'
170import ResponseCode from '@ohos.net.http'
171import image from '@ohos.multimedia.image'
172
173
174@Entry
175@Component
176struct Index {
177
178  // 先创建一个PixelMap状态变量用于接收网络图片
179  @State image: PixelMap = undefined
180
181  build() {
182    Column({space: 10}) {
183      Button("获取网络图片")
184        .onClick(() => {
185          this.httpRequest()
186        })
187      Image(this.image).height(100).width(100)
188    }
189    .width('100%')
190    .height('100%')
191    .padding(10)
192  }
193
194  // 网络图片请求方法
195  private httpRequest() {
196    let httpRequest = http.createHttp()
197
198    httpRequest.request(
199      "https://www.example.com/xxx.png",   // 请填写一个具体的网络图片地址
200      (error, data) => {
201        if(error) {
202          console.log("error code: " + error.code + ", msg: " + error.message)
203        } else {
204          let code = data.responseCode
205          if(ResponseCode.ResponseCode.OK == code) {
206            let imageSource = image.createImageSource(data.result)
207            let options = {alphaType: 0,                     // 透明度
208                           editable: false,                  // 是否可编辑
209                           pixelFormat: 3,                   // 像素格式
210                           scaleMode: 1,                     // 缩略值
211                           size: {height: 100, width: 100}}  // 创建图片大小
212            imageSource.createPixelMap(options).then((pixelMap) => {
213              this.image = pixelMap
214            })
215          } else {
216            console.log("response code: " + code)
217          }
218        }
219      }
220    )
221  }
222}
223```
224
225**说明**:网络图片加载的请求方式、超时、额外请求参数等配置可以参考HTTP工具包中关于[`request()`](../../reference/apis/js-apis-http.md)请求方法的细节。
226
227### 设置属性
228
229```ts
230@Entry
231@Component
232struct ImageExample2 {
233
234  build() {
235    Column({ space: 10 }) {
236      Text('renderMode').fontSize(12).fontColor(0xcccccc).width('96%').height(30)
237      Row({ space: 50 }) {
238        Image($r('app.media.img_example'))
239          .renderMode(ImageRenderMode.Original).width(100).height(100)
240          .border({ width: 1 })
241          .overlay('Original', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
242        Image($r('app.media.img_example'))
243          .renderMode(ImageRenderMode.Template).width(100).height(100)
244          .border({ width: 1 })
245          .overlay('Template', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
246      }
247
248      Text('alt').fontSize(12).fontColor(0xcccccc).width('96%').height(30)
249      Image('')
250        .alt($r('app.media.Image_none'))
251        .width(100).height(100).border({ width: 1 })
252
253      Text('sourceSize').fontSize(12).fontColor(0xcccccc).width('96%')
254      Row({ space: 50 }) {
255        Image($r('app.media.img_example'))
256          .sourceSize({
257            width: 150,
258            height: 150
259          })
260          .objectFit(ImageFit.ScaleDown).width('25%').aspectRatio(1)
261          .border({ width: 1 })
262          .overlay('w:150 h:150', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
263        Image($r('app.media.img_example'))
264          .sourceSize({
265            width: 200,
266            height: 200
267          })
268          .objectFit(ImageFit.ScaleDown).width('25%').aspectRatio(1)
269          .border({ width: 1 })
270          .overlay('w:200 h:200', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
271      }
272
273      Text('objectRepeat').fontSize(12).fontColor(0xcccccc).width('96%').height(30)
274      Row({ space: 5 }) {
275        Image($r('app.media.ic_health_heart'))
276          .width(120).height(125).border({ width: 1 })
277          .objectRepeat(ImageRepeat.XY).objectFit(ImageFit.ScaleDown)
278          .overlay('ImageRepeat.XY', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
279        Image($r('app.media.ic_health_heart'))
280          .width(110).height(125).border({ width: 1 })
281          .objectRepeat(ImageRepeat.Y).objectFit(ImageFit.ScaleDown)
282          .overlay('ImageRepeat.Y', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
283        Image($r('app.media.ic_health_heart'))
284          .width(110).height(125).border({ width: 1 })
285          .objectRepeat(ImageRepeat.X).objectFit(ImageFit.ScaleDown)
286          .overlay('ImageRepeat.X', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
287      }
288    }.height(150).width('100%').padding({ right: 10 })
289  }
290}
291```
292
293![zh-cn_image_0000001205812616](figures/zh-cn_image_0000001205812616.png)
294
295### 事件调用
296
297```ts
298@Entry
299@Component
300struct ImageExample3 {
301  @State widthValue: number = 0
302  @State heightValue: number = 0
303  private on: Resource = $r('app.media.image_on')
304  private off: Resource = $r('app.media.image_off')
305  private on2off: Resource = $r('app.media.image_on2off')
306  private off2on: Resource = $r('app.media.image_off2on')
307  @State src: Resource = this.on
308
309  build() {
310    Column() {
311      Row({ space: 20 }) {
312        Column() {
313          Image($r('app.media.img_example1'))
314            .alt($r('app.media.ic_public_picture'))
315            .sourceSize({
316              width: 900,
317              height: 900
318            })
319            .objectFit(ImageFit.Cover)
320            .height(180).width(180)
321            // 图片加载完成后,获取图片尺寸。
322            .onComplete((msg: { width: number,height: number }) => {
323              this.widthValue = msg.width
324              this.heightValue = msg.height
325            })
326            .onError(() => {
327              console.log('load image fail')
328            })
329            .overlay('\nwidth: ' + String(this.widthValue) + ' height: ' + String(this.heightValue), {
330              align: Alignment.Bottom,
331              offset: { x: 0, y: 20 }
332            })
333        }
334        // 为图片添加点击事件,点击完成后加载特定图片。
335        Image(this.src)
336          .width(120).height(120)
337          .onClick(() => {
338            if (this.src == this.on || this.src == this.off2on) {
339              this.src = this.on2off
340            } else {
341              this.src = this.off2on
342            }
343          })
344          .onFinish(() => {
345            if (this.src == this.off2on) {
346              this.src = this.on
347            } else {
348              this.src = this.off
349            }
350          })
351      }
352    }.width('100%')
353  }
354}
355```
356
357![zh-cn_image_0000001205972610](figures/zh-cn_image_0000001205972610.gif)
358
359###  渲染沙箱路径图片
360
361```ts
362import fileio from '@ohos.fileio';
363import fs from '@ohos.file.fs';
364import context from '@ohos.app.ability.common';
365
366@Entry
367@Component
368struct LoadImageExample {
369  @State resourcesPath: string = ''
370  @State sandboxPath: string = ''
371  context: context.UIAbilityContext = getContext(this) as context.UIAbilityContext
372
373  build() {
374    Column() {
375      Button('读取沙箱图片')
376        .margin({ bottom: 10, top: 10 })
377        .onClick(() => {
378          this.sandboxPath = this.context.getApplicationContext().filesDir + '/icon.png'
379          console.log(`读取沙箱图片=========>${this.sandboxPath}`)
380          let fd = fs.openSync(this.sandboxPath, 0o100)
381          console.log(`create file========>${fd}`)
382          let srcPath = this.context.bundleCodeDir + '/entry/resources/base/media/icon.png'
383          console.log('mySrcpath' + srcPath)
384          fileio.copyFileSync(srcPath, this.sandboxPath) // 复制图片到沙箱路径
385          this.sandboxPath = 'file://' + this.context.getApplicationContext().filesDir + '/icon.png'
386        })
387      Button('读取资源图片')
388        .margin({ bottom: 10 })
389        .onClick(() => {
390          this.resourcesPath = 'file://' + this.context.bundleCodeDir + '/entry/resources/base/media/icon.png'
391        })
392      Text(`资源图片路径:${this.resourcesPath}`)
393        .fontSize(20)
394        .margin({ bottom: 10 })
395      Image(this.resourcesPath)
396        .width(100)
397        .height(100)
398        .colorFilter([
399          0.30, 0.59, 0.11, 0, 0,
400          0.30, 0.59, 0.11, 0, 0,
401          0.30, 0.59, 0.11, 0, 0,
402          0, 0, 0, 1.0, 0
403        ])
404      Text(`沙箱图片路径:${this.sandboxPath}`)
405        .fontSize(20)
406        .margin({ bottom: 10 })
407      Image(this.sandboxPath)
408        .width(100)
409        .height(100)
410    }
411    .width('100%').height('100%')
412  }
413}
414```
415