最近项目有需要用到canvas的地方,作为很久没用过的老猿来说,一切都是崭新的开始。既然是开始,那就从最简单的用法去做,话有什么办法呢,这该死的迷人的前端。
canvas的基本方法
canvas只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)。所有其他类型的图形都是通过一条或者多条路径组合而成的。一方面可能会造成使用上的不便,但是另一方面,简单的API让学习成本也相应降低。
项目用的react,这里我举例子也用react hook来进行。
开始我们需要拿到canvas。
// 初始化canvas 的ref;
const canvasRef = useRef();
// 获取渲染上下文功能和绘画功能对象;
const [ctx, setCtx] = useState();
useEffect(() => {
// 项目中用到的是ts [?.] 语法为非空判断语法,如果用的js,es2020也已经支持这种写法;
setCtx(canvasRef?.current?.getContext('2d'));
}, []);
<canvas
ref={canvasRef}
height={1001}
width={1001}
></canvas>
绘制线条的流程:
// 这个方法相当于拿起画笔
ctx.beginPath();
// 相当于画笔的落笔点
ctx.moveTo(startX, startY);
// 相当于把画笔移动到的位置,
ctx.lineTo(endX, endY);
// 把开始位置和结束位置连接起来,这样一条线就画好了
ctx.stroke();
绘制矩形并填充的流程:
// 拿起画笔
ctx.beginPath();
// 沾上红色墨水
ctx.fillStyle = 'red';
// 准备写什么字体的字
ctx.font = '12px Georgia';
// 开始写(内容,横坐标,纵坐标)
ctx.fillText(item.class, item.date * 50, item.room * 50 + 12);
// 换一只笔
ctx.beginPath();
// 沾上颜色
ctx.fillStyle = 'rgba(0, 0, 200, 0.1)';
// 开始涂矩形(开始横坐标,开始纵坐标,宽度,高度)
ctx.fillRect(item.date * 50, item.room * 50 + 1, item.length, 50);
上面是比较简单的线条和带文字的矩形的画法,如果结合实物理解起来就比较好理解了。
这里有个问题,就是我们如果按照整数的落笔点,即上面的坐标点都选择整数的话,就会造成线条很粗的效果:
但是如果每个坐标点都以0.5结尾,那么这种情况就会消失:
可以对比上下两张图,能明显感到不同。
这是因为,canvas的渲染是根据坐标的像素为中心,向左右各延申半像素,然后剩余的版像素会模糊渲染,造成视觉上线条变宽并且不清晰,所以可以增加0.5的坐标来使他从整数坐标渲染。感兴趣可以参照MDN文档。