canvas使用总结

242 阅读7分钟

1.canvas基础用法

1.1 canvas概念

canvas标签相当于一个"画板",它常用于图片绘制、动画、数据可视化等。

1.2 canvas坐标系

1.3 小例子

<canvas id=“canvas” width=“400” height="400"></canvas> 
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d'); 
ctx.fillStyle = "green";
ctx.fillRect (10, 10, 55, 50);              

结果如下

注:

1).canvas标签需写全,不能简写为单标签。

2).canvas标签只有两个属性 width 和 height(当然 id、class等标签通用属性也有),canvas的大小只受width、height属性影响,css样式不起作用,如果不设置则默认为150*300。

3).canvas.getContex获取渲染上下文对象,该对象可以理解为该 “画板” 的 “绘画工具”。

2.使用 canvas 绘制图形

2.1 路径

路径指的是在 “画板“ 上产生的画痕,从开始 “下笔” 到结束,单一次在 “画板” 产生的画痕,算一个路径。

beginPath()

新建一条路径,生成之后,“绘画工具”指向新建的路径。

moveTo(x,y)

在画板坐标系上移动下笔的焦点

lineTo(x,y)

从焦点处画线到指定坐标处

stroke()

使刚刚画的路径现形

fill()

填充刚刚画的路径闭合区域

closePath()

关闭路径,"绘画工具会重新指向上下文"

例子如下

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 200;
canvas.height = 200;
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(40, 10);
ctx.lineTo(40, 40);
ctx.fill();
ctx.closePath();
document.body.appendChild(canvas);        

结果

2.2 矩形

canvas提供了api绘制矩形

fillRect(x, y, width, height)

绘制一个填充的矩形

strokeRect(x, y, width, height)

绘制一个矩形的边框

rect(x, y, width, hright)

将一个矩形加入当前路径,需使用stroke等使它现形

clearReact(x, y, width, height)

清除指定矩形区域,让清除部分完全透明

例子如下

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 400;
ctx.fillRect(10, 10, 100, 100);
ctx.clearRect(30, 30, 60, 60);
ctx.strokeRect(35, 35, 50, 50);
document.body.appendChild(canvas);           

结果如下:(自行脑补坐标系)

2.3 圆弧

arc(x, y, radius, startAngle, endAngle, anticlockwise)

画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。

其中,startAngle和endAngle的单位是弧度(1圈为2π=360度,1弧度为π/180),anticlockwise为布尔值(true逆时针,false顺时针),圆弧的0弧度在正右方。

小例子:

let canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.arc(20, 20, 20, 0, Math.PI / 3, false);
ctx.stroke();
document.body.appendChild(canvas);             

结果如下:

2.4 贝塞尔曲线

顾名思义,就是专门提供来画曲线的api

2.4.1 二次贝塞尔曲线

quadraticCurveTo(cp1x, cp1y, x, y)

两个蓝点,一个为起始点(当前焦点),一个为结束点(参数x,y)。

红点为控制点(参数cp1x,cp1y),用来 "拉扯" 出曲线的。

小例子:

let canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.moveTo(20, 20);
ctx.quadraticCurveTo(40, 20, 40, 40);
ctx.quadraticCurveTo(40, 60, 60, 60);
ctx.stroke();
document.body.appendChild(canvas);

结果如下:

2.4.2 三次贝塞尔曲线

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

同样两个蓝点,起始点(当前焦点),结束点(参数x,y)

两个控制点,坐标分别为(cp1x, cp1y),(cp2x, cp2y)

小例子:

let canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.moveTo(20, 20);
ctx.bezierCurveTo(40, 20, 40, 60, 60, 60);
ctx.stroke();
document.body.appendChild(canvas);

结果如下:

同样,焦点总会重新定到上一次曲线的结束点。

2.5 文本

2.5.1 canvas 提供了两种方法来渲染文本

fillText(text, x, y, maxWidth)

绘制实体文本,text为文本内容,x,y为文本开始坐标,maxWidth为最大宽度

strokeText(text, x, y, maxWidth)

绘制描边文本,参数含义与上相同

2.5.2 提供了四个属性设置文本样式

font

设置字号与字体,语法规则与css font一样,如"10px sans-serif"

textAlign

设置文本对齐,可选值有top、end、left、right、center,默认值start

textBaseline

设置基线对齐,可选值有top、hanging、middle、alphabetic、ideographic、bottom,默认alphabetic

direction

文本方向,可选值有ltr、rtl、inherit,默认inherit

小例子

let canvas = document.createElement('canvas');
canvas.width = 400;
canvas.height = 400;
let ctx = canvas.getContext('2d');
ctx.font = "36px serif";
ctx.strokeText('this is a world!', 20, 30);
ctx.textAlign = 'right';
ctx.fillText('this is a world!', 160, 60, 140);
document.body.appendChild(canvas);

结果如下

3.应用颜色和样式

3.1 颜色

实际上在绘制图形时,我们可以切换当前所使用的的颜色,从而画出彩色的图案。canvas通过fillStyle(设置图形的填充颜色)和strokeStyle(设置图形轮廓的颜色)这两个属性来实现这一点。它以路径为单位,每个路径都只能使用一种填充颜色和一种轮廓颜色。其中颜色的值可以为英文、16进制值、rgb、rgba。

小例子:

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
//画橙色的扇形
ctx.fillStyle = 'orange';
ctx.strokeStyle = "orange";
ctx.moveTo(40, 40);
ctx.lineTo(70, 40);
ctx.arc(40, 40, 30, 0, Math.PI / 3, false);
ctx.fill();
ctx.moveTo(74, 40);
ctx.arc(40, 40, 34, 0, Math.PI / 3, false);
ctx.stroke();
ctx.closePath();
// 画蓝色的扇形
ctx.beginPath();
ctx.strokeStyle = "blue";
ctx.fillStyle = "blue"
ctx.arc(40, 40, 30, Math.PI / 3, 0, false);
ctx.lineTo(40, 40);
ctx.fill();
ctx.moveTo(40, 74);
ctx.arc(40, 40, 34, Math.PI / 3, 0, false);
ctx.stroke();
document.body.appendChild(canvas); 

结果如下:

3.2 透明度

我们除了通过设置绘制颜色的rgba来间接控制图案的透明度外,还可以使用属性globalAlpha来直接控制。同样的,也是以路径为单位,每个路径只有一个透明度。

小例子:

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
for (let i = 1; i <= 10; i++) {
  ctx.beginPath();
  ctx.globalAlpha = 1 - i / 10;
  ctx.arc(30, 30, 3 * i, 0, 2 * Math.PI, true);
  ctx.fill();
 }
 document.body.appendChild(canvas);

结果如下:

3.3 线条样式

canvas提供了很多属性来控制线条的样式

3.3.1 lineWidth

设置线条宽度

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
ctx.strokeStyle = 'orange'
for (let i = 0; i < 10; i++) {
  ctx.beginPath()
  ctx.moveTo(i * 20 + i, 20);
  ctx.lineWidth = i;
 ctx.lineTo(i * 20 + i, 60);
 ctx.stroke();
}
document.body.appendChild(canvas);

结果如下:

3.3.2 lineCap

设置线条末端样式,可取值有"butt"(线段末端以方形结束),"round"(线段末端以圆形结束),"square"(线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域)

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
let caps = ['butt', 'round', 'square'];
ctx.lineWidth = 8;
caps.forEach((item, index) => {
  ctx.beginPath();
  ctx.moveTo(20, 20 * index + 20);
  ctx.lineCap = item;
  ctx.lineTo(80, 20 * index + 20);
  ctx.stroke();
})
document.body.appendChild(canvas);

结果如下:

3.3.3 lineJoin

设置线条与线条间接合处的样式,可取值有"round","bevel","miter"

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
let lineJoin = ['round', 'bevel', 'miter'];
ctx.lineWidth = 10;
for (var i = 0; i < lineJoin.length; i++) {
  ctx.lineJoin = lineJoin[i];
  ctx.beginPath();
  ctx.moveTo(-5, 5 + i * 40);
  ctx.lineTo(35, 45 + i * 40);
  ctx.lineTo(75, 5 + i * 40);
  ctx.lineTo(115, 45 + i * 40);
  ctx.lineTo(155, 5 + i * 40);
  ctx.stroke();
}  
document.body.appendChild(canvas);

结果如下:

3.3.4 miterLimit

限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
ctx.lineWidth = 10;
ctx.moveTo(20, 20);
ctx.lineTo(40, 100);
ctx.lineTo(80, 20);
ctx.stroke();
//加上limit限制后
ctx.beginPath();
ctx.miterLimit = 2;
ctx.moveTo(90, 20);
ctx.lineTo(110, 100);
ctx.lineTo(150, 20);
ctx.stroke();
document.body.appendChild(canvas);

结果如下:

3.3.5 setLineDash(array)

设置线条为虚线,传入一个数字数组([长度,间距,长度,间距,......]),该数组被当做重复的最小虚线单元,如果数组长度为奇数则会被重复一遍([5,6,7]=>[5,6,7,5,6,7])

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
ctx.lineWidth = 2;
ctx.setLineDash([10, 2])
ctx.moveTo(20, 20);
ctx.lineTo(160, 20);
ctx.stroke();
document.body.appendChild(canvas);         

结果如下:

3.3.6 getLineDash()

获取当前路径的虚线数组

3.3.7 lineDashOffset

设置虚线的起始偏移量,正数向左偏移,负数向右偏移

3.4 渐变

canvas的渐变方式

1).创建一个渐变对象

2).设置渐变对象的渐变规则

通过addColorStop(position,color)方法实现,整个渐变趋势进度为0~1,而position和color表示在某个进度位置的渐变颜色,可设置多个进度颜色。

3).将渐变对象赋给fillStyle或strokeStyle属性

4).当前路径的所有绘制都具有相应的渐变效果

canvas提供了两种渐变对象,linearGradient和radialGradient

3.4.1 linearGradient

该对象通过设置两个坐标点,来表示整个路径绘制的颜色渐变趋势,常用于整体颜色渐变。

小例子:

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
let lg = ctx.createLinearGradient(0, 0, 150, 150);
lg.addColorStop(0, 'red');
lg.addColorStop(0.25, 'purple');
lg.addColorStop(0.5, 'blue')
lg.addColorStop(0.75,'orange');
lg.addColorStop(1, 'green');
ctx.fillStyle = lg;
ctx.fillRect(0, 0, 170, 170);
document.body.appendChild(canvas);

结果如下:

3.4.2 radialGradient

该对象用来实现圆心向外扩散的渐变效果,对象接收两个圆(内圆与外圆),外圆包裹着内圆,两圆之间的间距部分就是用来呈现最终的渐变效果的。

小例子:

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
let lg = ctx.createRadialGradient(40, 40, 20, 46, 46, 80);
lg.addColorStop(0, 'white');
lg.addColorStop(1, 'black');
ctx.fillStyle = lg;
ctx.fillRect(0, 0, 150, 150);
document.body.appendChild(canvas);

结果如下:

3.5 图案样式

可以使用指定的图案来绘制canvas

1).创建图案对象(img对象或canvas对象)

2).基于图案对象创建样式对象

3).将样式对象赋给strokeStyle或fillStyle

小例子:

let canvasImg = document.createElement('canvas');
canvasImg.width = 40;
canvasImg.height = 40;
let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
//创建图案
let ctxImg = canvasImg.getContext('2d');
ctxImg.fillStyle = "orange";
ctxImg.strokeStyle = "orange";
ctxImg.moveTo(0, 0);
ctxImg.lineTo(40, 0);
ctxImg.arc(0, 0, 40, 0, Math.PI / 2, false);
ctxImg.fill();
// 创建样式对象
let ctx = canvas.getContext('2d');
let ptrn = ctx.createPattern(canvasImg, 'repeat');
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, 200, 200);
document.body.appendChild(canvas);

结果如下:

3.6 阴影

canvas提供了四个属性来设置阴影样式

shadowOffsetX

表示阴影在x轴的延伸距离,正值向右延伸,负值向左延伸,默认为0

shadowOffsetY

表示阴影在y轴的延伸距离,正值向下延伸,负值向上延伸,默认为0

shadowBlur

表示阴影的模糊程度,数值越大越模糊,负值无效,默认值为0

shadowColor

表示阴影的颜色,值可取英文、rgba、十六进制值

小例子:

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
ctx.arc(40, 40, 30, 0, 2 * Math.PI, false);
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.shadowBlur = 2;
ctx.shadowColor = "orange";
ctx.stroke();
document.body.appendChild(canvas);           

结果如下:

3.7 填充规则

canvas有两种填充规则

"nonzero"

表示全填充,只要是闭合图形都进行填充(默认)

"evenodd"

只填充图形不相交的部分

小例子:

let canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext('2d');
ctx.arc(40, 40, 30, 0, 2 * Math.PI, false);
ctx.arc(50, 40, 30, 0, 2 * Math.PI, false);
ctx.fill('evenodd');
document.body.appendChild(canvas);         

结果如下:

(图片和动画后面再补充...)