问题现象

随机生成1~3中的某一个数,组合成$r('app.media.icon1')/$r('app.media.icon1')/$r('app.media.icon3'),用以显示相应的图片,使用Canvas的drawImage无法绘制出图片。

相关源码如下:

private drawImage() {
    let random: number = RandomUtil.randomNumber(1, 3)
    this.bgViweName = `app.media.icon${random}`
    ...
    const context: Context = getContext(this);
    const resourceManager: resourceManager.ResourceManager = context.resourceManager;

    resourceManager.getMediaContent($r(this.bgViweName)).then((data: Uint8Array) => {
      const buffer = data.buffer.slice(0);
      const imageSource: image.ImageSource = image.createImageSource(buffer);
      let decodingOptions: image.DecodingOptions = {
        editable: true,
        desiredPixelFormat: 3,
      }
      imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => {
        this.img = new ImageBitmap(pixelMap);
        // 绘制image
        this.drawContext.drawImage(this.img, 0, 0, PuzzleSize, PuzzleSize + BezierOffset)
      }).catch((err: BusinessError) => {
        console.error("create PixelMap error: " + err.toString())
      });
    }).catch((err: BusinessError) => {
      console.error("getMediaContent error: " + err.toString())
    })
  }

背景知识
1、image.createImageSource (uri: string): ImageSource
通过传入的uri创建图片源实例:https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/reference/apis-image-kit/js-apis-image.md#imagecreateimagesource

2、在工程中,可以通过"$r('app.type.name')"的形式引用应用资源
app代表是应用内resources目录中定义的资源;type 代表资源类型(或资源的存放位置),可以取 color、float、string、media等,name代表资源命名。

3、资源管理模块提供获取应用资源信息读取接口
其中getMediaByName接口可以获取指定资源名称对应的媒体文件内容,getMediaContent接口可以获取指定资源ID对应的媒体文件内容。

问题定位

传入固定的名称的图片,发现图片可以正常加载:

resourceManager.getMediaContent($r('app.media.icon1')).then((data:
  const buffer = data.buffer.slice(0);
  const imageSource: image.ImageSource = image.createImageSource(buffer);
  let decodingOptions: image.DecodingOptions = {
    editable: true,
    desiredPixelFormat: 3,
  }
  imageSource.createPixelMap(decodingOptions).then((pixelMap: image.PixelMap) => {
    this.img = new ImageBitmap(pixelMap);
    // 绘制image
    this.moveContext.drawImage(this.img, 0, 0, PuzzleSize, PuzzleSize + BezierOffset)
  }).catch((err: BusinessError) => {
    console.error("create PixelMap error: " + err.toString())
  });
}).catch((err: BusinessError) => {
  console.error("getMediaContent error: " + err.toString())
})

因此确认了是$r传的参数问题:如果传入的是一个变量,则加载不出来。

解决方案

方案一:使用getMediaByName替换原来的getMediaContent方法

getMediaByName的参数是字符串,因此可用于getMediaContent。

private drawImage() {
  // 获取1-3随机数
  let random: number = RandomUtil.randomNumber(1, 3);
  // 传参是名称即可,不用加app.media
  this.bgViweName = `icon${random}`
  ...

  const context: Context = getContext(this);
  const resourceManager: resourceManager.ResourceManager = context.resourceManager;

  resourceManager.getMediaByName(this.bgViweName).then((data: Uint8Array) => {
    ...
  }).catch((err: BusinessError) => {
    console.error("create PixelMap error: " + err.toString())
  });
}).catch((err: BusinessError) => {
  console.error("getMediaContent error: " + err.toString())
})

方案二:用map将图片名称和Resource建立关联

建立一个名字和Resource的map映射,从map中取出随机数生成的名称对应的Resource,传入getMediaContent方法。

// 将名称转换成resource
let viewResource = this.map.get(this.bgViweName);
resourceManager.getMediaContent(viewResource).then((data: Uint8Array) => {
  ...
}).catch((err: BusinessError) => {
  console.error("getMediaContent error: " + err.toString())
})
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐