<canvas> 看起来和 <img> 元素很相像,惟一的不一样就是它并无 src 和 alt 属性。实际上,<canvas> 标签只有两个属性—— width和height。当没有设置宽度和高度的时候,canvas会初始化宽度为300像素和高度为150像素。该元素可使用CSS来定义大小,但在绘制时图像会伸缩以适应它的框架尺寸:若是CSS的尺寸与初始画布的比例不一致,它会出现扭曲。
<canvas> 元素有一个作 getContext() 的方法,这个方法是用来得到渲染上下文和它的绘画功能。
咱们这里只作2d的绘画功能。javascript
<html> <head> <title>Canvas tutorial</title> <style type="text/css"> canvas { border: 1px solid black; } </style> <body onload="draw();"> <canvas id="tutorial" width="150" height="150">您的浏览器不支持canvas</canvas> </body> <script type="text/javascript"> function draw(){ var canvas = document.getElementById('tutorial'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); } } </script> </head> </html>
模板看起来会是这样。如这里所示,它最初是空白的。
一个简单例子
一开始,让咱们来看个简单的例子,咱们绘制了两个有趣的长方形,其中的一个有着alpha透明度。咱们将在接下来的例子里深刻探索一下这是如何工做的。css
<html> <head> <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } } </script> </head> <body onload="draw();"> <canvas id="canvas" width="150" height="150"></canvas> </body> </html>
效果html
在咱们开始画图以前,咱们须要了解一下画布栅格(canvas grid)以及坐标空间。上一页中的HTML模板中有个宽150px, 高150px的canvas元素。如右图所示,canvas元素默认被网格所覆盖。一般来讲网格中的一个单元至关于canvas元素中的一像素。栅格的起点为左上角(坐标为(0,0))。全部元素的位置都相对于原点定位。因此图中蓝色方形左上角的坐标为距离左边(Y轴)x像素,距离上边(X轴)y像素(坐标为(x,y))。在课程的最后咱们会平移原点到不一样的坐标上,旋转网格以及缩放。如今咱们仍是使用原来的设置。java
HTML中的元素canvas只支持一种原生的图形绘制:矩形。全部其余的图形的绘制都至少须要生成一条路径。不过,咱们拥有众多路径生成的方法让复杂图形的绘制成为了可能。canvas
首先,咱们回到矩形的绘制中。canvas提供了三种方法绘制矩形:
fillRect(x, y, width, height)
绘制一个填充的矩形
strokeRect(x, y, width, height)
绘制一个矩形的边框
clearRect(x, y, width, height)
清除指定矩形区域,让清除部分彻底透明,例如一个镂空的矩形。
上面提供的方法之中每个都包含了相同的参数。x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。width和height设置矩形的尺寸。浏览器
下面的draw() 函数是前面中取得的,如今就来使用上面的三个函数。app
function draw() { 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); } }
效果
fillRect()函数绘制了一个边长为100px的黑色正方形。clearRect()函数从正方形的中心开始擦除了一个6060px的正方形,接着strokeRect()在清除区域内生成一个5050的正方形边框。
绘制路径
图形的基本元素是路径。路径是经过不一样颜色和宽度的线段或曲线相连造成的不一样形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形须要一些额外的步骤。框架
首先,你须要建立路径起始点。
而后你使用画图命令去画出路径。
以后你把路径封闭。
一旦路径生成,你就能经过描边或填充路径区域来渲染图形。
如下是所要用到的函数:
beginPath()
新建一条路径,生成以后,图形绘制命令被指向到路径上生成路径。
closePath()
闭合路径以后图形绘制命令又从新指向到上下文中。
stroke()
经过线条来绘制图形轮廓。
fill()
经过填充路径的内容区域生成实心的图形。
生成路径:
第一步叫作beginPath()。本质上,路径是由不少子路径构成,这些子路径都是在一个列表中,全部的子路径(线、弧形、等等)构成图形。而每次这个方法调用以后,列表清空重置,而后咱们就能够从新绘制新的图形。
第二步就是调用函数指定绘制路径,本文稍后咱们就能看到了。函数
第三,就是闭合路径closePath(),不是必需的。这个方法会经过绘制一条从当前点到开始点的直线来闭合图形。若是图形是已经闭合了的,即当前点为开始点,该函数什么也不作。
绘制一个三角形spa
function draw() { var canvas = document.getElementById('canvas'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.moveTo(75,50); ctx.lineTo(100,75); ctx.lineTo(100,25); ctx.fill(); } }
效果
移动笔触
一个很是有用的函数,而这个函数实际上并不能画出任何东西,也是上面所描述的路径列表的一部分,这个函数就是moveTo()。或者你能够想象一下在纸上做业,一支钢笔或者铅笔的笔尖从一个点到另外一个点的移动过程。
moveTo(x, y)
将笔触移动到指定的坐标x以及y上。
当canvas初始化或者beginPath()调用后,你一般会使用moveTo()函数设置起点。咱们也可以使用moveTo()绘制一些不连续的路径。看一下下面的笑脸例子。我将用到moveTo()方法(红线处)的地方标记了。
你能够尝试一下,使用下边的代码片。只须要将其复制到以前的draw()函数便可。
function draw() { 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(); } }
效果
arc()函数介绍:
因为canvas中全部于角有关的API,都须要以弧度(R)来指定该角的值。三角函数也都采用弧度制。因此须要记好如下公式:
180度=π弧度
1弧度=(π/180)×度
1度=(180/π)×弧度
π=3.14,因此45度等于(3.14/180)×45度得0.7853弧度
若是你想看到连续的线,你能够移除调用的moveTo()。
线
绘制直线,须要用到的方法lineTo()。
lineTo(x, y)
绘制一条从当前位置到指定x以及y位置的直线。
该方法有两个参数:x以及y ,表明坐标系中直线结束的点。开始点和以前的绘制路径有关,以前路径的结束点就是接下来的开始点,等等。。。开始点也能够经过moveTo()函数改变。
下面的例子绘制两个三角形,一个是填充的,另外一个是描边的。
function draw() { 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(); } }
这里从调用beginPath()函数准备绘制一个新的形状路径开始。而后使用moveTo()函数移动到目标位置上。而后下面,两条线段绘制后构成三角形的两条边。
你会注意到填充与描边三角形步骤有所不一样。正如上面所提到的,由于路径使用填充(filled)时,路径自动闭合,使用描边(stroked)则不会闭合路径。若是没有添加闭合路径closePath()到描述三角形函数中,则只绘制了两条线段,并非一个完整的三角形。
圆弧
绘制圆弧或者圆,咱们使用arc()方法。固然可使用arcTo(),不过这个的现实并非那么的可靠,因此咱们这里不做介绍。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。
arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线链接两个控制点。
该方法有五个参数:x,y为绘制圆弧所在圆上的圆心坐标。radius为半径。startAngle以及endAngle参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准。参数anticlockwise 为一个布尔值。为true时,是逆时针方向,不然顺时针方向。
下面的例子比上面的要复杂一下,下面绘制了12个不一样的角度以及填充的圆弧。
下面两个for循环,生成圆弧的行列(x,y)坐标。每一段圆弧的开始都调用beginPath()。代码中,每一个圆弧的参数都是可变的,实际生活中,咱们并不须要这样作。
x,y坐标是可变的。半径(radius)和开始角度(startAngle)都是固定的。结束角度(endAngle)在第一列开始时是180度(半圆)而后每列增长90度。最后一列造成一个完整的圆。
clockwise 语句做用于第1、三行是顺时针的圆弧,anticlockwise做用于2、四行为逆时针圆弧。if 语句让1、二行描边圆弧,下面两行填充路径。
function draw() { var canvas = document.getElementById('canvas'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); for(var i=0;i<4;i++){ for(var j=0;j<3;j++){ ctx.beginPath(); var x = 25+j*50; // x 坐标值 var y = 25+i*50; // y 坐标值 var radius = 20; // 圆弧半径 var startAngle = 0; // 开始点 var endAngle = Math.PI+(Math.PI*j)/2; // 结束点 var anticlockwise = i%2==0 ? false : true; // 顺时针或逆时针 ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); if (i>1){ ctx.fill(); } else { ctx.stroke(); } } } } }
效果
贝塞尔(bezier)以及二次贝塞尔
下一个十分有用的路径类型就是 贝塞尔曲线。二次以及三次贝塞尔曲线都十分有用,通常用来绘制复杂有规律的图形。
quadraticCurveTo(cp1x, cp1y, x, y)
绘制二次贝塞尔曲线,x,y为结束点,cp1x,cp1y为控制点。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
绘制三次贝塞尔曲线,x,y为结束点,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二。
下边的图可以很好的描述二者的关系,二次贝塞尔曲线有一个开始、结束点(蓝色)以及一个控制点(红色),而三次贝塞尔曲线使用两个控制点。
参数x、y在这两个方法中都是结束点坐标。cp1x,cp1y为坐标中的第一个控制点,cp2x,cp2y为坐标中的第二个控制点。
使用二次以及三次贝塞尔曲线是有必定的难度的,由于不一样于像Adobe Illustrators这样的矢量软件,咱们所绘制的曲线没有直接的视觉反馈给咱们。这让绘制复杂的图形十分的困难。在下面的例子中,咱们会绘制一些简单有规律的图形,若是你有时间,以及更多的耐心不少复杂的图形你均可以绘制出来。
能够看我本身写的一个实际项目例子,在个人文章里有。今天就先写到这了。后面再慢慢给你们写,我也是刚刚学这个。不足之处多谅解。关注我哦^_^!