声明
本文依赖文章canvas详细入门教程(1W字 吐血分享),讲解了harmonyOS的Canvas的使用,在内容上做了一定的精简,完整学习Canvas建议点击链接
构造canvas对象
这是官网的案例
使用CanvasRenderingContext2D对象在Canvas画布上绘制。
@Entry
@Component
struct CanvasExample1 {
//用来配置CanvasRenderingContext2D对象的参数,包括是否开启抗锯齿,true表明开启抗锯齿。
private settings: RenderingContextSettings = new RenderingContextSettings(true)
//用来创建CanvasRenderingContext2D对象,通过在canvas中调用CanvasRenderingContext2D对象来绘制。
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
//在canvas中调用CanvasRenderingContext2D对象。
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#F5DC62')
.onReady(() => {
//可以在这里绘制内容。
this.context.strokeRect(50, 50, 200, 150);
})
}
.width('100%')
.height('100%')
}
}
重点---在Canvas里绘制
Canvas的绘制主要在onReady()事件回调里
坐标系:以左上角为起点
一、绘制基础图形
画线之前你需要知道canvas上下文的以下几个api:
moveTo(x,y)
:定义画线的起始点;
lineTo(x,y)
:定义画线的折点;
stroke()
:通过线条来绘制图形轮廓
beginPath():开启一条新的路径
closePath();关闭路径
1.画线段
@Entry
@Component
struct CanvasExample2 {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() =>{
// 画线段
this.context.beginPath()
this.context.moveTo(150,150)
this.context.lineTo(300,150)
this.context.stroke()
this.context.beginPath()
this.context.moveTo(150,450)
this.context.lineTo(300,450)
})
}
.width('100%')
.height('100%')
}
}
如果没有调用 this.context.stroke()第二条线实际上并不会在画布上显示出来,因为
this.context.moveTo(150,450) this.context.lineTo(300,450)
这些方法只是定义了路径,并没有绘制它。
2. 画三角形
@Entry
@Component
struct CanvasExample2 {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() =>{
// 画三角形
this.context.beginPath()
this.context.moveTo(150,150) // 起点坐标
this.context.lineTo(300,150)
this.context.lineTo(300,300)
this.context.lineTo(150,150)
this.context.closePath()
this.context.lineWidth=20 //设置线段宽度
this.context.strokeStyle='blue' //设置线段颜色
// 注意,要在stroke() 前设置样式,否者会显示不出来
this.context.stroke()
})
}
.width('100%')
.height('100%')
}
}
3.画矩形
@Entry
@Component
struct CanvasExample3 {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() =>{
this.context.beginPath()
this.context.rect(40,40,160,90)
this.context.closePath()
this.context.lineWidth=20 //设置线段宽度
this.context.strokeStyle='blue' //设置线段颜色
// 注意,要在stroke() 前设置样式,否者会显示不出来
this.context.stroke()
})
}
.width('100%')
.height('100%')
}
}
4.画圆形
@Entry
@Component
struct CanvasExample4 {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() =>{
//绘制圆形
this.context.beginPath();
this.context.arc(150, 250, 50, 0, 6.28);
this.context.stroke();
//绘制半圆形
this.context.beginPath();
this.context.arc(150, 350, 50, 0, 3.14);
this.context.stroke();
})
}
.width('100%')
.height('100%')
}
}
5.画椭圆
@Entry
@Component
struct CanvasExample5 {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() =>{
//绘制椭圆
this.context.beginPath();
this.context.ellipse(150, 350, 50, 100, Math.PI * 0.25, Math.PI * 0, Math.PI * 2);
this.context.stroke();
})
}
.width('100%')
.height('100%')
}
}
二.设置文本
可以通过fillText(绘制填充类文本)、strokeText(绘制描边类文本)等接口进行文本绘制。
@Entry
@Component
struct Canvas_demo_04 {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() =>{
this.context.font ='20vp' //.font方法可以设置文本大小和字体;
this.context.beginPath()
this.context.strokeText('hello world',100,100,200)
this.context.closePath()
this.context.beginPath()
this.context.font ='100vp'
this.context.strokeText('hello world',100,300,200)
this.context.closePath()
this.context.beginPath()
this.context.fillText('这是文本',100,600,100)
})
}
.width('100%')
.height('100%')
}
}
三.样式补充
渐变色
//渐变色
@Entry
@Component
struct CanvasDemo_05 {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffffffff')
.onReady(() => {
// 创建渐变
let gradient = this.context.createLinearGradient(0, 0, 700, 0);
gradient.addColorStop(0, Color.Green.toString());
gradient.addColorStop(1, Color.Red.toString());
// 填充渐变背景
this.context.beginPath();
this.context.fillStyle = gradient;
this.context.fillRect(0, 0, 700, 600);
this.context.fill();
});
}
.width('100%')
.height('100%')
}
}
四.使用案例
使用Canvas绘制气温变化图
@Entry
@Component
struct TempLineChart {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
// 定义气温和小时数组
private Temp: number[] = [18, 20, 21, 21, 22, 23, 25, 27, 29, 30, 32, 34, 36, 35, 32, 30, 27, 26, 24, 22, 21, 20, 20, 19]
private Hour: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
build() {
Scroll(){
Canvas(this.context)
.width(680)
.height(300)
.backgroundColor('#ffffffff')
.onReady(() => {
this.drawChart()
})
}
.scrollable(ScrollDirection.Horizontal)
}
// 绘制折线图函数
drawChart() {
const width: number = 680
const height: number = 300
// 定义绘图区域的边距
const padding: number = 40
const graphWidth: number = width - 2 * padding
const graphHeight: number = height - 2 * padding
// 绘制坐标轴
this.drawAxes(padding, graphWidth, graphHeight)
// 绘制折线
this.drawLine(padding, graphWidth, graphHeight)
// 绘制X轴小时数
this.drawXAxisLabels(padding, graphWidth, graphHeight)
}
// 绘制坐标轴函数
drawAxes(padding: number, graphWidth: number, graphHeight: number) {
this.context.strokeStyle = '#000000'
this.context.lineWidth = 2
// 绘制X轴
this.context.beginPath()
this.context.moveTo(padding, padding + graphHeight)
this.context.lineTo(padding + graphWidth, padding + graphHeight)
this.context.stroke()
// 绘制Y轴
this.context.beginPath()
this.context.moveTo(padding, padding)
this.context.lineTo(padding, padding + graphHeight)
this.context.stroke()
}
// 绘制折线函数
drawLine(padding: number, graphWidth: number, graphHeight: number) {
this.context.strokeStyle = '#ff0000'
this.context.lineWidth = 2
// 根据气温和小时数据计算折线图的点
this.context.beginPath()
for (let i = 0; i < this.Hour.length; i++) {
const x = padding + (graphWidth / (this.Hour.length - 1)) * i
const y = padding + graphHeight - 30-(graphHeight / 20) * (this.Temp[i] - 18)
if (i === 0) {
this.context.moveTo(x, y)
} else {
this.context.lineTo(x, y)
}
this.context.fillText(this.Temp[i].toString()+'°', x, y-20)
}
this.context.stroke()
}
// 绘制X轴小时数函数
drawXAxisLabels(padding: number, graphWidth: number, graphHeight: number) {
this.context.fillStyle = '#000000'
this.context.font = '30px Arial'
this.context.textAlign = 'center'
for (let i = 0; i < this.Hour.length; i++) {
const x = padding + (graphWidth / (this.Hour.length - 1)) * i
const y = padding + graphHeight + 20 // 调整标签的位置
this.context.fillText(this.Hour[i].toString(), x, y)
}
}
}