以前我们用 div+css 可以绘制矩形、圆角矩形、圆形、或者椭圆形,可是若想绘制三角形、五角形,或者异形,那就很难了
因此,这个时候我们就需要使用 canvas 绘图。我们可以使用 canvas 绘制复杂图形,做动画,处理图像,开发游戏,处理视频…

这时候,会 svg 的小伙伴可能会说,用 svg 也可以绘制上面的形状
svg 与 canvas 确实有着很多共通之处,很多项目可以用 SVG 开发,也可以用 canvas 开发
但svg与canvas的差异也挺大的:
注:当 canvas 图像数量和图像的计算量太大的时候,也会卡,这时候便可以选择 WebGL,因为 WebGL 有GPU 加速
设置 canvas 的 width、height 属性:
<canvas id="canvas" width="700" height="800">也可用 js 设置:
const canvas=document.getElementById('canvas');
canvas.width=300;
canvas.height=150;注:不要使用 css 设置 canvas 尺寸,除非想要调整图像清晰度
如果说 canvas 是画布,那么 canvas 上下文对象就是画笔。获取上下文对象的方法:canvas.getContext('2d')
//画布
const canvas=document.getElementById('canvas');
//画笔
const ctx=canvas.getContext('2d');使用画笔在 canvas 上画画,要考虑三个方面:
如,绘制一个红色的矩形:
<canvas id="canvas" width="700" height="800">
不兼容
</canvas>
<script>
//画布
const canvas=document.getElementById('canvas');
//画笔
const ctx=canvas.getContext('2d');
//填充色
ctx.fillStyle='red';
//绘制填充矩形
ctx.fillRect(
20,20,
400,200
)
</script>效果如下:

canvas 的尺寸不能过大,尺寸尽量控制在 4000 以内,canvas 尺寸的极限值因浏览器、平台不同而不同
canvas 在不同浏览器和平台上的极限值:
Chrome:
Maximum height/width: 32,767 pixels
Maximum area: 268,435,456 pixels (e.g., 16,384 x 16,384)
Firefox:
Maximum height/width: 32,767 pixels
Maximum area: 472,907,776 pixels (e.g., 22,528 x 20,992)

这里说的矩形是 canvas 绘图形式中的矩形,它有三种类型:

const canvas=document.getElementById('canvas');
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
//画笔
const ctx=canvas.getContext('2d');
/*填充矩形方法:fillRect(x,y,w,h)*/
ctx.fillRect(
100,50,
400,200
)
/*描边矩形方法:strokeRect(x,y,w,h)*/
ctx.strokeStyle='red';
ctx.lineWidth=10;
ctx.strokeRect(
100,50,
400,200
)
/*清理矩形方法:clearRect(x,y,w,h)*/
ctx.clearRect(
100,50,
400,200
)开始建立路径:beginPath()
向路径集合中添加子路径:
[
moveTo(x,y); 形状; closePath() 可选,
moveTo(x,y); 形状; closePath() 可选,
moveTo(x,y); 形状; closePath() 可选,
]
//画笔
const ctx=canvas.getContext('2d');
//线宽
ctx.lineWidth=10;
//直线
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(400,50);
ctx.lineTo(400,250);
ctx.closePath();
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.arc(
300,300,
200,
0,Math.PI*3/2,
);
ctx.moveTo(300+200,500);
ctx.arc(
300,500,
200,
0,Math.PI*3/2,
);
ctx.stroke();

ctx.beginPath();
//起点
ctx.moveTo(50,50);
// 控制点与起点
ctx.quadraticCurveTo(
400,500,
400,250,
)
ctx.stroke();
//起始点
ctx.moveTo(50,50);
ctx.bezierCurveTo(
//控制点1
400,50,
//控制点2
400,250,
//结束点
600,250
)
ctx.stroke();ctx.beginPath();
ctx.rect(
100,50,
400,200
)
ctx.rect(
100,350,
400,200
)
ctx.stroke();rect(x,y,w,h) 绘制路径时,会内置 moveTo() 功能


图形的着色区域有两种:

图形的着色方式有 3 种:纯色、渐变、纹理
书写方式(与 css 一致):
#000000rgb(r,g,b)rgba(r,g,b,a)为图形着色
ctx.fillStyle = 'red'
ctx.strokeStyle = 'rgb(r,g,b)'gradient=ctx.createLinearGradient(x1, y1, x2, y2)gradient=ctx.createRadialGradient(x1, y1, r1, x2, y2, r2)gradient.addColorStop(position, color)
ctx.fillStyle= gradient
ctx.strokeStyle= gradient
const linerGradient=ctx.createLinearGradient(x1,y1,x2,y2);
linerGradient.addColorStop(0,'red');
linerGradient.addColorStop(.5,'yellow');
linerGradient.addColorStop(1,'green');
const radGradient=ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
radGradient.addColorStop(0,'red');
radGradient.addColorStop(.5,'yellow');
radGradient.addColorStop(1,'green');纹理可以将一张图片作为图形的底色,如下图所示:

pattern=context.createPattern(image,"repeat|repeat-x|repeat-y|no-repeat");ctx.fillStyle= pattern
ctx.strokeStyle= pattern



ctx.miterLimit 可避免此问题:


ctx.setLineDash([ 60, 90 ])
ctx.setLineDash([ 60, 90, 120 ])
lineDashOffset:虚线偏移

投影是上下文对象的一种属性,在绘制图形时,无论执行的是描边方法,还是填充方法,只要设置了投影相关的属性,都会在其所绘图形的后面添加投影

投影相关的属性:
偏移位置
shadowOffsetX = float
shadowOffsetY = float
模糊度: shadowBlur = float
颜色:shadowColor = color
其实,投影不仅可以做投影,当投影比较亮的时候,还可以做光晕
文本的属性有 3 种:
canvas 里的 font 属性和 css 的 font 属性是一样的,它可以设置文本的粗细、字号、字体等
p{font:bold 18px serif;}ctx.font = 'bold 18px serif'更多参数可参考 css MDN:https://developer.mozilla.org/zh-CN/docs/Web/CSS/font
下方文字的 x 位置都是一样,都是垂直虚线的 x 位置,它们的 textAlign 属性各不相同。

ctx.textAlign='start';
ctx.fillText('start',300,100);
ctx.textAlign='left';
ctx.fillText('left',300,150);
ctx.textAlign='end';
ctx.fillText('end',300,200);
ctx.textAlign='right';
ctx.fillText('right',300,250);
ctx.textAlign='center';
ctx.fillText('center',300,300);注:start 和 left 的差异在文本的阅读方向dir
<html dir='ltr'><html dir='rtl'>

| alphabetic | 默认。标准字母基线对齐 |
|---|---|
| top | 上对齐 |
| hanging | 悬挂基线对齐 |
| middle | 垂直居中 |
| ideographic | 表意基线对齐 |
| bottom | 下对齐 |
ctx.textBaseline='top';
ctx.fillText('top',100,200);
ctx.textBaseline='middle';
ctx.fillText('middle',200,200);
ctx.textBaseline='bottom';
ctx.fillText('bottom',300,200);
ctx.textBaseline='alphabetic';
ctx.fillText('alphabetic',400,200);文本的绘制方法有 2 种:
除此之外,还有一个方法可以获取文本的宽度:measureText(text)
//文字内容
const text='好好学习,天天向上';
//字体
ctx.font='100px arial';
//描边宽度
ctx.lineWidth=3;
//描边色
ctx.strokeStyle='red';
//填充文字
ctx.fillText(text,100,300);
//描边文字
ctx.strokeText(text,100,300);
这里说的图像源就是 canvas 在绘制图像时所用的源文件。常见的图像源有三种:
drawImage() 方法可以将一张图像绘制到 canvas 画布里。drawImage() 方法因参数数量不同,其具体功能也不同:

const ctx=canvas.getContext('2d');
const img=new Image();
img.src='./images/dog.jpg';
img.onload=function(){
/*图像尺寸*/
const {width,height}=img;
/*绘图+移动 drawImage(image, x, y) */
ctx.drawImage(
img,
50,100
);
};
const ctx=canvas.getContext('2d');
const img=new Image();
img.src='./images/dog.jpg';
img.onload=function(){
/*图像尺寸*/
const {width,height}=img;
/*绘图+移动+缩放 drawImage(image, x, y,width,height) */
ctx.drawImage(
img,
0,0,
width*2,height*2
)
};
此时的 drawImage() 方法已经具备了相机视口的功能
const ctx=canvas.getContext('2d');
const img=new Image();
img.src='./images/dog.jpg';
img.onload=function(){
/*图像尺寸*/
const {width,height}=img;
/*绘图+裁剪+移动+缩放 drawImage(image, x1, y1,w1,h1,x2,y2,w2,h2) */
ctx.drawImage(
img,
//裁剪
width/2,height/2,
width/2,height/2,
//位移+缩放
100,100,
width,height
)
};