前言
有没有很好奇,类似 processOn 这类作图网站中,网格背景 是怎么做的呢?
如果你 F12 看过它的代码,你将发现原来不是通过 background-image 之类 css 属性做的,而是通过 canvas 实现的。
这篇主要讲如何通过 canvas 来绘制出这样的 网格背景,以及中间碰到的一个 线条模糊的问题。
手把手写代码
1. 创建 ctx 对象
这边将新建一个和屏幕尺寸相同的 canvas 画布:
1 | const canvasEl = document.createElement("canvas"); |
2. 绘制网格
先简单说下思路:
根据 canvas 画布尺寸,以 10px 为间距,分别绘制横纵坐标的线条。
比如绘制横向线条,先将“画笔”移至起点坐标 (0, y),然后通过线条方法 lineTo 绘制屏幕宽度的线条,即绘制 (0, y) 至 (screen.width, y) 的直线。
然后 y 会按照间距 10px 逐渐递增,直至绘制完整个屏幕。
下面根据横纵两个方向,封装了 draw 方法:
1 | const draw = function (isColumn) { |
很顺利你将得到 canvas 绘制的网格图形:
线条模糊
如果你观察比较细腻,能发现上面的网格图形并不是很清晰,可以仔细观察下面的图:
为什么会有这样的情况出现呢?
因为调用 lineTo 是从 A 点到 B 点,轨迹是点到点的连线。当绘制 1px 线条时,是以这个轨迹连线为中间线左右各渲染 0.5px 的线条。这会使得一个像素点只渲染了一半,而另一半会用一个比较弱的颜色填充,导致绘制出模糊的线条。
怎么改?
只要在 moveTo 时,将坐标偏移 0.5px(即将线条轨迹偏移 0.5 位置),然后调用 lineTo 时,也将坐标偏移 0.5px。
这样,最终绘制线条的时候,将在一个完整的像素区域进行渲染了。
有没有便捷的方法?
使用 translate 偏移 x 和 y 坐标值,然后绘制后再调用 setTransform 重置回来:
1 | ctx.translate(0.5, 0.5); |