在我们开始探索一门新的技术的时候,要以更高的角度来看一下这门技术能解决什么问题。
我觉得这样说应该不为过吧!CSS + HTML 能做的事情,canvas 都能做,而 canvas 能做的事情,CSS + HTML 却不一定能做。
那 canvas 究竟能做什么?
canvas 的本质是 HTML 中的一个标签、一个 HTML 元素:
<canvas id="canvas"></canvas>
使用 JavaScript 可以从 canvas 元素中获得一块「画布」(绘图上下文),可以是 2d 的也可以是 3d 的,有了画布以后,画家(程序员)就可以通过画笔(代码)进行绘制大好河山,发挥自己的想象。
使用 canvas 能够做:
1、动画,做一些炫酷的动画
2、游戏
3、数据可视化,比如 Echarts 做的可视化大屏;
4、图像处理;
5、实时视频处理;
总的来说 canvas 能做的事情很多。我们用代码感受一下 canvas。特别强调一下,关于 canvas 所有内容都是通过 TS 实现,好处是使用 TS 能够享受到智能提示。我在 demo 中也使用了 vite,写起来比较方便。
本节内容我们实现的效果是这样的:
完成上面的效果需要做几件事情,我直接上代码:
代码中共用的一些变量:
const parentId = 'canvas-warp';
const canvasWidth = 400;
const canvasHeight = 400;
// 网格线间距
const gridSpace = 40;
const lineColor = '#cec';
let dprValue = window.devicePixelRatio || 1;
1、创建一个 canvas 元素;
与创建其它 DOM 元素一样,直接使用 DOM 相关的API 即可。canvas 可以直接设置 width 和 height 属性,表示画布的宽高,dprValue 主要为了解决清晰度的。而通过 canvas.style.width 设置的是 CSS 的属性,只会影响 canvas 元素在网页中的布局和样式,不会影响画布的大小。
const createACanvas = () => {
let canvas = document.createElement('canvas') as HTMLCanvasElement;
// 设置画布的宽度
canvas.width = canvasWidth * dprValue;
// 设置画布的高度
canvas.height = canvasHeight * dprValue;
// 设置画布的 CSS 样式
canvas.style.width = `${canvasWidth}px`;
canvas.style.height = `${canvasHeight}px`;
canvas.style.backgroundColor = '#fff';
canvas.style.marginLeft = '40px';
canvas.style.marginTop = '40px';
return canvas;
}
2、画一个网格,并标记网格对应的坐标值;
画网格线的思路,在 x 和 y 方向上画不同的线即可,并在线的顶点处画坐标值即可。
const drawGrid = (ctx: CanvasRenderingContext2D) => {
let xCount = canvasHeight / gridSpace;
let yCount = canvasWidth / gridSpace;
const drawValue = (i, isX) => {
ctx.font = '12px';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillStyle = '#222';
if (isX) {
ctx.fillText(`${i * gridSpace}`, 0, gridSpace * i);
}
else {
ctx.fillText(`${i * gridSpace}`, gridSpace * i, 0);
}
}
for (let i = 0; i < xCount; i++) {
ctx.beginPath();
ctx.moveTo(0, gridSpace * i);
ctx.lineTo(canvasWidth, gridSpace * i);
ctx.strokeStyle = lineColor;
ctx.lineWidth = 1;
ctx.stroke();
drawValue(i, true);
}
for (let i = 0; i < yCount; i++) {
ctx.beginPath();
ctx.moveTo(gridSpace * i, 0);
ctx.lineTo(gridSpace * i, canvasHeight);
ctx.strokeStyle = lineColor;
ctx.lineWidth = 1;
ctx.stroke();
drawValue(i, false);
}
};
3、画一个矩形区域
const drawReact = (ctx: CanvasRenderingContext2D) => {
ctx.fillStyle = 'blue';
ctx.fillRect(40, 40, 120, 80);
}
最后,把各个步骤连起来就能看到最终的效果:
// 1. 创建 canvas
let canvas = createACanvas();
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
ctx.setTransform(dprValue, 0, 0, dprValue, 0, 0);
// 2. 画网格
drawGrid(ctx);
// 3. 把 canvas 添加到 DOM 节点中
let parentDom = document.getElementById(parentId);
parentDom.appendChild(canvas);
// 4. 在画布中画一个矩形区域
drawReact(ctx);
上面的内容可能你看不懂,没关系,后面我们会逐步学习各个 API 的作用,大家加油!demo 地址:
https://github.com/lefex/FE/tree/master/learn-canvas
长按关注
素燕《前端小课》
帮助 10W 人入门并进阶前端
官网:https://lefex.gitee.io/