HarmonyOS鸿蒙Next中如何解决Canvas组件下设置drawImage图片没有展示的问题
HarmonyOS鸿蒙Next中如何解决Canvas组件下设置drawImage图片没有展示的问题
【问题现象】
有三张图片分别命名icon1、icon2、icon3,随机数随机生成中的某一个数,找到相应的图片,Canvas使用drawImage无法绘制出来。运行结果如下:
问题代码如下:
private drawImage() {
// 获取1-3随机数
let random: number = RandomUtil.randomNumber(1, 3)
this.bgViewName = `app.media.icon${random}`
...
const context: Context = getContext(this);
const resourceManager: resourceManager.ResourceManager = context.resourceManager;
resourceManager.getMediaContent($r(this.bgViewName)).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. Canvas画布组件
画布组件可用于自定义绘制图形。
2. 资源管理模块提供获取应用资源信息读取接口
其中getMediaByName接口可以获取指定资源名称对应的媒体文件内容,getMediaContent接口可以获取指定资源ID对应的媒体文件内容。
3. 在工程中,可以通过"$r(‘app.type.name’)"的形式引用应用资源
APP代表是应用内resources目录中定义的资源;type 代表资源类型(或资源的存放位置),可以取 color、float、string、plural和media,name代表资源命名。
【定位思路】
-
首先检查了随机数生成的图片名称是正确的,执行的过程也没报异常。
-
注释掉其他代码,传入固定的名称的图片,发现图片可以正常加载。
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.bgViewName = `icon${random}`
...
const context: Context = getContext(this);
const resourceManager: resourceManager.ResourceManager = context.resourceManager;
resourceManager.getMediaByName(this.bgViewName).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.bgViewName);
resourceManager.getMediaContent(viewResource).then((data: Uint8Array) => {
...
}).catch((err: BusinessError) => {
console.error("getMediaContent error: " + err.toString())
})
修改后效果:
【总结】
使用 $r获取Resource可以使代码更加简洁方便,但需要注意的是:虽然$r传入的参数类型是字符型的,但是由于它是在编译时处理,不支持程序运行时动态改变,因此不能传入变量。如果想要实现动态改变的要求,可以尝试在resourceManager里找到相应的方法进行替换。
更多关于HarmonyOS鸿蒙Next中如何解决Canvas组件下设置drawImage图片没有展示的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中如何解决Canvas组件下设置drawImage图片没有展示的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,Canvas组件下设置drawImage
图片没有展示的问题
可以通过以下两种方案解决:
方案一:使用getMediaByName
替换getMediaContent
方法
private drawImage() {
let random: number = RandomUtil.randomNumber(1, 3);
this.bgViewName = `icon${random}`;
const context: Context = getContext(this);
const resourceManager: resourceManager.ResourceManager = context.resourceManager;
resourceManager.getMediaByName(this.bgViewName).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);
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());
});
}
方案二:用map
将图片名称和Resource
建立关联
let viewResource = this.map.get(this.bgViewName);
resourceManager.getMediaContent(viewResource).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);
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());
});
这两种方案都可以解决drawImage
图片无法展示的问题。