Canvas使用教程——几何图形绘制(Drawing shapes)
原文:http://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes
The grid
在我们开始绘制图形前,我们先探讨一下canvas中的网格及坐标空间。在前一篇教程中,我们定义了一个150*150的canvas区域,并在该区域绘制了一个图形。在canvas区域中,以左上角为坐标原点(0,0),坐标最小单位为1px。区域内所有元素相对与原点定位。不过在以后的实例中,我们还会向你展示如何重定义坐标原点、旋转坐标甚至是重新定义坐标单位,但是现在,我们还是从默认设置开始学习。
Drawing shapes
与SVG语法不同的是,canvas只提供了一个绘制矩形的语法,其他形状的绘制就必须依靠路径功能来绘制了,哈哈,其实我们已经收集了很多多绘制各种复杂多边形的function,拿来就能用喽。
Rectangles
首先让我们来看下,目前有三种绘制矩形的语法:
fillRect(x,y,width,height) : 绘制一个实心的举行 strokeRect(x,y,width,height) : 绘制一个矩形边框 clearRect(x,y,width,height) : 绘制一个透明的矩形
以上三种方法中都有x和y参数,这对参数的值就是相对于canvas原点(左上角)的距离。
以下代码为之前教程中出现过的draw()函数,我们这次将三种矩形绘制的方法都写进去:
function draw(){ var canvas = document.getElementById('tutorial'); 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函数绘制了一个100*100的大矩形,clearRect函数从这个矩形挖掉了一块60*60的矩形并且strokeRect函数又绘制了一个50*50的矩形边框。在以后的教材中我们将看到另外的clearRect方法以及我们如何为矩形填充不同的颜色和绘制不同的边框。
与接下来我们要讲的path方法不同,以上三个矩形绘制方法执行后都会立即应用到canvas区域内。
Drawing paths
用路径来绘制多边形,以下这些方法我们都是需要的:
beginPath() closePath() stroke() fill()
第一步,我们使用beginPath方法声明一个路径,路径的绘制需要用到一系列字方法(lines,arcs,ect)共同配合来完成一个多边形,每次我们用到路径来绘制多边形时,我们都需要声明一个beginPath来开始绘制。
第二步,我们将需要调用一些特定方法来绘制我们需要的路径,我们很快就会了解到。
第三步,closePath,是一个可选步骤,这个方法将封闭绘制路径的起点,如果该多边形已经被封闭,那么,这个方法将不产生任何作用。
最后的步骤,是运用stroke或者fill方法,为绘制好的多边形路径填充颜色或者描边。
注意:如果用fill方法填充一个未封闭的多边形时,该多边形将被自动封闭,无需closePath帮忙了。
例如,以下代码将会绘制一个简单的三角形:
ctx.beginPath(); ctx.moveTo(75,50); ctx.lineTo(100,75); ctx.lineTo(100,25); ctx.fill();
moveTo
这是一个非常有用的函数,虽然该函数不会绘制任何东西,但是它是路径描述中的一个重要的功能。
moveTo函数将传入2个参数,x坐标和y坐标,以该坐标点为一个新的绘制起点。
当canvas初始化或者beginPath方法执行后,最起始的坐标点默认是(0,0),在绝大多数的应用中,我们会用moveTo方法来定位路径绘制的起点。我们亦可以用此方法绘制一些没有连接的路径,比如右边的这张笑脸图,用红色线条标识出来的就是用moveTo方法来实现的。
示例:
ctx.beginPath(); ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle ctx.moveTo(110,75); ctx.arc(75,75,35,0,Math.PI,false); // Mouth (clockwise) ctx.moveTo(65,65); ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye ctx.moveTo(95,65); ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye ctx.stroke();
Lines
顾名思义,画直线的方法。
lineTo(x, y)
该方法带的2个参数为线段终点的坐标,起点坐标则依赖于上一个路径所申明的终点,当然该线段的起点也可以是由moveTo方法所申明的坐标。
示例:如右边的图片所示,我们绘制了2个三角形,一个做填充,一个做描边。首先用beginPath方法申明一个新的路径绘制,用moveTo方法定义绘制起点。
你可能会注意到绘制实心和空心的三角形,其语法略有差异,那是因为当一个多边形需要填充时,其会自动封闭路径的始末端。
// Filled triangle ctx.beginPath(); ctx.moveTo(25,25); ctx.lineTo(105,25); ctx.lineTo(25,105); ctx.fill(); // Stroked triangle ctx.beginPath(); ctx.moveTo(125,125); ctx.lineTo(125,45); ctx.lineTo(45,125); ctx.closePath(); ctx.stroke();
Arcs
该方法为绘制弧线或者圆形路径时使用,该方法另一个写法为arcTo,不过该写法仅仅用于safari浏览器,而不会兼容采用Gecko为核心的浏览器。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
该方法接收N个参数:x和y为该段弧线所对应的原点坐标;radius为半径;startAngle和endAngle则决定了该段弧线的2个端点,起始和结束的角度以坐标系X轴为衡量基准;anticlockwise为一个布尔值参数,当为true时则逆时针方向画狐,反之则顺时针。
警告:在firefox的某些beta版本中,最后一个参数被定义为clockwise,请确保将你的浏览器版本升级至最终发布版本。
注意:在本表达式中的Angle是以弧度为单位呈现的,实际运用中,我们经常需要在角度与弧度之间做一个转换,其JS的转换表达式为:var radians = (Math.PI/180)*degrees
示例:
for (i=0;i<4;i++){ for(j=0;j<3;j++){ ctx.beginPath(); var x = 25+j*50; // x coordinate var y = 25+i*50; // y coordinate var radius = 20; // Arc radius var startAngle = 0; // Starting point on circle var endAngle = Math.PI+(Math.PI*j)/2; // End point on circle var anticlockwise = i%2==0 ? false : true; // clockwise or anticlockwise ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise); if (i>1){ ctx.fill(); } else { ctx.stroke(); } } }
Bezier and quadratic curves
如果我们需绘制更加复杂的曲线路径,我们或许该用到贝塞尔或者2次方程曲线。
quadraticCurveTo(cp1x, cp1y, x, y) // BROKEN in Firefox 1.5 (see work around below) bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
两种曲线有何区别?我们可以参看一下右边这张图,2种曲线都有一个起点和终点(blue point),但是贝塞尔曲线仅有一个“control point”(red point),2次曲线则有2个。
两个方法中的x和y参数都为曲线的终点坐标,cp1x和cp1y为第一control point的坐标,cp2x和cp2y为2次曲线的第二控制点。
熟练运用2次曲线和贝塞尔曲线进行路径绘制,是一件蛮有挑战性的工作,因为它不像某些矢量绘图软件,比如ADOBE Illustrator等具有直观的视觉反馈,所以这使得我们在绘制一些复杂的曲线时会遇到一点小困难,不过如果你有耐心和时间的话,你肯定能绘制出许多复杂的曲线来。
二次曲线示例:
// Quadratric curves example 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();
贝塞尔曲线示例:
// Bezier curves example ctx.beginPath(); ctx.moveTo(75,40); ctx.bezierCurveTo(75,37,70,25,50,25); ctx.bezierCurveTo(20,25,20,62.5,20,62.5); ctx.bezierCurveTo(20,80,40,102,75,120); ctx.bezierCurveTo(110,102,130,80,130,62.5); ctx.bezierCurveTo(130,62.5,130,25,100,25); ctx.bezierCurveTo(85,25,75,37,75,40); ctx.fill();
加支付宝好友偷能量挖...