Canvas学习笔记

名词概念

画布宽高 VS. 样式宽高

API分类:设置状态 VS. 绘制指令

指令式绘图系统(Canvas) VS. 声明式绘图系统(HTML/SVG)

代码片段

清空画布

1

线条

1
2
3
4
5
6
7
8
9
10
11
12
13
function drawDashLine(
ctx: CanvasRenderingContext2D,
start: { x: number; y: number },
end: { x: number; y: number }
) {
ctx.moveTo(start.x, start.y);
ctx.lineTo(end.x, end.y);
ctx.lineWidth = 1;
ctx.strokeStyle = '#FFFFFF';
ctx.setLineDash([4, 4]);
ctx.lineDashOffset = -10;
ctx.stroke();
}

文本

关键函数是:fillText()

1
2
3
4
5
6
7
8
9
10
11
12
13
function drawText(
ctx: CanvasRenderingContext2D,
point: { x: number; y: number },
content: string,
textAlign: CanvasTextAlign = 'start',
textBaseline: CanvasTextBaseline = 'alphabetic'
) {
ctx.font = '10px serif';
ctx.fillStyle = '#FFFFFF';
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.fillText(content, point.x, point.y);
}

文本的定位基准点

注意:绘制文本时,其定位基准点是文字的左下角

因此fillText(text, x, y)函数的y一般要设置为文字的高度值。

设置文本的字体大小

canvas可以通过context.font设置字体的单位,且支持绝对尺寸px和相对尺寸rem等:

1
2
3
4
// 绝对尺寸
context.font = 'bold 12px serif';
// 相对尺寸
context.font = 'bold 2rem serif';

网格辅助线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function drawGrid(canvasElement: HTMLCanvasElement) {
const ctx = canvasElement.getContext('2d');
const { width, height } = canvasElement;
console.error('canvasElement.width', canvasElement.width);

const interval = 100;

for (let i = interval; i < width; i += interval) {
const start = { x: i, y: 0 };
const end = { x: i, y: height };
drawDashLine(ctx, start, end);
drawText(ctx, start, ` ${i}`, 'start', 'top');
}

for (let i = interval; i < height; i += interval) {
const start = { x: 0, y: i };
const end = { x: width, y: i };
drawDashLine(ctx, start, end);
drawText(ctx, start, `${i}`);
}
}

常见问题

0.5像素问题

在我们K线图中遇到过,中间那根线老是画偏。

实际上不是中间的线偏了,而是矩形柱子在宽度为奇数时,多画了一个像素的宽度。

canvas总结:线段宽度与像素边界 - rockyli - 博客园

canvas中strokeRect的渲染问题:strokeRect把一像素的边框渲染成两像素

参考资料

常用API:

https://blog.csdn.net/zeping891103/article/details/72730968

https://www.runoob.com/w3cnote/html5-canvas-intro.html

浅谈 Canvas 渲染引擎:

https://zhuanlan.zhihu.com/p/608415829