一、什么是canvas?
Canvas API(画布)是在HTML5中的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。
Canvas 对象表示一个 HTML 画布元素 -。它没有自己的行为,但是定义了一个 API 支持脚本化客户端绘图操作。
二、浏览器支持
Internet Explorer 9+, Firefox, Opera, Chrome, 和 Safari 支持 标记.
<canvas id="myCanvas" width="500" height="500">
浏览器不支持 Canvas
</canvas>
如果浏览器不支持这个 API,就会显示标签中间的文字:“您的浏览器不支持 Canvas”。
三、开始使用
元素用于生成图像。它本身就像一个画布,JavaScript 通过操作它的 API,在上面生成图像。它的底层是一个个像素,基本上是一个可以用 JavaScript 操作的位图(bitmap)。
它与 SVG 图像的区别在于,是脚本调用各种方法生成图像,SVG 则是一个 XML 文件,通过各种子元素生成图像。
每个元素都有一个对应的CanvasRenderingContext2D对象(上下文对象)。Canvas API 就定义在这个对象上面。
const canvas = document.querySelector('#myCanvas')
const ctx = canvas.getContext('2d')
Canvas API 需要getContext方法指定参数2d,表示该节点生成 2D 的平面图像。如果参数是webgl,就表示用于生成 3D 的立体图案,这部分属于 WebGL API。
按照用途,Canvas API 分成两大部分:绘制图形和图像处理。
绘制图形

这是一个500*500的canvas平面画布。他的左上角为起始点(0,0)。
路径
路径的绘制会用到一下的方法和属性:
- CanvasRenderingContext2D.beginPath():开始绘制路径。
- CanvasRenderingContext2D.closePath():结束路径,返回到当前路径的起始点,会从当前点到起始点绘制一条直线。如果图形已经封闭,或者只有一个点,那么此方法不会产生任何效果。
- CanvasRenderingContext2D.moveTo():设置路径的起点,即将一个新路径的起始点移动到(x,y)坐标。
- CanvasRenderingContext2D.lineTo():使用直线从当前点连接到(x, y)坐标。
- CanvasRenderingContext2D.fill():在路径内部填充颜色(默认为黑色)。
- CanvasRenderingContext2D.stroke():路径线条着色(默认为黑色)。
- CanvasRenderingContext2D.fillStyle:指定路径填充的颜色和样式(默认为黑色)。
- CanvasRenderingContext2D.strokeStyle:指定路径线条的颜色和样式(默认为黑色)。
绘制一段路径
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.lineTo(100, 200);
然后发现画布上并没有什么变化。这是因为只进行了绘制的动作。并没有对绘制的内容着色。
着色又分为两种形式:fill 和 stroke 。
使用 fill 后得到一个黑色三角。
ctx.fill()

使用 stroke 得到一个黑色线段组成的角。
ctx.stroke()

修改颜色,使用 fillStyle 和 strokeStyle 调整填充色和路径颜色。得到一个绿色路径填充了红色的三角形。
ctx.fillStyle = 'red';
ctx.strokeStyle = 'green';
ctx.fill()
ctx.stroke()

线型
关于路径线条的属性和方法:
-
CanvasRenderingContext2D.lineWidth:指定线条的宽度,默认为1.0。
-
CanvasRenderingContext2D.lineCap:指定线条末端的样式,有三个可能的值:butt(默认值,末端为矩形)、round(末端为圆形)、square(末端为突出的矩形,矩形宽度不变,高度为线条宽度的一半)。
-
CanvasRenderingContext2D.lineJoin:指定线段交点的样式,有三个可能的值:round(交点为扇形)、bevel(交点为三角形底边)、miter(默认值,交点为菱形)。
-
CanvasRenderingContext2D.miterLimit:指定交点菱形的长度,默认为10。该属性只在lineJoin属性的值等于miter时有效。
-
CanvasRenderingContext2D.getLineDash():返回一个数组,表示虚线里面线段和间距的长度。
-
CanvasRenderingContext2D.setLineDash():数组,用于指定虚线里面线段和间距的长度。
绘制一条宽度为8,线条木点和交点都是圆角,并且是虚线,虚线中实线和间距为15和5。
ctx.lineWidth = 8;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.setLineDash([15, 5]);
ctx.stroke();

对比之前使用默认属性绘制的线条,线条的末端和交点转角处都被处理成了圆角。
矩形
绘制矩形的方法:
- CanvasRenderingContext2D.rect():绘制矩形路径。
- CanvasRenderingContext2D.fillRect():填充一个矩形。
- CanvasRenderingContext2D.strokeRect():绘制矩形边框。
- CanvasRenderingContext2D.clearRect():指定矩形区域的像素都变成透明。
上面四个方法都接受四个参数,分别是矩形左上角的横坐标和纵坐标、矩形的宽和高。
在距离左上角(10,10)的位置开始绘制一个宽100 高150的矩形。
ctx.rect(10, 10, 100, 150);
ctx.fill();

修改填充色,绘制一个红色矩形。
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 150);

对比两次绘制矩形,除了修改填充色之外,使用的方法也不一样。
一个是先使用ctx.rect() 绘制路径,然后在使用 ctx.fill() 将路径填充颜色。
一个是直接使用 ctx.fillRect() 绘制并填充颜色。
擦除指定矩形区域的像素颜色(只有矩形)。
ctx.clearRect(15, 15, 90, 140);

将画布上,(15,15)位置宽90和高140的矩形区域的像素信息擦除。结合之前绘制的内容形成一个矩形框。
弧线
绘制弧线的方法:
- CanvasRenderingContext2D.arc():通过指定圆心和半径绘制弧形。
- CanvasRenderingContext2D.arcTo():通过指定两根切线和半径绘制弧形。
使用==CanvasRenderingContext2D.arc()==可以来绘制圆形和扇形。
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
arc()方法的x和y参数是圆心坐标
radius是半径
startAngle和endAngle则是扇形的起始角度和终止角度(以弧度表示)
anticlockwise表示做图时应该逆时针画(true)还是顺时针画(false),这个参数用来控制扇形的方向(比如上半圆还是下半圆)。
ctx.arc(60, 60, 50, 0, Math.PI * 0.5, true);
ctx.stroke()

如果使用 ==fill()==方法填充,想要获得一个扇形。
ctx.arc(60, 60, 50, 0, Math.PI * 0.5, true);
ctx.fill()

绘制出来的形状并不是扇形。
fill 方法是为路径内部填充颜色。如果路径没有闭合,则自动将最后点位和起始点位相连形成封闭路径,将内部填充颜色。
所以绘制出来的形状不是扇形,所以想要直接使用arc() 方法绘制扇形,并不能实现。要使用 lineTo() 连接回圆心实现。
ctx.arc(60, 60, 50, 0, Math.PI * 0.5, true);
ctx.lineTo(60, 60);
ctx.closePath();
ctx.stroke();
ctx.fill();

CanvasRenderingContext2D.arcTo() 方法主要用来绘制圆弧,需要给出两个点的坐标,当前点与第一个点形成一条直线,第一个点与第二个点形成另一条直线,然后画出与这两根直线相切的弧线。
ctx.moveTo(0, 0);
ctx.arcTo(50, 50, 100, 0, 25);
ctx.lineTo(100, 0);
ctx.stroke();
ctx.fill();

arcTo()有5个参数
前两个参数是第一个点的坐标
第三个参数和第四个参数是第二个点的坐标
第五个参数是半径
然后,(0, 0)与(50, 50)形成一条直线,然后(50, 50)与(100, 0)形成第二条直线。弧线就是与这两根直线相切的部分。
这样看可能稍微有点抽象,使用线段标识来展示一下:
ctx.moveTo(0, 0);
ctx.lineTo(50, 50);
ctx.lineTo(100, 0);
ctx.stroke();
ctx.moveTo(0, 0);
ctx.arcTo(50, 50, 100, 0, 25);
ctx.lineTo(100, 0);
ctx.stroke();

文本
文本相关方法:
- CanvasRenderingContext2D.fillText():在指定位置绘制实心字符。
- CanvasRenderingContext2D.strokeText():在指定位置绘制空心字符。
- CanvasRenderingContext2D.measureText():返回一个 TextMetrics 对象。
- CanvasRenderingContext2D.font:指定字型大小和字体,默认值为 10px sans-serif 。
- CanvasRenderingContext2D.textAlign:文本的对齐方式,默认值为 start。
- CanvasRenderingContext2D.direction:文本的方向,默认值为 inherit。
- CanvasRenderingContext2D.textBaseline:文本的垂直位置,默认值为 alphabetic。
使用 fillText() 方法绘制实心字符。
CanvasRenderingContext2D.fillText(text, x, y, maxWidth)
text:所要填充的字符串。
x:文字起点的横坐标,单位像素。
y:文字起点的纵坐标,单位像素。
maxWidth:文本的最大像素宽度。该参数可选,如果省略,则表示宽度没有限制。如果文本实际长度超过这个参数指定的值,那么浏览器将尝试用较小的字体填充。
ctx.fillText('Hello world', 50, 50);

设置最大宽度的话:
ctx.fillText('Hello world', 50, 50, 20);

注意,fillText()方法不支持文本断行,所有文本一定出现在一行内。如果要生成多行文本,只有调用多次fillText()方法。
使用 strokeText() 方法绘制空心字符。参数与 fillText() 一致。
ctx.strokeText('Hello world', 50, 150);

由于默认字体大小为10px,空心字符效果看起来不明显,修改 ctx.font 的值让效果明显。
ctx.font = "80px sans-serif";

虽然空心字符看起来像封闭路径,但是并不能使用 fill() 方法对空白部分填充。
使用 textAlign 设置文本的对齐方式。
left:左对齐
right:右对齐
center:居中
start:默认值,起点对齐(从左到右的文本为左对齐,从右到左的文本为右对齐)。
end:结尾对齐(从左到右的文本为右对齐,从右到左的文本为左对齐)。
ctx.textAlign = 'center';
ctx.fillText('Hello world', 50, 150);

这时有可能存在误解,会认为此时的文本会在绘制的canvas或者整个canvas画布的中间。
但实际上,对齐的基准点为绘制文本时的起始点坐标(50,150)。
证实一下结论:从(50,150)这个点分别向上方和左侧边缘绘制垂直线。
ctx.moveTo(50,0)
ctx.lineTo(50,150)
ctx.stroke();
ctx.moveTo(0,150)
ctx.lineTo(50,150)
ctx.stroke();

可以看出绘制出来的垂直辅助线将文本对半分割。
使用direction来调整文字方向。
默认值为inherit,表示继承或document的设置。其他值包括ltr(从左到右)和rtl(从右到左)。
ctx.direction = 'rtl'
ctx.strokeText("Hello world", 50, 150);

同样的文字方向的基准点还是以绘制文字时的坐标为准。
暂时先整理这些,后续会继续整理渐变色和图像填充部分

被折叠的 条评论
为什么被折叠?



