首页
社区
课程
招聘
鸿蒙HarmonyOS实战-ArkUI组件(Image)
发表于: 2024-5-14 22:41 3826

鸿蒙HarmonyOS实战-ArkUI组件(Image)

2024-5-14 22:41
3826

????一、Image

在HarmonyOS中,Image组件是用于显示图像文件的UI组件。它可以显示本地图像文件或远程URL地址的图像文件。Image组件的实现方式比较简单,只需提供图像文件路径或URL地址即可。

Image通过调用接口来创建,接口调用形式如下:

1
Image(src: string | Resource | media.PixelMap)

该接口通过图片数据源获取图片,支持本地图片和网络图片的渲染展示。其中,src是图片的数据源

更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY

1.加载图片资源

????1.1 存档图类型数据源

☀️1.1.1 本地资源

Image组件引入本地图片路径,即可显示图片(根目录为ets文件夹)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entry
@Component
struct NavigationExample {
 
  build() {
    Column() {
      Image('1702344909275.jpg')
        .width(200)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

☀️1.1.2 网络资源

引入网络图片需申请权限ohos.permission.INTERNET,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
![image](https://img2024.cnblogs.com/blog/3365444/202404/3365444-20240416140657671-2108869509.png)
 
 
@Entry
@Component
struct NavigationExample {
 
  build() {
    Column() {
      Image('https://img1.baidu.com/it/u=3954245725,1121943782&fm=253&fmt=auto&app=120&f=JPEG?w=640&h=400')
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

☀️1.1.3 Resource资源

使用资源格式可以跨包/跨模块引入图片,resources文件夹下的图片都可以通过rr或rrawfile资源接口读取到并转换到Resource格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entry
@Component
struct NavigationExample {
 
  build() {
    Column() {
      Image($r('app.media.icon'))
 
    }
    .height('20%')
    .width('20%')
    .backgroundColor('#F1F3F5')
  }
}

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Entry
@Component
struct NavigationExample {
 
  build() {
    Column() {
      Image($rawfile('1702344909275.jpg'))
 
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

☀️1.1.4 媒体库

支持file://路径前缀的字符串,用于访问通过媒体库提供的图片路径。

1、调用接口获取图库的照片url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import picker from '@ohos.file.picker';
 
@Entry
@Component
struct Index {
  @State imgDatas: string[] = [];
  // 获取照片url集
  getAllImg() {
     
    let result = new Array<string>();
    try {
      let PhotoSelectOptions = new picker.PhotoSelectOptions();
      PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
      PhotoSelectOptions.maxSelectNumber = 5;
      let photoPicker = new picker.PhotoViewPicker();
      photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
        this.imgDatas = PhotoSelectResult.photoUris;
        console.info('PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));
      }).catch((err) => {
        console.error(`PhotoViewPicker.select failed with. Code: ${err.code}, message: ${err.message}`);
      });
    } catch (err) {
      console.error(`PhotoViewPicker failed with. Code: ${err.code}, message: ${err.message}`);    }
  }
 
  // aboutToAppear中调用上述函数,获取图库的所有图片url,存在imgDatas中
  async aboutToAppear() {
    this.getAllImg();
  }
  // 使用imgDatas的url加载图片。
  build() {
    Column() {
      Grid() {
        ForEach(this.imgDatas, item => {
          GridItem() {
            Image(item)
              .width(200)
          }
        }, item => JSON.stringify(item))
      }
    }.width('100%').height('100%')
  }
}

2、从媒体库获取的url格式通常如下

1
2
Image('file://media/Photos/5')
.width(200)
☀️1.1.5 base64

路径格式为data:image/[png|jpeg|bmp|webp];base64,[base64 data],其中[base64 data]为Base64字符串数据。

图片转换地址:https://c.runoob.com/front-end/59/
image

代码太长就不展示了,图片如下:

image

????1.2 多媒体像素图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import http from '@ohos.net.http';
import ResponseCode from '@ohos.net.http';
import image from '@ohos.multimedia.image';
@Entry
@Component
struct NavigationExample {
  @State image: PixelMap = undefined;
 
  build() {
 
    Column() {
      Button("获取网络图片")
        .onClick(() => {
          http.createHttp().request("https://img1.baidu.com/it/u=3954245725,1121943782&fm=253&fmt=auto&app=120&f=JPEG?w=640&h=400",
            (error, data) => {
              if (error){
                console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
              } else {
 
                let code = data.responseCode;
                if (ResponseCode.ResponseCode.OK === code) {
                  let res: any = data.result
                  let imageSource = image.createImageSource(res);
                  let options = {
                    alphaType: 0,                     // 透明度
                    editable: false,                  // 是否可编辑
                    pixelFormat: 3,                   // 像素格式
                    scaleMode: 1,                     // 缩略值
                    size: { height: 100, width: 100}
                  // 创建图片大小
                  imageSource.createPixelMap(options).then((pixelMap) => {
                    console.log('进不来')
                    this.image = pixelMap
                  })
                }
              }
            }
          )
        })
      Image(this.image)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

2.显示矢量图

Image组件支持显示矢量图(svg格式的图片),并且支持以下标签:svg、rect、circle、ellipse、path、line、polyline、polygon和animate。如果你想改变图片的绘制颜色,可以使用fillColor属性。

更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY

1
2
Image($r('app.media.cloud')).width(50)
.fillColor(Color.Blue)

3.添加属性

????3.1 设置图片缩放类型

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Entry
@Component
struct MyComponent {
  scroller: Scroller = new Scroller()
 
  build() {
    Scroll(this.scroller) {
      Column(){
        Row() {
          Image($r('app.media.img_2')).width(200).height(150)
            .border({ width: 1 })
            .objectFit(ImageFit.Contain).margin(15) // 保持宽高比进行缩小或者放大,使得图片完全显示在显示边界内。
            .overlay('Contain', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          Image($r('app.media.img_2')).width(200).height(150)
            .border({ width: 1 })
            .objectFit(ImageFit.Cover).margin(15)
            // 保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界。
            .overlay('Cover', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          Image($r('app.media.img_2')).width(200).height(150)
            .border({ width: 1 })
              // 自适应显示。
            .objectFit(ImageFit.Auto).margin(15)
            .overlay('Auto', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
        }
        Row() {
          Image($r('app.media.img_2')).width(200).height(150)
            .border({ width: 1 })
            .objectFit(ImageFit.Fill).margin(15)
            // 不保持宽高比进行放大缩小,使得图片充满显示边界。
            .overlay('Fill', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          Image($r('app.media.img_2')).width(200).height(150)
            .border({ width: 1 })
              // 保持宽高比显示,图片缩小或者保持不变。
            .objectFit(ImageFit.ScaleDown).margin(15)
            .overlay('ScaleDown', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          Image($r('app.media.img_2')).width(200).height(150)
            .border({ width: 1 })
              // 保持原有尺寸显示。
            .objectFit(ImageFit.None).margin(15)
            .overlay('None', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
        }
      }
    }
  }
}

image

????3.2 图片插值

图片插值(Image interpolation)是指通过计算和处理像素点之间的值,生成一个新的像素值并插入到图像中的过程。插值通常用于调整图像的大小,例如将图像从低分辨率放大到高分辨率或从高分辨率缩小到低分辨率。通过插值算法,可以在不失真或失真最小的情况下调整图像大小。常用的插值算法包括双线性插值、双三次插值等。

HarmonyOS可以使用interpolation属性对图片进行插值,使图片显示得更清晰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Entry
@Component
struct Index {
  build() {
    Column() {
      Row() {
        Image($r('app.media.img_2'))
          .width('40%')
          .interpolation(ImageInterpolation.None)
          .borderWidth(1)
          .overlay("Interpolation.None", { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          .margin(10)
        Image($r('app.media.img_2'))
          .width('40%')
          .interpolation(ImageInterpolation.Low)
          .borderWidth(1)
          .overlay("Interpolation.Low", { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          .margin(10)
      }.width('100%')
      .justifyContent(FlexAlign.Center)
 
      Row() {
        Image($r('app.media.img_2'))
          .width('40%')
          .interpolation(ImageInterpolation.Medium)
          .borderWidth(1)
          .overlay("Interpolation.Medium", { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          .margin(10)
        Image($r('app.media.img_2'))
          .width('40%')
          .interpolation(ImageInterpolation.High)
          .borderWidth(1)
          .overlay("Interpolation.High", { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
          .margin(10)
      }.width('100%')
      .justifyContent(FlexAlign.Center)
    }
    .height('100%')
  }
}

image

????3.3 设置图片重复样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Entry
@Component
struct MyComponent {
  build() {
    Column({ space: 10 }) {
      Row({ space: 5 }) {
        Image($r('app.media.icon'))
          .width(110)
          .height(115)
          .border({ width: 1 })
          .objectRepeat(ImageRepeat.XY)
          .objectFit(ImageFit.ScaleDown)
            // 在水平轴和竖直轴上同时重复绘制图片
          .overlay('ImageRepeat.XY', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
        Image($r('app.media.icon'))
          .width(110)
          .height(115)
          .border({ width: 1 })
          .objectRepeat(ImageRepeat.Y)
          .objectFit(ImageFit.ScaleDown)
            // 只在竖直轴上重复绘制图片
          .overlay('ImageRepeat.Y', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
        Image($r('app.media.icon'))
          .width(110)
          .height(115)
          .border({ width: 1 })
          .objectRepeat(ImageRepeat.X)
          .objectFit(ImageFit.ScaleDown)
            // 只在水平轴上重复绘制图片
          .overlay('ImageRepeat.X', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
      }
    }.height(150).width('100%').padding(8)
  }
}

image

????3.4 设置图片渲染模式

通过renderMode属性设置图片的渲染模式为原色或黑白。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Entry
@Component
struct MyComponent {
  build() {
    Column({ space: 10 }) {
      Row({ space: 50 }) {
        Image($r('app.media.img_2'))
          // 设置图片的渲染模式为原色
          .renderMode(ImageRenderMode.Original)
          .width(100)
          .height(100)
          .border({ width: 1 })
            // overlay是通用属性,用于在组件上显示说明文字
          .overlay('Original', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
        Image($r('app.media.img_2'))
          // 设置图片的渲染模式为黑白
          .renderMode(ImageRenderMode.Template)
          .width(100)
          .height(100)
          .border({ width: 1 })
          .overlay('Template', { align: Alignment.Bottom, offset: { x: 0, y: 20 } })
      }
    }.height(150).width('100%').padding({ top: 20,right: 10 })
  }
}

image

????3.5 设置图片解码尺寸

图片解码尺寸是指在解码后,图片的实际尺寸大小。它通常由两个值表示,即图片的宽度和高度。例如,一个图片的解码尺寸可以是 1920 x 1080,表示它的宽度为 1920 像素,高度为 1080 像素。不同的图片格式和编码方式可能会影响图片解码后的尺寸大小。

更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY

通过sourceSize属性设置图片解码尺寸,降低图片的分辨率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Entry
@Component
struct Index {
  build() {
    Column() {
      Row({ space: 20 }) {
        Image($r('app.media.img_2'))
          .sourceSize({
            width: 150,
            height: 150
          })
          .objectFit(ImageFit.ScaleDown)
          .width('25%')
          .aspectRatio(1)
          .border({ width: 1 })
          .overlay('width:150 height:150', { align: Alignment.Bottom, offset: { x: 0, y: 40 } })
        Image($r('app.media.img_2'))
          .sourceSize({
            width: 400,
            height: 400
          })
          .objectFit(ImageFit.ScaleDown)
          .width('25%')
          .aspectRatio(1)
          .border({ width: 1 })
          .overlay('width:400 height:400', { align: Alignment.Bottom, offset: { x: 0, y: 40 } })
      }.height(150).width('100%').padding(20)
 
    }
  }
}

image

????3.6 为图片添加滤镜效果

图片滤镜效果是一种对图片进行特殊处理的方式,用于改变图片的色彩、亮度、对比度、清晰度等属性,以达到特定的视觉效果。常见的图片滤镜效果包括黑白、复古、模糊、反转色等,这些效果可以通过软件或在线工具来实现。人们一般使用图片滤镜效果来增强图片的美观度或表现力,例如在社交媒体上发表照片,或将其用于艺术创作和广告设计等领域。

通过colorFilter修改图片的像素颜色,为图片添加滤镜。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Entry
@Component
struct Index {
  build() {
    Column() {
      Row() {
        Image($r('app.media.img_2'))
          .width('40%')
          .margin(10)
        Image($r('app.media.img_2'))
          .width('40%')
          .colorFilter(
            [1, 1, 0, 0, 0,
              0, 1, 0, 0, 0,
              0, 0, 1, 0, 0,
              0, 0, 0, 1, 0])
          .margin(10)
      }.width('100%')
      .justifyContent(FlexAlign.Center)
    }
  }
}

image

????3.7 同步加载图片

图片加载是应用开发非常重要的一部分,因为图片对于页面的视觉效果和用户体验非常关键。在一般情况下,浏览器会采用异步加载的方式,也就是说图片会在后台进行加载,不会影响页面的交互性能,这样页面才能更快地响应用户的操作。

然而,在某些情况下,当图片需要刷新或替换时,我们可能会遇到图片闪烁的问题。为了解决这个问题,可以使用syncLoad属性,将图片的加载方式改为同步加载,这样可以避免闪烁的出现。但是需要注意的是,这种同步加载的方式会导致图片加载时间更长,可能会影响页面的响应速度,因此不建议在图片加载较长时间的情况下使用。

除此之外,我们还可以通过其他方式来优化图片的加载效果,例如使用逐步加载的技术,或者使用图片压缩等方法来减少图片的大小和加载时间。综合考虑各种因素,对于不同的业务场景,我们需要选择合适的图片加载策略,以取得最佳的用户体验效果。

1
2
Image($r('app.media.icon'))
  .syncLoad(true)

4.事件调用

应用程序中,常常需要使用图片来展示产品、场景、用户头像等内容。我们可以通过Image组件来加载和显示图片。为了保证用户体验,我们需要在图片加载完成后获取必要的信息,并及时处理图片加载失败的情况。

通过在Image组件上绑定onComplete事件,我们可以监听图片加载完成的事件,并在回调函数中获取图片的必要信息,例如图片的宽度、高度、大小等。这些信息可以帮助我们更好地布局和显示图片,并提高应用程序的用户体验。

另外,如果图片加载失败,我们也需要及时处理这种情况,以避免出现空白或错误的页面。通过绑定onError回调函数,我们可以捕获图片加载失败的事件,并进行相应的处理。例如,可以显示一个默认的图片或者给用户一个提示信息,以告诉用户图片加载失败的原因和解决方法。

需要注意的是,为了保证应用程序的稳定性和性能,我们需要合理使用图片,避免加载过多或过大的图片。对于使用频率较高的图片,可以采用预加载的方式进行优化,提高图片加载的性能和用户体验。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Entry
@Component
struct MyComponent {
  @State widthValue: number = 0
  @State heightValue: number = 0
  @State componentWidth: number = 0
  @State componentHeight: number = 0
 
  build() {
    Column() {
      Row() {
        Image($r('app.media.img_2'))
          .width(200)
          .height(150)
          .margin(15)
          .onComplete((msg: {
            width: number,
            height: number,
            componentWidth: number,
            componentHeight: number
          }) => {
            this.widthValue = msg.width
            this.heightValue = msg.height
            this.componentWidth = msg.componentWidth
            this.componentHeight = msg.componentHeight
          })
            // 图片获取失败,打印结果
          .onError(() => {
            console.info('load image fail')
          })
          .overlay('\nwidth: ' + String(this.widthValue) + ', height: ' + String(this.heightValue) + '\ncomponentWidth: ' + String(this.componentWidth) + '\ncomponentHeight: ' + String(this.componentHeight), {
            align: Alignment.Bottom,
            offset: { x: 0, y: 60 }
          })
      }
    }
  }
}

image

????写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing????,不定期分享原创知识。
  • 更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY

image


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//