手把手教你玩转 HarmonyOS 中的 Canvas 组件:从入门到实战
咱们开发者在开发 HarmonyOS 应用时,经常会遇到需要自定义绘制图形的需求,这时候 Canvas 组件就派上大用场啦。今天我就带着大家深入了解一下这个超实用的组件,从基础概念到代码实战,保证让你一看就懂、一学就会!
一、Canvas 组件到底是啥?能干啥?
简单来说,Canvas 组件就是 HarmonyOS 给咱们提供的一块 “画布”,咱们可以在上面自由绘制各种图形、文字,甚至进行 AI 图像分析。它从 API version 8 开始支持,后续版本还不断增加了新功能,像 API 12 + 就加入了 AI 分析相关的能力。
重点总结:
- 核心功能:提供自定义绘制图形的画布,支持 2D 绘图和 AI 图像分析(API 12+)。
- 设备支持:手机、PC/2in1、平板、穿戴设备都能用。
- 子组件:不支持嵌套子组件,只能单独使用。
代码示例(基础画布创建):
@Entry
@Component
struct CanvasBasicExample {
build() {
// 创建一个占满屏幕的Canvas
Canvas()
.width('100%')
.height('100%')
.backgroundColor('#f0f0f0') // 设置画布背景色
}
}
这段代码就是创建了一个最简单的 Canvas,背景是浅灰色,占满整个屏幕。不过现在它还是空的,接下来咱们就来看看怎么在上面画画。
二、Canvas 接口详解:怎么初始化画布?
Canvas 组件有两种初始化方式,根据不同的 API 版本和需求来选择。
1. 基础接口(API 8+)
Canvas(context?: CanvasRenderingContext2D | DrawingRenderingContext)
- 参数说明:context 可选,类型可以是 2D 渲染上下文或绘图上下文。
- 注意事项:多个 Canvas 不能共用一个 context 对象,每个 Canvas 最好有自己的上下文。
2. 增强接口(API 12+)
Canvas(context: CanvasRenderingContext2D | DrawingRenderingContext, imageAIOptions: ImageAIOptions)
- 新增参数:imageAIOptions,用于配置 AI 分析选项,比如设置分析类型或绑定控制器。
- 适用场景:需要使用 AI 图像分析功能时使用这个接口。
重点总结:
- 选择建议:单纯绘图用基础接口,需要 AI 分析用增强接口。
- context 创建:通常在组件内部创建 context 对象,保证每个 Canvas 独立。
代码示例(初始化带 context 的 Canvas):
@Entry
@Component
struct CanvasWithContextExample {
// 创建2D渲染上下文
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context2D: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
// 创建绘图上下文(API 12+)
private contextDrawing: DrawingRenderingContext = new DrawingRenderingContext();
build() {
Flex({ direction: FlexDirection.Column }) {
// 使用2D上下文的Canvas
Text('2D渲染上下文画布')
.fontSize(16)
.margin(10)
Canvas(this.context2D)
.width('100%')
.height(200)
.backgroundColor('#e0e0e0')
// 使用绘图上下文的Canvas(需要API 12+)
Text('绘图上下文画布')
.fontSize(16)
.margin(10)
Canvas(this.contextDrawing)
.width('100%')
.height(200)
.backgroundColor('#e0e0e0')
}
.width('100%')
.padding(10)
}
}
这里创建了两个 Canvas,分别使用不同的上下文,注意绘图上下文(DrawingRenderingContext)是 API 12 + 才支持的哦。
三、Canvas 属性:怎么给画布加功能?
除了通用属性外,Canvas 还有一个特别的属性 ——enableAnalyzer,这是 API 12 + 新增的 AI 分析功能。
enableAnalyzer 属性
enableAnalyzer({ enable: boolean })
- 作用:开启 Canvas 的 AI 分析功能,支持主体识别、文字识别、对象查找等。
- 使用条件:需要搭配 CanvasRenderingContext2D 中的 startImageAnalyzer 和 stopImageAnalyzer 方法一起用。
- 注意事项:不能和 overlay 属性同时使用,否则 overlay 会失效。
重点总结:
- 开启 AI 分析:设置 enable 为 true,默认是 false。
- 配套方法:必须调用 start 和 stop 方法来控制分析过程。
- 设备依赖:该功能依赖设备能力,有些设备可能不支持。
代码示例(开启 AI 分析功能):
@Entry
@Component
struct CanvasAIAnalyzerExample {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private config: ImageAnalyzerConfig = {
types: [ImageAnalyzerType.SUBJECT, ImageAnalyzerType.TEXT] // 分析主体和文字
}
private aiController: ImageAnalyzerController = new ImageAnalyzerController();
build() {
Column() {
// 控制按钮
Row() {
Button('开始分析')
.onClick(() => {
this.context.startImageAnalyzer(this.config)
.then(() => console.log('分析完成'))
.catch((error) => console.log('分析错误:', error));
})
Button('停止分析')
.onClick(() => this.context.stopImageAnalyzer())
}
.margin(10)
// 开启AI分析的Canvas
Canvas(this.context)
.width(300)
.height(200)
.backgroundColor('#f5f5f5')
.enableAnalyzer({ enable: true }) // 开启AI分析
.onReady(() => {
// 画布准备好后绘制内容
this.context.fillStyle = '#007DFF';
this.context.fillRect(50, 50, 200, 100);
})
}
.width('100%')
.padding(10)
}
}
这个示例中,Canvas 开启了 AI 分析功能,点击按钮可以控制分析的开始和停止,配置了分析主体和文字两种类型。
四、Canvas 事件:怎么知道画布准备好了?
Canvas 有一个很重要的事件 ——onReady,用来监听画布初始化完成或大小变化。
onReady 事件
onReady(event: VoidCallback)
- 触发时机:Canvas 初始化完成或大小变化时触发,触发后画布会被清空。
- 使用场景:在这个事件回调里进行绘制操作,因为此时画布宽高确定,可以安全获取。
- 注意事项:位置变化不会触发 onReady,只会触发 onAreaChange 事件,且 onAreaChange 在 onReady 之后触发。
重点总结:
- 绘制时机:onReady 回调是进行绘制的最佳时机。
- 事件顺序:先 onReady,再 onAreaChange(如果有大小变化)。
- 避免重复绘制:注意处理多次触发的情况,比如大小变化时可能需要重新绘制。
代码示例(使用 onReady 事件绘制图形):
@Entry
@Component
struct CanvasOnReadyExample {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
// 自适应屏幕的Canvas
Canvas(this.context)
.width('90%')
.height(300)
.backgroundColor('#f9f9f9')
.onReady(() => {
console.log('画布准备好了,开始绘制...');
// 绘制一个红色圆形
this.context.fillStyle = 'red';
this.context.beginPath();
this.context.arc(150, 150, 100, 0, 2 * Math.PI);
this.context.fill();
// 绘制文字
this.context.fillStyle = 'white';
this.context.font = '20px Arial';
this.context.textAlign = 'center';
this.context.fillText('Hello Canvas!', 150, 150);
})
}
}
在 onReady 回调里,我们绘制了一个红色圆形和白色文字,这时候画布的宽高已经确定,不用担心绘制位置错误。
五、实战示例:三种常见用法场景
光看概念可能有点抽象,接下来咱们通过三个实战示例,看看 Canvas 在不同场景下怎么用。
示例 1:使用 CanvasRenderingContext2D 绘制基础图形
这个示例展示了最常用的 2D 绘图上下文的用法,适合绘制矩形、圆形、线条等基础图形。
@Entry
@Component
struct Canvas2DExample {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
Canvas(this.context)
.width('90%')
.height(400)
.backgroundColor('#f0f8ff') // 浅蓝色背景
.onReady(() => {
// 绘制多个图形
this.drawShapes();
})
}
.width('100%')
.padding(20)
}
// 绘制各种图形的方法
drawShapes() {
// 绘制矩形
this.context.fillStyle = '#FFD700'; // 金色
this.context.fillRect(50, 50, 100, 80); // 填充矩形
// 绘制带边框的矩形
this.context.strokeStyle = '#0000FF'; // 蓝色
this.context.lineWidth = 3;
this.context.strokeRect(200, 50, 100, 80); // 描边矩形
// 绘制圆形
this.context.fillStyle = '#FF69B4'; // 粉色
this.context.beginPath();
this.context.arc(125, 200, 50, 0, 2 * Math.PI);
this.context.fill();
// 绘制圆弧
this.context.strokeStyle = '#228B22'; // 绿色
this.context.lineWidth = 4;
this.context.beginPath();
this.context.arc(275, 200, 50, 0, Math.PI); // 半圆弧
this.context.stroke();
// 绘制线条
this.context.strokeStyle = '#8B0000'; // 棕色
this.context.lineWidth = 2;
this.context.beginPath();
this.context.moveTo(50, 300);
this.context.lineTo(300, 300);
this.context.stroke();
// 绘制贝塞尔曲线
this.context.strokeStyle = '#000000'; // 黑色
this.context.lineWidth = 3;
this.context.beginPath();
this.context.moveTo(50, 350);
this.context.quadraticCurveTo(175, 400, 300, 350);
this.context.stroke();
}
}
这个示例中,我们在 onReady 事件里调用了 drawShapes 方法,绘制了矩形、圆形、线条、贝塞尔曲线等多种图形,还设置了不同的颜色和线条宽度,是不是很直观?
示例 2:使用 DrawingRenderingContext 绘制图形(API 12+)
DrawingRenderingContext 是 API 12 + 新增的绘图上下文,用法和 CanvasRenderingContext2D 有点不同,咱们来看示例:
@Entry
@Component
struct CanvasDrawingExample {
private context: DrawingRenderingContext = new DrawingRenderingContext();
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
Text('API 12+绘图上下文示例')
.fontSize(18)
.margin(10)
Canvas(this.context)
.width('90%')
.height(300)
.backgroundColor('#e6e6fa') // 淡紫色背景
.onReady(() => {
// 使用DrawingRenderingContext绘制
this.drawWithDrawingContext();
})
}
.width('100%')
.padding(20)
}
drawWithDrawingContext() {
// 获取画布对象
const canvas = this.context.canvas;
// 绘制蓝色圆形
canvas.drawCircle(150, 150, 80, {
fill: { color: '#1E90FF' }
});
// 绘制红色矩形
canvas.drawRect({ x: 50, y: 50, width: 100, height: 80 }, {
stroke: { color: '#FF0000', width: 3 }
});
// 绘制绿色文字
canvas.drawText('DrawingContext示例', { x: 50, y: 250 }, {
font: { size: 16, family: 'Arial' },
fill: { color: '#008000' }
});
// 刷新画布
this.context.invalidate();
}
}
这里使用了 DrawingRenderingContext,它的绘制方式更面向对象一些,通过 canvas 对象的 drawCircle、drawRect 等方法来绘制,最后需要调用 invalidate () 来刷新画布。注意这个示例需要 API 12 + 哦。
示例 3:使用 attributeModifier 动态设置 Canvas 属性
有时候咱们需要动态修改 Canvas 的属性和方法,这时候 attributeModifier 就派上用场了,来看示例:
import { BusinessError } from '@ohos.basicServices'; // 假设引入方式正确
// 自定义属性修饰器
class MyCanvasModifier implements AttributeModifier<CanvasAttribute> {
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D();
// 应用普通属性
applyNormalAttribute(instance: CanvasAttribute): void {
// 设置onReady事件,绘制图片
instance.onReady(() => {
// 这里假设image.png存在,实际使用时需要正确路径
let image = new ImageBitmap('image.png');
image.then((bitmap) => {
this.context.drawImage(bitmap, 0, 0, 200, 200);
});
});
// 开启AI分析功能
instance.enableAnalyzer({ enable: true });
}
// 设置上下文
setContext(context: CanvasRenderingContext2D) {
this.context = context;
}
}
@Entry
@Component
struct CanvasAttributeModifierExample {
@State modifier: MyCanvasModifier = new MyCanvasModifier();
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private config: ImageAnalyzerConfig = {
types: [ImageAnalyzerType.SUBJECT, ImageAnalyzerType.TEXT]
}
private aiController: ImageAnalyzerController = new ImageAnalyzerController();
private options: ImageAIOptions = {
types: [ImageAnalyzerType.SUBJECT, ImageAnalyzerType.TEXT],
aiController: this.aiController
}
build() {
Column() {
// 控制按钮
Row() {
Button('开始分析')
.width(100)
.onClick(() => {
this.context.startImageAnalyzer(this.config)
.then(() => console.log('分析完成'))
.catch((error: BusinessError) => {
console.log('错误码:', error.code);
});
})
Button('停止分析')
.width(100)
.onClick(() => this.context.stopImageAnalyzer())
Button('获取支持类型')
.width(120)
.onClick(() => {
this.aiController.getImageAnalyzerSupportTypes()
.then((types) => console.log('支持的分析类型:', types))
.catch((error) => console.log('获取类型错误:', error));
})
}
.margin(10)
// 使用属性修饰器的Canvas
Canvas(this.context, this.options)
.width(250)
.height(250)
.borderWidth(1)
.attributeModifier(this.modifier) // 应用属性修饰器
.onAppear(() => {
// 组件出现时设置上下文
this.modifier.setContext(this.context);
})
}
.width('100%')
.padding(20)
}
}
这个示例中,我们创建了一个自定义的属性修饰器 MyCanvasModifier,在里面动态设置 onReady 事件和 enableAnalyzer 属性,还可以通过按钮控制 AI 分析的过程,非常灵活。
六、使用 Canvas 的注意事项
最后咱们来总结一下使用 Canvas 时需要注意的点,避免踩坑:
- context 唯一性:多个 Canvas 不能共用一个 context 对象,每个 Canvas 都要有自己的上下文,否则会出问题。
- API 版本:注意不同功能的 API 版本要求,比如 DrawingRenderingContext 和 enableAnalyzer 都是 API 12 + 才支持的。
- 绘制时机:尽量在 onReady 事件里进行绘制,确保画布宽高已确定。
- AI 分析限制:enableAnalyzer 不能和 overlay 属性同时使用,否则 overlay 会失效。
- 设备能力:AI 分析功能依赖设备能力,有些设备可能不支持,需要做好兼容性处理。
- 性能优化:频繁绘制时注意性能,避免过多重绘影响应用流畅度。
结语
好了,关于 HarmonyOS 中的 Canvas 组件,咱们从概念到实战都过了一遍,相信大家已经对它有了比较清晰的认识。无论是绘制基础图形,还是使用 AI 分析功能,Canvas 都能满足咱们的需求。赶紧动手试试吧,在实际开发中多练习,很快就能熟练掌握啦!如果遇到问题,别忘了回头看看这些示例和注意事项哦~
更多推荐

所有评论(0)