鸿蒙开发 一 (八)、自定义绘制
·
做过Android开发的同学对View的自定义绘制应该多少都有点了解,那么再接触鸿蒙的自定义绘制就好上手了。
工具介绍
在Android中常用的工具,和画笔
画布:Canvas
画笔:Paint
在鸿蒙中其实也是这样:
画布:Canvas
画笔:CanvasRenderingContext2D 和 OffscreenCanvasRenderingContext2D
那么这两个画笔有什么区别呢?
- CanvasRenderingContext2D 使用CanvasRenderingContext2D对象在Canvas画布上绘制。
-
OffscreenCanvasRenderingContext2D :离屏绘制,是指将需要绘制的内容先绘制在缓存区,再将其转换成图片,一次性绘制到Canvas上,加快了绘制速度。过程为:
- 通过transferToImageBitmap方法将离屏画布最近渲染的图像创建为一个ImageBitmap对象。
- 通过CanvasRenderingContext2D对象的transferFromImageBitmap方法显示给定的ImageBitmap对象。
常用的方法
//常用方法:
fill() //(对封闭路径进行填充)
stroke() //(进行边框绘制操作)
clip() //(设置当前路径为剪切路径)
fillStyle() //(指定绘制的填充色)
globalAlpha() //(设置透明度)
strokeStyle() //(设置描边的颜色)等属性修改绘制内容的样式
fillText() //(文本填充
strokeText() //(文本描边)
arc() //(绘制弧线路径
ellipse() //(绘制一个椭圆)
rect() //(创建矩形路径)
drawImage() //(图像绘制)
putImageData() //(使用ImageData数据填充新的矩形区域)
createImageData() //(创建新的ImageData 对象
getPixelMap() //(以当前canvas指定区域内的像素创建PixelMap对象
getImageData() //(以当前canvas指定区域内的像素创建ImageData对象
createLinearGradient() //(创建一个线性渐变色)
createRadialGradient() //(创建一个径向渐变色)
代码示例
接下来用一个小例子帮大家熟悉一下鸿蒙的自定义绘制
@ComponentV2
export struct DemoPage {
// 配置渲染上下文设置,开启抗锯齿
private settings: RenderingContextSettings = new RenderingContextSettings(true);
// 创建 2D 渲染上下文
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
// 创建路径对象,用于复杂图形绘制
private path: Path2D = new Path2D();
// 动态文本内容
@Local text: string = 'ArkTS Canvas';
aboutToAppear(): void {
// 预先定义一个路径,将在 onReady 中使用
this.path.arc(150, 500, 50, 0, Math.PI * 2);
}
build() {
Column() {
// 标题
Text("Canvas API 演示")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// Canvas 绘制区域
Canvas(this.context)
.width('100%')
.height('80%')
.backgroundColor('#f5f5f5')
.onReady(() => {
this.drawScene();
})
}
.width('100%')
.height('100%')
.padding(20)
}
// 绘制整个场景
private drawScene(): void {
// 清空画布
this.context.clearRect(0, 0, 1000, 1000);
// 1. 绘制背景 - 使用径向渐变
this.drawBackground();
// 2. 绘制太阳 - 使用圆形和径向渐变
this.drawSun();
// 3. 绘制房子 - 使用矩形和路径
this.drawHouse();
// 4. 绘制树 - 使用路径和填充
this.drawTree();
// 5. 绘制文本 - 使用填充文本和描边文本
this.drawTexts();
// 6. 使用预定义路径绘制一个圆
this.context.fillStyle = '#3366CC';
this.context.fill(this.path);
this.context.strokeStyle = '#000000';
this.context.lineWidth = 2;
this.context.stroke(this.path);
}
// 绘制渐变背景
private drawBackground(): void {
// 创建线性渐变 - 从顶部到底部
let skyGradient = this.context.createLinearGradient(0, 0, 0, 600);
skyGradient.addColorStop(0.0, '#87CEEB'); // 天空蓝
skyGradient.addColorStop(0.7, '#E0F7FA'); // 浅蓝
skyGradient.addColorStop(1.0, '#81C784'); // 草地绿
// 填充背景
this.context.fillStyle = skyGradient;
this.context.fillRect(0, 0, 1000, 600);
}
// 绘制太阳
private drawSun(): void {
// 创建径向渐变
let sunGradient = this.context.createRadialGradient(100, 100, 10, 100, 100, 50);
sunGradient.addColorStop(0.0, '#FFEB3B'); // 亮黄色
sunGradient.addColorStop(1.0, '#FF9800'); // 橙色
// 绘制太阳圆形
this.context.beginPath();
this.context.arc(100, 100, 50, 0, Math.PI * 2);
this.context.fillStyle = sunGradient;
this.context.fill();
// 绘制太阳光芒
this.context.strokeStyle = '#FFEB3B';
this.context.lineWidth = 3;
for (let i = 0; i < 12; i++) {
const angle = (Math.PI / 6) * i;
this.context.beginPath();
this.context.moveTo(100 + Math.cos(angle) * 50, 100 + Math.sin(angle) * 50);
this.context.lineTo(100 + Math.cos(angle) * 70, 100 + Math.sin(angle) * 70);
this.context.stroke();
}
}
// 绘制房子
private drawHouse(): void {
// 房子主体 - 矩形
this.context.fillStyle = '#795548';
this.context.fillRect(300, 300, 200, 150);
// 房顶 - 路径
this.context.beginPath();
this.context.moveTo(300, 300);
this.context.lineTo(400, 220);
this.context.lineTo(500, 300);
this.context.closePath();
this.context.fillStyle = '#D32F2F';
this.context.fill();
// 门 - 矩形
this.context.fillStyle = '#5D4037';
this.context.fillRect(375, 375, 50, 75);
// 窗户 - 矩形和清除区域
this.context.fillStyle = '#90CAF9';
this.context.fillRect(325, 325, 50, 50);
this.context.fillRect(425, 325, 50, 50);
// 窗户框架
this.context.strokeStyle = '#000000';
this.context.lineWidth = 2;
this.context.strokeRect(325, 325, 50, 50);
this.context.strokeRect(425, 325, 50, 50);
// 窗户十字架
this.context.beginPath();
this.context.moveTo(350, 325);
this.context.lineTo(350, 375);
this.context.moveTo(325, 350);
this.context.lineTo(375, 350);
this.context.moveTo(450, 325);
this.context.lineTo(450, 375);
this.context.moveTo(425, 350);
this.context.lineTo(475, 350);
this.context.stroke();
}
// 绘制树
private drawTree(): void {
// 树干
this.context.fillStyle = '#8D6E63';
this.context.fillRect(600, 350, 20, 100);
// 树叶 - 使用椭圆
this.context.fillStyle = '#388E3C';
// 底部椭圆
this.context.beginPath();
this.context.ellipse(610, 350, 60, 40, 0, 0, Math.PI * 2);
this.context.fill();
// 中间椭圆
this.context.beginPath();
this.context.ellipse(610, 320, 50, 35, 0, 0, Math.PI * 2);
this.context.fill();
// 顶部椭圆
this.context.beginPath();
this.context.ellipse(610, 290, 40, 30, 0, 0, Math.PI * 2);
this.context.fill();
}
// 绘制文本
private drawTexts(): void {
// 标题文本 - 填充
this.context.font = '40px bolder sans-serif';
this.context.fillStyle = '#000000';
this.context.fillText('美丽的风景', 50, 50);
// 动态文本 - 描边
this.context.font = '30px sans-serif';
this.context.strokeStyle = '#FF5722';
this.context.lineWidth = 1;
this.context.strokeText(this.text, 50, 580);
// 组合文本 - 填充和描边
this.context.font = '24px sans-serif';
this.context.fillStyle = '#FFFFFF';
this.context.fillText('Canvas 绘图示例', 300, 450);
this.context.strokeStyle = '#000000';
this.context.lineWidth = 0.5;
this.context.strokeText('Canvas 绘图示例', 300, 450);
}
}
更多推荐



所有评论(0)