3、Canvas 2D绘图基础:Canvas组件入门、绘制基本图形(矩形、圆形、线条)、设置样式与颜色。
好,咱们开始聊Canvas 2D绘图。说实话,鸿蒙的Canvas组件,是我个人觉得整个图形渲染体系里最亲切的一块。为什么?因为它上手快,反馈直接。你写几行代码,屏幕上立刻就能看到图形,这种成就感,是搞底层渲染给不了的。
我记得我刚接触鸿蒙开发那会儿,第一个练手的项目就是拿Canvas画一个简单的仪表盘。虽然现在回头看那代码写得挺糙的,但当时看着指针动起来,心里确实挺爽。今天咱们就从最基础的开始,一步步把Canvas玩明白。
3.1 Canvas组件入门
在鸿蒙里,Canvas不是一个“画板”概念,它就是一个实实在在的组件。你需要在布局文件里声明它,然后在代码里拿到它的画笔,才能开始画。
说白了,Canvas组件就是一块画布,而画笔是它的灵魂。没有画笔,Canvas就是一块空白的区域,啥也干不了。
咱们先看怎么在布局里放一个Canvas组件。以ArkUI的声明式语法为例,代码非常简洁:
@Entry
@Component
struct CanvasExample {
build() {
Column() {
Canvas(this.context)
.width('100%')
.height('300px')
.backgroundColor('#F5F5F5')
}
.width('100%')
.height('100%')
}
}
这里有个关键点——this.context。这个context就是Canvas的绘图上下文,所有绘图操作都得通过它来完成。你想想看,没有context,你连画一条线都做不到。
3.2 绘制基本图形
好,画布有了,画笔也有了,咱们开始画点东西。先从最基础的三个图形说起:矩形、圆形、线条。这三个图形,几乎能组合出你见过的所有2D界面。
3.2.1 绘制矩形
矩形是Canvas里最简单的图形。你只需要告诉它四个参数:左上角的x坐标、y坐标、宽度、高度。代码长这样:
// 绘制一个填充矩形
this.context.fillRect(50, 50, 200, 100);
// 绘制一个描边矩形
this.context.strokeRect(50, 200, 200, 100);
这里fillRect画的是实心矩形,strokeRect画的是空心矩形。我在项目中遇到过一个问题:有次画矩形时,发现矩形位置总是不对,后来一查,原来是坐标原点理解错了。鸿蒙Canvas的坐标原点默认在左上角,x轴向右,y轴向下。这个和数学里的坐标系不太一样,刚接触时容易搞混。
3.2.2 绘制圆形
画圆形稍微复杂一点,因为它用的是路径(Path)的方式。你需要先开始一条路径,然后画一个圆弧,最后关闭路径。看代码:
// 开始路径
this.context.beginPath();
// 画一个圆弧(圆形其实就是360度的圆弧)
// 参数:圆心x, 圆心y, 半径, 起始角度, 结束角度
this.context.arc(150, 150, 80, 0, Math.PI * 2);
// 关闭路径
this.context.closePath();
// 填充或描边
this.context.fill();
// 或者 this.context.stroke();
嗯,这里要注意一点:arc方法里的角度用的是弧度制,不是角度制。360度对应的是Math.PI * 2。我曾经见过有同事直接传了360进去,结果画出来的不是圆,而是一个奇怪的扇形。所以这个细节一定要记住。
3.2.3 绘制线条
线条就更直接了。你只需要指定起点和终点,然后调用stroke方法。但线条的绘制也遵循路径的规则:
// 开始路径
this.context.beginPath();
// 移动到起点
this.context.moveTo(50, 50);
// 画线到终点
this.context.lineTo(250, 150);
// 描边
this.context.stroke();
如果你想画一条折线,那就多调用几次lineTo。比如画一个三角形:
this.context.beginPath();
this.context.moveTo(100, 100);
this.context.lineTo(200, 100);
this.context.lineTo(150, 200);
this.context.closePath(); // 自动闭合到起点
this.context.stroke();
3.3 设置样式与颜色
图形画出来了,但都是默认的黑色,太单调了。咱们得给它上点颜色,加点样式。Canvas提供了几个属性来控制这些:
| 属性名 | 作用 | 示例值 |
|---|---|---|
| fillStyle | 设置填充颜色 | '#FF0000'、'rgb(255,0,0)' |
| strokeStyle | 设置描边颜色 | '#00FF00'、'rgba(0,255,0,0.5)' |
| lineWidth | 设置线条宽度 | 5(单位是像素) |
| lineCap | 设置线条端点样式 | 'butt'、'round'、'square' |
| lineJoin | 设置线条交点样式 | 'miter'、'round'、'bevel' |
咱们来一个综合的例子,把前面学的都串起来:
// 设置填充颜色为蓝色,半透明
this.context.fillStyle = 'rgba(0, 0, 255, 0.3)';
// 设置描边颜色为红色,线宽为3像素
this.context.strokeStyle = '#FF0000';
this.context.lineWidth = 3;
// 画一个填充矩形
this.context.fillRect(30, 30, 100, 100);
// 画一个描边圆形
this.context.beginPath();
this.context.arc(200, 80, 50, 0, Math.PI * 2);
this.context.stroke();
// 画一条粗线
this.context.beginPath();
this.context.moveTo(30, 200);
this.context.lineTo(300, 200);
this.context.lineWidth = 8;
this.context.strokeStyle = '#00FF00';
this.context.stroke();
你看,通过改变fillStyle和strokeStyle,我们可以轻松控制图形的颜色。而且这些样式是“有状态的”——你设置一次,后续所有绘制都会沿用这个样式,直到你再次修改它。
3.4 实战小练习:画一个简单的笑脸
光说不练假把式。咱们用刚学的知识,画一个简单的笑脸。这个例子能帮你巩固矩形、圆形、线条以及样式的使用:
// 1. 画脸(一个大圆形)
this.context.beginPath();
this.context.arc(150, 150, 100, 0, Math.PI * 2);
this.context.fillStyle = '#FFD700'; // 金色
this.context.fill();
this.context.strokeStyle = '#333';
this.context.lineWidth = 3;
this.context.stroke();
// 2. 画眼睛(两个小圆形)
this.context.beginPath();
this.context.arc(110, 120, 15, 0, Math.PI * 2);
this.context.fillStyle = '#333';
this.context.fill();
this.context.beginPath();
this.context.arc(190, 120, 15, 0, Math.PI * 2);
this.context.fill();
// 3. 画嘴巴(一条弧线)
this.context.beginPath();
this.context.arc(150, 150, 60, 0.2 * Math.PI, 0.8 * Math.PI);
this.context.strokeStyle = '#333';
this.context.lineWidth = 4;
this.context.stroke();
这个笑脸画出来,虽然简单,但已经包含了Canvas绘制的核心流程:路径、样式、绘制。你想想看,如果把这个思路延伸一下,画一个复杂的仪表盘、一个游戏界面,甚至一个简单的绘图工具,是不是都基于同样的原理?
好,Canvas 2D绘图的基础就聊到这儿。下一节咱们会深入聊一聊路径的高级操作和渐变填充,到时候你会发现,原来Canvas能做的事情远比想象中多得多。