鴻蒙HarmonyOS實戰-ArkUI元件(Image)

蜀道山QAQ發表於2024-04-16

🚀一、Image

在HarmonyOS中,Image元件是用於顯示影像檔案的UI元件。它可以顯示本地影像檔案或遠端URL地址的影像檔案。Image元件的實現方式比較簡單,只需提供影像檔案路徑或URL地址即可。

Image透過呼叫介面來建立,介面呼叫形式如下:

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

該介面透過圖片資料來源獲取圖片,支援本地圖片和網路圖片的渲染展示。其中,src是圖片的資料來源

🔎1.載入圖片資源

🦋1.1 存檔圖型別資料來源

☀️1.1.1 本地資源

Image元件引入本地圖片路徑,即可顯示圖片(根目錄為ets資料夾)

@Entry
@Component
struct NavigationExample {

  build() {
    Column() {
      Image('1702344909275.jpg')
        .width(200)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

☀️1.1.2 網路資源

引入網路圖片需申請許可權ohos.permission.INTERNET,

![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資料夾下的圖片都可以透過$r或$rawfile資源介面讀取到並轉換到Resource格式

@Entry
@Component
struct NavigationExample {

  build() {
    Column() {
      Image($r('app.media.icon'))

    }
    .height('20%')
    .width('20%')
    .backgroundColor('#F1F3F5')
  }
}

image

@Entry
@Component
struct NavigationExample {

  build() {
    Column() {
      Image($rawfile('1702344909275.jpg'))

    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

☀️1.1.4 媒體庫

支援file://路徑字首的字串,用於訪問透過媒體庫提供的圖片路徑。

1、呼叫介面獲取相簿的照片url

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格式通常如下

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 多媒體畫素圖

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屬性。

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

🔎3.新增屬性

🦋3.1 設定圖片縮放型別

image

@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屬性對圖片進行插值,使圖片顯示得更清晰。

@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 設定圖片重複樣式

@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屬性設定圖片的渲染模式為原色或黑白。

@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 畫素。不同的圖片格式和編碼方式可能會影響圖片解碼後的尺寸大小。

透過sourceSize屬性設定圖片解碼尺寸,降低圖片的解析度。

@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修改圖片的畫素顏色,為圖片新增濾鏡。

@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屬性,將圖片的載入方式改為同步載入,這樣可以避免閃爍的出現。但是需要注意的是,這種同步載入的方式會導致圖片載入時間更長,可能會影響頁面的響應速度,因此不建議在圖片載入較長時間的情況下使用。

除此之外,我們還可以透過其他方式來最佳化圖片的載入效果,例如使用逐步載入的技術,或者使用圖片壓縮等方法來減少圖片的大小和載入時間。綜合考慮各種因素,對於不同的業務場景,我們需要選擇合適的圖片載入策略,以取得最佳的使用者體驗效果。

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

🔎4.事件呼叫

應用程式中,常常需要使用圖片來展示產品、場景、使用者頭像等內容。我們可以透過Image元件來載入和顯示圖片。為了保證使用者體驗,我們需要在圖片載入完成後獲取必要的資訊,並及時處理圖片載入失敗的情況。

透過在Image元件上繫結onComplete事件,我們可以監聽圖片載入完成的事件,並在回撥函式中獲取圖片的必要資訊,例如圖片的寬度、高度、大小等。這些資訊可以幫助我們更好地佈局和顯示圖片,並提高應用程式的使用者體驗。

另外,如果圖片載入失敗,我們也需要及時處理這種情況,以避免出現空白或錯誤的頁面。透過繫結onError回撥函式,我們可以捕獲圖片載入失敗的事件,並進行相應的處理。例如,可以顯示一個預設的圖片或者給使用者一個提示資訊,以告訴使用者圖片載入失敗的原因和解決方法。

需要注意的是,為了保證應用程式的穩定性和效能,我們需要合理使用圖片,避免載入過多或過大的圖片。對於使用頻率較高的圖片,可以採用預載入的方式進行最佳化,提高圖片載入的效能和使用者體驗。

@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

相關文章