HarmonyOS鸿蒙Next中想要把图片画满Canvas,需要怎么设置drawImage的参数
HarmonyOS鸿蒙Next中想要把图片画满Canvas,需要怎么设置drawImage的参数
想要在canvas上绘制网络图片,但是绘制的图片没有撑满Canvas, api16, 请赐教
// TestPage.ets
import { util } from '@kit.ArkTS';
import { image } from '@kit.ImageKit';
async function loadImageToBitmap(url: string): Promise<ImageBitmap> {
// 1. 发起网络请求获取图片数据
const httpRequest = http.createHttp();
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
expectDataType: http.HttpDataType.ARRAY_BUFFER // 接收二进制数据
});
// 2. 获取二进制数据
const arrayBuffer = response.result as ArrayBuffer;
if (!arrayBuffer) {
throw new Error('Failed to download image');
}
// 3. 创建 ImageSource 对象并解码为 PixelMap
const imageSource = image.createImageSource(arrayBuffer);
const pixelMap: PixelMap = await imageSource.createPixelMap();
pixelMap.getImageInfo().then(res => {
console.log("pixel imageInfo: ", JSON.stringify(res.size))
})
// 4. 将 PixelMap 转换为 ImageBitmap
const imageBitmap: ImageBitmap = new ImageBitmap(pixelMap)
return imageBitmap;
}
const imageUrl = 'https://img2.baidu.com/it/u=3826169544,1465685839&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1309'
const COMPONENT_WIDTH = 600;
const COMPONENT_HEIGHT = 400;
@ObservedV2
class Pos {
@Trace
x: number = 0;
@Trace
y: number = 0;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
@Entry
@ComponentV2
struct Sliver {
@Local startPos: Pos = new Pos(10, 50); // 移动方块起始点
@Local targetPos: Pos = new Pos(130, 50)
@Local x: number = 0;
@Local intervalId: number = -1;
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
@Local outSetValueOne: number = 0;
@Local message: string = 'Base64ToPixelMap';
@Local private pixelMap: PixelMap | null = null;
private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600)
init = async () => {
try {
const res = await loadImageToBitmap(imageUrl)
let offContext: OffscreenCanvasRenderingContext2D = this.offCanvas.getContext("2d", this.settings)
offContext.save() // save the default state
// 绘制底图
offContext.drawImage(res,
0, 0, COMPONENT_WIDTH, COMPONENT_HEIGHT /COMPONENT_WIDTH *(COMPONENT_WIDTH),
0, 0, COMPONENT_WIDTH, COMPONENT_HEIGHT,
)
let image = this.offCanvas.transferToImageBitmap()
this.context.transferFromImageBitmap(image)
res.close()
} catch (e) {
console.log('draw sliver fail: ', e.message)
}
}
aboutToAppear(): void {
this.init()
}
build() {
Row({space: 50}) {
Image(imageUrl).width(300)
Column() {
RelativeContainer() {
Canvas(this.context)
.width(600)
.height(400)
.backgroundColor('#aaff00')
}
.width(COMPONENT_WIDTH).height(COMPONENT_HEIGHT)
.backgroundColor(Color.Blue)
}
// .width(700)
.alignItems(HorizontalAlign.Start)
}.width('100%').justifyContent(FlexAlign.Center)
}
}
更多关于HarmonyOS鸿蒙Next中想要把图片画满Canvas,需要怎么设置drawImage的参数的实战教程也可以访问 https://www.itying.com/category-93-b0.html
设置图片宽高和画布宽高一致就可以将图片铺满画布:
// 设置图片宽为canvas_width,设置图片高为canvas_heith
this.contextFull.drawImage(pixelMap, 0, 0, canvas_width, canvas_heith * 2, 0, 0, canvas_width, canvas_heith)
Canvas(this.context)
.backgroundColor('#F5DC62')
.onReady(() => {
this.drawImage()
})
.width(canvas_width) // 设置画布宽为canvas_width
.height(canvas_heith) // 设置画布高为canvas_heith
完整demo如下:
import { resourceManager } from '@kit.LocalizationKit'
import { image } from '@kit.ImageKit'
const canvas_width = 400
const canvas_heith = canvas_width / 2
@Entry
@Component
export struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
private contextFull: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
async drawImage() {
// 获取资源管理器实例
const resourceMgr: resourceManager.ResourceManager = getContext(this).resourceManager
// 获取媒体内容(这里是启动图标)
const fileData: Uint8Array = await resourceMgr.getMediaContent($r('app.media.startIcon'))
// 将文件数据转换为缓冲区
const buffer = fileData.buffer
// 创建图像源对象
const imageSource: image.ImageSource = image.createImageSource(buffer)
// 设置解码选项
let opts: image.DecodingOptions = {
// 是否可编辑
editable: true,
// 目标大小
desiredSize: {
height: 400,
width: 400
}
};
// 创建像素映射对象
const pixelMap: image.PixelMap = await imageSource.createPixelMap(opts)
// 在画布上绘制图像
this.context.drawImage(pixelMap, 100, 0)
// 设置图片铺满画布
this.contextFull.drawImage(pixelMap, 0, 0, canvas_width, canvas_heith * 2, 0, 0, canvas_width, canvas_heith)
}
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
Canvas(this.context)
.backgroundColor('#F5DC62')
.height('30%')
Row().height('30%')
Canvas(this.contextFull)
.backgroundColor('#F5DC62')
.onReady(() => {
this.drawImage()
})
.width(canvas_width)
.height(canvas_heith)
}
}
}
更多关于HarmonyOS鸿蒙Next中想要把图片画满Canvas,需要怎么设置drawImage的参数的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,要将图片画满Canvas,使用drawImage
方法时需设置目标绘制区域参数。具体参数为:drawImage(image, 0, 0, canvas.width, canvas.height)
。其中image
为图片资源对象,后四个参数分别表示目标绘制的起始坐标(0,0)和结束坐标(canvas的宽高)。这样设置会拉伸图片至Canvas的完整尺寸。需确保图片已加载完成再调用绘制。
在HarmonyOS Next中,要让图片填满Canvas,需要正确设置drawImage
方法的参数。根据你的代码,问题出在drawImage
的源矩形参数计算上。
修改建议:
- 获取图片的实际宽高信息
- 使用正确的宽高比计算来填充Canvas
修正后的drawImage
调用应该是:
// 先获取图片信息
const imageInfo = await res.getImageInfo();
const imgWidth = imageInfo.size.width;
const imgHeight = imageInfo.size.height;
// 计算适合Canvas的缩放比例
const scale = Math.max(COMPONENT_WIDTH/imgWidth, COMPONENT_HEIGHT/imgHeight);
// 绘制图片填满Canvas
offContext.drawImage(
res,
0, 0, imgWidth, imgHeight, // 源图区域
0, 0, COMPONENT_WIDTH, COMPONENT_HEIGHT // 目标Canvas区域
);
关键点:
- 使用
getImageInfo()
获取图片原始尺寸 drawImage
后四个参数直接使用Canvas的宽高(COMPONENT_WIDTH/HEIGHT
)- 这样会自动进行缩放填充整个Canvas区域
注意:这种方式会保持图片原始比例,如果图片比例与Canvas不一致,会有部分内容被裁剪。如果需要完全填充不保持比例,可以分别设置宽高缩放。