Canvas 2D

画布尺寸

canvas元素默认的宽高为300px * 150px 建议使用canvaswidthheight设置宽高,单位使用px,例如:

<canvas ref="{canvasRef}" width="1000px" height="600px">
  该浏览器暂不支持canvas标签
</canvas>
注意

使用csscanvas设置宽高虽然可以生效,但是绘制的图形会被扭曲拉伸,如果想要canvas元素铺满全屏可以使用js获取可视区域宽高,设置canvaswidthheight 属性

请务必不要把canvas当做单标签使用,否则浏览器会把其后的内容视为在不兼容canvas元素的浏览器中展示的替代内容
本文全篇使用react语法,所以不会有这种情况,但是仍建议使用双标签,并书写兼容提示

画布上下文

canvasgetContext()方法根据传入的参数返回不同的上下文,也就是画板和可以使用的画笔、颜料桶等等,本文只涉及CanvasRenderingContext2D

const canvas = canvasRef.current;
// 获取canvas的dom节点,原生js可以给canvas设置id,使用document.getElementById获取dom
const ctx = canvas.getContext("2d");
图1:画布的坐标轴方向
图1:画布的坐标轴方向

如下图所示,画布是由像素点组成的,像素点便是图形绘制时的基础单位

图2:画布中的点
图2:画布中的点

遗憾的是并没有一个专门绘制像素点的方法,当然我们还是可以绘制像素点的,毕竟像素点也是矩形,最小的矩形

ctx.fillRect(0, 0, 1, 1);
// 绘制一个填充的矩形
ctx.strokeRect(0, 0, 1, 1);
// 绘制一个线框矩形
ctx.rect(0, 0, 1, 1);
// 绘制一个矩形路径
ctx.stroke();

尽管三种方法并不相同,但是当宽高都为1px时,绘制出的也就是一个点,三种方法中fillRect()方法绘制的点最为理想

线

点向一个方向延展便会形成线,在canvas中线和路径是分不开的,路径是由线组成的。
当然也有直接生成路径的方法,比如前文的rect()可以直接生成一个矩形路径

beginPath

生成一个路径,将绘制命令指向这个路径

ctx.beginPath();

closePath

闭合路径,将绘制命令指回上下文

ctx.closePath();

stroke

绘制路径的轮廓,即用线去勾勒路径

ctx.stroke();

fill

填充路径,绘制实心的图形

ctx.fill();

moveTo

移动笔触,即抬笔将笔移动到点(x,y)

ctx.moveTo(x, y);

lineTo

绘制一条从当前点到(x,y)的路径

ctx.lineTo(x, y);

arc

绘制一段以(x,y)为圆心,半径为radius,起始角度为startAngle,结束角度为endAngle,顺时针(逆时针)的圆弧

ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

ctx.arcTo(x1, y1, x2, y2, radius): 表现形式很诡异, 不建议使用, 可以自行了解

quadraticCurveTo

绘制一段从当前点到(x,y),控制点为(cp1x, cp1y)的二次贝塞尔曲线

ctx.quadraticCurveTo(cp1x, cp1y, x, y);

bezierCurveTo

绘制一段从当前点到(x,y),控制点为(cp1x, cp1y)(cp2x, cp2y)的三次贝塞尔曲线

ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

案例-绘制哆啦 A 梦

效果展示

绘制思路

  • 绘制时以一个个的闭合回路为基本单位,每个回路的绘制步骤大体都是:
  • 申明路径(beginPath)-->
  • 移动笔触(moveTo)-->
  • 绘制直线(lineTo)、弧线(arc)、二次贝塞尔曲线(quadraticCurveTo)或 三次贝塞尔曲线(bezierCurveTo)-->
  • 重复前两步直到该回路绘制完毕 -->
  • 根据情况选择是否需要闭合回路(closePath)-->
  • 根据情况选择是否需要填充图形(fill)-->
  • 根据情况选择是否需要勾勒图形轮廓(stroke)

示例代码

哆啦 A 梦