Canvas基础入门篇

Canvas API 提供了一个通过 JavaScript 和 HTML 的 canvas 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

Canvas API 主要聚焦于2D图形。而同样使用 canvas 元素的 WebGL API 则用于绘制硬件加速的 2D 和 3D 图形。

获取渲染上下文(2D环境)

除一些过时的浏览器不支持 canvas 元素外,所有的新版本主流浏览器都支持它。Canvas 的默认大小为 300px X 150px。但是,可以使用 HTML 的高度和宽度属性来自定义 Canvas 的尺寸。为了在 Canvas 上绘制图形,先使用一个 JavaScript 上下文对象,它能动态创建图像。

注意: CSS 中的 width、height 控制的是画布在文档中的宽高,当宽度比例与 canvas 属性中定义的宽度不一致时,会拉伸 Canvas 元素,相当于把固定的图片拉伸了。

<div class="flex_box">
    <canvas id="canvas" class="flex_item" width="500" height="500"></canvas>
</div>
const canvas = document.getElementById("canvas_base")
const context = canvas.getContext("2d")
function getContext2D () {
    return new Promise((resolve, reject) => {
        const canvas = document.getElementById("canvas_base")
        const context = canvas.getContext("2d")
        if (context) {
            resolve(context)
        } else {
            reject()
        }
    })
}

状态的保存和恢复

Canvas 是基于状态的绘制,包括:当前应用的变形、当前的裁切路径、以及以下属性:

Canvas 可通过以下方法管理状态:

  • save():保存画布的所有状态

  • restore():save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

Canvas 状态存储在栈中,每当 save() 方法被调用后,当前的状态就被推送到栈中保存。

从线条开始

移动画笔:

这句代码的意思是移动画笔至(x, y)这个点(单位是px)。记住,这里是以 canvas 画布的左上角为笛卡尔坐标系的原点,且y轴的正方向向下,x轴的正方向向右。

笔画停点:

这句的意思是从上一笔的停止点绘制到(x, y)这里。不过要清楚,这里的 moveTo()、lineTo() 都只是状态而已,是规划,是我准备要画,还没有开始画,只是一个计划而已!

选择画笔:

Canvas是基于状态的绘制,所以我们在选择画笔粗细和颜色的同时,其实也是选择了线条的粗细和颜色。

确定绘制:

**确定绘制只有两种方法,fill() 和 stroke() **,前者是指填充,后者是指描边。

image-20200802152344385

查看DEMO

期待绘制结果:第一条线是青色,第二条线是粉红色,第三条线是深蓝。 然而,最终绘制结果:三条线都是深蓝色。这里的原因就是前面强调——Canvas是基于状态的绘制

什么意思呢?就是说每当状态发生改变,Canvas 会重新渲染。

从上面示例来说:每次使用 stroke() 时,它都会把之前设置的状态再绘制一遍。如,第一次 stroke() 时,绘制一条青色的折线;第二次 stroke() 时,会再重新绘制之前的那条青色的折线,但是这个时候的画笔已经被更换成粉红色的了,所以画出的折线全是粉红色的;第三次 stroke() 同理,画笔更换成了深蓝色,所以最终三条线都是深蓝!

实际上,这里看到的三条折线,其实绘制了 3 次,一共绘制了 6 条折线。

创建新路径:

beginPath() 是 Canvas 2D API 通过清空子路径列表开始一个新路径的方法。

在每次绘制之前加上 beginPath() ,表示下次绘制的起始处为 beginPath() 之后的代码。beginPath() 设置的绘制状态的作用域结束于 stroke()、fill() 或者 closePath() 方法。

image-20200802152715047

查看DEMO

线条属性概述:

lineCap 属性定义上下文中线的端点,可以有以下 3 个值:

  • butt:默认值,端点是垂直于线段边缘的平直边缘。

  • round:端点是在线段边缘处以线宽为直径的半圆。

  • square:端点是在选段边缘处以线宽为长、以一半线宽为宽的矩形。

lineJoin 属性定义两条线相交产生的拐角,可将其称为连接。在连接处创建一个填充三角形,可以使用 lineJoin 设置它的基本属性。

  • miter:默认值,在连接处边缘延长相接。miterLimit 是角长和线宽所允许的最大比例(默认是 10)。

  • bevel:连接处是一个对角线斜角。

  • round:连接处是一个圆。

lineWidth 属性定义线的宽度(默认值为 1.0)。

strokeStyle 属性定义线和形状边框的颜色和样式。

填充颜色

基本颜色:

线性渐变:

image-20200802153043369

查看DEMO

径向渐变:

image-20200802153527937

查看DEMO

填充纹理: 纹理其实就是图案的重复,填充图案通过 createPattern() 函数进行初始化。

image-20200802154344739

查看DEMO

绘制矩形

绘制标准圆弧

image-20200802154748374

查看DEMO

image-20200802154936529

查看DEMO

贝塞尔曲线

二次贝塞尔曲线

二次贝塞尔曲线需要两个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用 beginPath() 和 moveTo() 方法来定义开始点

image-20200802160540181

查看DEMO

三次贝塞尔曲线

三次贝塞尔曲线需要三个点。前两个点是用于三次贝塞尔计算中的控制点,第三个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用 beginPath() 和 moveTo() 方法来定义开始点。

文本设置

image-20200802160727162

查看DEMO

变换设置

对于缩放变换有两点问题需要注意:

1.缩放时,图像左上角坐标的位置也会对应缩放

2.缩放时,图像线条的粗细也会对应缩放

image-20200802162108256

查看DEMO

注意保存和恢复Canvas状态

变换只会影响 transform() 等方法调用之后的绘图

裁剪区域

clip() 方法来实现 Canvas 的图像裁剪功能。该方法使用路径来对Canvas画布设置一个裁剪区域。因此,必须先创建好路径。创建完整后,调用 clip() 方法来设置裁剪区域。

需要注意的是裁剪是对画布进行的,裁切后的画布不能恢复到原来的大小,也就是说画布是越切越小的,要想保证最后仍然能在canvas最初定义的大小下绘图需要注意 save() 和 restore() 。画布是先裁切完了再进行绘图。并不一定非要是图片,路径也可以放进去~。

image-20200802162403917

查看DEMO

绘制图像

Canvas 更有意思的一项特性就是图像操作能力。可以用于动态的图像合成或者作为图形的背景,以及游戏界面等等。浏览器支持的任意格式的外部图片都可以使用,比如 PNG、GIF、JPEG。 你甚至可以将同一个页面中其他 Canvas 元素生成的图片作为图片源。

Canvas 的 API 可以使用下面这些类型中的一种作为图片的源:

  • HTMLImageElement:Image() 函数构造出来的,或者任何的 img 元素。

  • HTMLVideoElement: video 元素作为图片源,可以从视频中抓取当前帧作为一个图像。

  • HTMLCanvasElement:可以使用另一个 Canvas 元素作为图片源。

  • ImageBitmap:一个高性能的位图。

这些源统一由 CanvasImageSource 类型来引用。

image-20200802162553067

查看DEMO

非零环绕原则与奇偶原则

我们一般使用Canvas的fill方法时,是直接进行填充路径。其实fill方法有两个参数可选:nonzero | evenodd。nonzero - 非零环绕原则,也是默认值;evenodd - 奇偶原则。

非零环绕原则nonzero

奇偶原则

image-20200802162859005

查看DEMO

其他属性

阴影设置:

需要注意的是,这里的阴影同其他属性设置一样,都是基于状态的设置。因此,如果只想为某一个对象应用阴影而不是全局阴影,需要在下次绘制前重置阴影的这四个属性。

全局透明:

橡皮擦:

检测点:

isPointInPath 用于判断在当前路径中是否包含检测点的方法。

绘制圆角矩形

image-20200802163558011

查看DEMO

绘制圆角图片

image-20200802173138214
image-20200802173158563

查看DEMO 圆角图片1 查看DEMO 圆角图片2

参考链接

Canvas API中文文档首页地图

MDN - canvas

原生HTML5 Canvas 参考API文档

canvas

最后更新于

这有帮助吗?