Canvas-绘制图形
绘制形状
canvas元素默认被网格所覆盖。通常来说网格中的一个单元相当于canvas元素中的一像素。栅格的起点为左上角(坐标为(0,0))。所有元素的位置都相对于原点定位。所以图中蓝色方形左上角的坐标为距离左边(X轴)x像素,距离上边(Y轴)y像素(坐标为(x,y))。
路径path
路径绘制图形步骤:
- 创建路径起始点,
beginPath()
新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。 - 使用画图命令去画出路径,如:
ctx.strokeRect(50, 50, 50, 50)
- 封闭路径,
closePath()
闭合路径之后图形绘制命令又重新指向到上下文中,不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。 - 一旦路径生成,就能通过描边或填充路径区域来渲染图形。
stroke()
通过线条来绘制图形轮廓;fill()
通过填充路径的内容区域生成实心的图形。
直线lineTo
语法:
context.lineTo(x, y);
参数 | 描述 |
---|---|
x | 路径的目标位置x坐标 |
y | 路径的目标位置y坐标 |
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
// 填充三角形
ctx.beginPath();
ctx.moveTo(25,25);
ctx.lineTo(105,25);
ctx.lineTo(25,105);
ctx.fill();
// 描边三角形
ctx.beginPath();
ctx.moveTo(125,125);
ctx.lineTo(125,45);
ctx.lineTo(45,125);
ctx.closePath();
ctx.stroke();
}
矩形rect
语法:
context.rect(x, y, width, height);
context.fillRect(x, y, width, height);
context.clearRect(x, y, width, height);
context.strokeRect(x, y, width, height);
参数值:
参数 | 描述 |
---|---|
x | 矩形左上角的 x 坐标 |
y | 矩形左上角的 y 坐标 |
width | 矩形的宽度,以像素计 |
height | 矩形的高度,以像素计 |
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25, 25, 100, 100);
ctx.clearRect(45, 45, 60, 60);
ctx.strokeRect(50, 50, 50, 50);
// 红色矩形
ctx.beginPath();
ctx.lineWidth="6";
ctx.strokeStyle="red";
ctx.rect(0,0,150,150);
ctx.stroke();
}
fillRect()
函数绘制了一个边长为100px的黑色正方形。clearRect()
函数从正方形的中心开始擦除了一个6060px的正方形,接着strokeRect()
在清除区域内生成一个5050的正方形边框。
绘制三角形
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(75, 50); //moveTo(x, y) 将笔触移动到指定的坐标x以及y上。
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill();
}
圆形arc
语法:
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
参数值:
参数 | 描述 |
---|---|
x | 圆的中心的 x 坐标。 |
y | 圆的中心的 y 坐标。 |
r | 圆的半径。 |
sAngle | 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。 |
eAngle | 结束角,以弧度计。 |
counterclockwise | 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。 |
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // 绘制
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // 口(顺时针)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true); // 左眼
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true); // 右眼
ctx.stroke();
// 无moveTo则展现完整路径
ctx.beginPath();
ctx.strokeStyle="red";
ctx.arc(175,75,50,0,Math.PI*2,true); // 绘制
//ctx.moveTo(210,75);
ctx.arc(175,75,35,0,Math.PI,false); // 口(顺时针)
//ctx.moveTo(165,65);
ctx.arc(160,65,5,0,Math.PI*2,true); // 左眼
//ctx.moveTo(195,65);
ctx.arc(190,65,5,0,Math.PI*2,true); // 右眼
ctx.stroke();
}
圆弧arcTo
语法:
arcTo(x1, y1, x2, y2, radius)
参数 | 描述 |
---|---|
x1 | 切线起点的 x 坐标。 |
y1 | 切线起点的 y 坐标。 |
x2 | 切线终点的 x 坐标。 |
y2 | 切线终点的 y 坐标。 |
r | 圆的半径。 |
点(x1, y1)
分别与点(x2, y2)
及当前笔触点(x0, y0)
构成两条切线,绘制的弧线是两个切点之间以r为半径的最短圆弧。
/*
*
* ctx 画布
* x , y 左上角坐标
* width, height 矩形宽高
* r 弧形半径
* */
function drawRoundedRect(ctx, x, y, width, height, r) {
ctx.save();
ctx.beginPath();
// draw top and top right corner
ctx.moveTo(x + r, y);
ctx.arcTo(x + width, y, x + width, y + r, r);
// draw right side and bottom right corner
ctx.arcTo(x + width, y + height, x + width - r, y + height, r);
// draw bottom and bottom left corner
ctx.arcTo(x, y + height, x, y + height - r, r);
// draw left and top left corner
ctx.arcTo(x, y, x + r, y, r);
ctx.fill();
ctx.stroke();
ctx.restore();
}
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
drawRoundedRect(ctx, 20, 20, 100, 100, 10);
}
贝塞尔曲线
贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,
二阶贝塞尔
原理:AD/AB = BE/BC = DF/DE语法:
context.quadraticCurveTo(cpx,cpy,x,y);
参数值:
参数 | 描述 |
---|---|
cpx | 贝塞尔控制点的 x 坐标 |
cpy | 贝塞尔控制点的 y 坐标 |
x | 结束点的 x 坐标 |
y | 结束点的 y 坐标 |
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// 二次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(75,25);
ctx.quadraticCurveTo(25,25,25,62.5);
ctx.quadraticCurveTo(25,100,50,100);
ctx.quadraticCurveTo(50,120,30,125);
ctx.quadraticCurveTo(60,120,65,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();
}
三阶贝塞尔
语法:
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
参数值:
参数 | 描述 |
---|---|
cp1x | 第一个贝塞尔控制点的 x 坐标 |
cp1y | 第一个贝塞尔控制点的 y 坐标 |
cp2x | 第二个贝塞尔控制点的 x 坐标 |
cp2y | 第二个贝塞尔控制点的 y 坐标 |
x | 结束点的 x 坐标 |
y | 结束点的 y 坐标 |
四阶贝塞尔
五阶贝塞尔
Path2D 对象
Path2D用来缓存或记录绘画命令,这样你将能快速地回顾路径。
Path2D()会返回一个新初始化的Path2D对象(可能将某一个路径作为变量——创建一个它的副本,或者将一个包含SVG path数据的字符串作为变量)。
new Path2D(); // 空的Path对象
new Path2D(path); // 克隆Path对象
new Path2D(d); // 从SVG建立Path对象
所有的路径方法比如moveTo, rect, arc或quadraticCurveTo等,如我们前面见过的,都可以在Path2D中使用。
Path2D API 添加了 addPath作为将path结合起来的方法。当你想要从几个元素中来创建对象时,这将会很实用。比如:
Path2D.addPath(path [, transform])
添加了一条路径到当前路径(可能添加了一个变换矩阵)。
Path2D可以使用SVG path data来初始化canvas上的路径。
var p = new Path2D("M10 10 h 80 v 80 h -80 Z");
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
var rectangle = new Path2D();
rectangle.rect(10, 10, 50, 50);
var circle = new Path2D();
circle.moveTo(125, 35);
circle.arc(100, 35, 25, 0, 2 * Math.PI);
ctx.stroke(rectangle);
ctx.fill(circle);
}