2.7 路径、描边与填充
迄今为止,在本章之中我们所绘制的唯一图形,就是通过在Canvas的绘图环境对象上调用strokeRect()方法所画的矩形。我们也通过调用fillRect()方法对其进行了填充。这两个方法都是立即生效的。实际上,它们是Canvas绘图环境中仅有的两个可以用来立即绘制图形的方法(strokeText()与fillText()方法也是进行立即绘制的,但文本不算是图形)。绘图环境对象中还有一些方法,用于绘制诸如贝塞尔曲线(bézier curve)这样更为复杂的图形,这些方法都是基于路径(path)的。
大多数绘制系统,例如Scalable Vector Graphics (可缩放向量图形,简称SVG)、Apple的Cocoa框架,以及Adobe Illustrator等,都是基于路径的。使用这些绘制系统时,你需要先定义一个路径,然后再对其进行描边(也就是绘制路径的轮廓线)或填充,也可以在描边的同时进行填充。图2-13演示了这三种绘制方式。
该应用程序创建了9个不同的路径,对左边一列的路径进行了描边操作,对中间一列的路径进行了填充,并对右边一列的路径同时进行描边与填充。
第一行的矩形路径与最后一行的圆弧路径都是封闭路径(closed path),而中间一行的弧形路径则是开放路径(open path)。请注意,不论一个路径是开放或是封闭,你都可以对其进行填充。当填充某个开放路径时,浏览器会把它当成封闭路径来填充。图中右边一列的中间那个图形,就是这种效果。
程序清单2-9列出了图2-13中那个应用程序的代码。
程序清单2-9 文本、矩形与圆弧的描边及填充
- var context =document.getElementById('drawingCanvas').getContext('2d');
- // Functions..........................................................
- function drawGrid(context, color, stepx, stepy) {
- // Listing omitted for brevity. See Example 2.13
- // for a complete listing.
- }
- // Initialization.....................................................
- drawGrid(context, 'lightgray', 10, 10);
- // Drawing attributes.................................................
- context.font = '48pt Helvetica';
- context.strokeStyle = 'blue';
- context.fillStyle = 'red';
- context.lineWidth = '2'; // Line width set to 2 for text
- // Text...............................................................
- context.strokeText('Stroke', 60, 110);
- context.fillText('Fill', 440, 110);
- context.strokeText('Stroke & Fill', 650, 110);
- context.fillText('Stroke & Fill', 650, 110);
- // Rectangles.........................................................
- context.lineWidth = '5'; // Line width set to 5 for shapes
- context.beginPath();
- context.rect(80, 150, 150, 100);
- context.stroke();
- context.beginPath();
- context.rect(400, 150, 150, 100);
- context.fill();
- context.beginPath();
- context.rect(750, 150, 150, 100);
- context.stroke();
- context.fill();
- // Open arcs..........................................................
- context.beginPath();
- context.arc(150, 370, 60, 0, Math.PI*3/2);
- context.stroke();
- context.beginPath();
- context.arc(475, 370, 60, 0, Math.PI*3/2);
- context.fill();
- context.beginPath();
- context.arc(820, 370, 60, 0, Math.PI*3/2);
- context.stroke();
- context.fill();
- // Closed arcs........................................................
- context.beginPath();
- context.arc(150, 550, 60, 0, Math.PI*3/2);
- context.closePath();
- context.stroke();
- context.beginPath();
- context.arc(475, 550, 60, 0, Math.PI*3/2);
- context.closePath();
- context.fill();
- context.beginPath();
- context.arc(820, 550, 60, 0, Math.PI*3/2);
- context.closePath();
- context.stroke();
- context.fill();
首先调用beginPath()方法来开始一段新的路径,rect()与arc()方法分别用于创建矩形及弧形路径。然后,应用程序在绘图环境对象上调用stroke()与fill()方法,对刚才那些路径进行描边或填充。
描边与填充操作的效果取决于当前的绘图属性,这些属性包括了lineWidth、strokeStyle、fillStyle以及阴影属性等。比如,程序清单2-9中的这个应用程序,将lineWidth属性值设置为2,然后对文本进行描边,其后又将其重置为5,再对路径进行描边。
由rect()方法所创建的路径是封闭的,然而,arc()方法创建的圆弧路径则不封闭,除非你用它创建的是个圆形路径。要封闭某段路径,必须像程序清单2-9中那样,调用closePath()方法才行。
表2-5总结了本应用程序中与路径相关的方法。
表2-5 CanvasRenderingContext2D之中与路径有关的方法
提示:路径与隐形墨水
有一个很恰当的比喻,可以用来说明“创建路径随后对其进行描边或填充”这个操作。我们可以将该操作比作“使用隐形墨水来绘图”。
你用隐形墨水所绘制的内容并不会立刻显示出来,必须进行一些后续操作,像是加热、涂抹化学药品、照射红外线等,才可以将你所画的内容显示出来。如果读者关注这个话题,可以在http://en.wikipedia.org/wiki/Invisible_ink读到所有关于隐形墨水的知识。
使用rect()与arc()这样的方法来创建路径,就好比使用隐形墨水来进行绘制一样。这些方法会创建一条不可见的路径,稍后可以调用stroke()或fill()令其可见。