HarmonyOS鸿蒙Next中Canvas drawImage只响应一次
HarmonyOS鸿蒙Next中Canvas drawImage只响应一次
@ComponentV2
export struct ArcImageCrop {
@Local private angle: number = Math.PI
// canvas参数
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private img: image.PixelMap | null = null;
aboutToAppear(): void {
const fileUri = ProjectUtils.getCurrProjectImageUri('60')!
this.img = ImageUtils.sandBoxImageToImagePixelMap(fileUri.toString())
}
@Monitor('angle')
onAngleChange() {
if (this.context) {
LogUtils.debug("this.angle === " + this.angle)
let width = AppUtil.getUIContext().px2vp(500);
// 清空画布
this.context.clearRect(0, 0, width, width);
// 创建扇形路径
this.context.beginPath();
this.context.moveTo(width / 2, width / 2);
this.context.arc(width / 2, width / 2, width / 2, Math.PI, this.angle);
this.context.closePath();
this.context.stroke();
// 应用裁剪
this.context.clip();
// 绘制图片
this.context.drawImage(this.img, 0, 0, width, width);
}
}
build() {
RelativeContainer() {
Canvas(this.context)
.width(AppUtil.getUIContext().px2vp(500))
.height(AppUtil.getUIContext().px2vp(500))
.backgroundColor('#f0f0f0')
.onReady(() => {
this.context.strokeStyle = "rgba(255,0,0,1)";
this.context.fillStyle = "rgba(255,0,0,1)";
this.context.lineWidth = 1;
})
Button('点我')
.position({ y: -50 })
.onClick(() => {
this.angle += Math.PI / 4
})
}
.width('100%')
.height('100%')
}
}
这个代码为什么Canvas只绘制一次图片, LogUtils.debug("this.angle === " + this.angle)是有输出的
更多关于HarmonyOS鸿蒙Next中Canvas drawImage只响应一次的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者您好,clearRect方法仅能清除绘制内容,但是之前clip裁剪的路径无法清除,所以需要在每次调用onAngleChange时,需要先添加reset操作来清空画布,示例代码如下:
@Monitor('angle')
onAngleChange() {
if (this.context) {
console.info('this.angle === ' + this.angle);
let width = this.getUIContext().px2vp(500); // 重置
this.context.reset(); // 清空画布
this.context.clearRect(0, 0, width, width); // 创建扇形路径
this.context.beginPath();
this.context.moveTo(width / 2, width / 2);
this.context.arc(width / 2, width / 2, width / 2, Math.PI, this.angle);
this.context.closePath();
this.context.stroke(); // 应用裁剪
this.context.clip(); // 绘制图片
this.context.drawImage(this.img, 0, 0, width, width);
}
}
更多关于HarmonyOS鸿蒙Next中Canvas drawImage只响应一次的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,Canvas的drawImage方法只响应一次通常是由于Canvas渲染机制或状态未重置导致的。确保每次调用drawImage前,Canvas上下文已正确更新,并检查图像资源是否加载完成。避免在单次绘制周期内重复调用,或尝试使用requestAnimationFrame进行连续绘制。
问题出在Canvas的绘制状态管理上。在HarmonyOS Next的Canvas中,clip()方法会永久改变裁剪区域,导致后续绘制被限制。
你的代码中,每次onAngleChange()调用都会执行:
clearRect()清空画布- 创建新的扇形路径
clip()应用新的裁剪区域drawImage()绘制图片
但clip()是累积的,第二次调用时会在第一次的裁剪区域基础上再次裁剪,可能导致有效绘制区域为零。
解决方案:
使用save()和restore()来管理状态:
onAngleChange() {
if (this.context) {
LogUtils.debug("this.angle === " + this.angle)
let width = AppUtil.getUIContext().px2vp(500);
// 清空画布
this.context.clearRect(0, 0, width, width);
// 保存当前状态
this.context.save();
// 创建扇形路径
this.context.beginPath();
this.context.moveTo(width / 2, width / 2);
this.context.arc(width / 2, width / 2, width / 2, Math.PI, this.angle);
this.context.closePath();
this.context.stroke();
// 应用裁剪
this.context.clip();
// 绘制图片
this.context.drawImage(this.img, 0, 0, width, width);
// 恢复之前的状态,清除裁剪区域
this.context.restore();
}
}
save()会保存当前绘图状态(包括裁剪区域、变换矩阵等),restore()会恢复到这个状态,这样每次都是全新的绘制环境。
另外,确保this.img已正确加载且不为null,可以在drawImage前添加空值检查。

