这个例子使用arc()绘制了两个圆:内外各一,用于创建钟的边框。外圆半径为99像素,中心在(100,100),也就是画布的中心。要绘制一个完整的圆,必须起始于0度角,画整一圈至2π个弧度(使用Math.PI进行计算)。在绘制内圆之前,路径必须移动到一个圆所在的新点,以面绘制额外的线条。第二次调用arc()使用了缩小的半径以到达边框效果。之后,组合使用moveTo()和lineTo()绘制了时针和分针。最后一步是调用stroke(),让图形显示。
路径是2D绘图环境的主要绘制机制,因为它们让开发人员能更好地控制要画什么。由于路径使用频繁,还有个方法叫做isPointInPath(),接受一个x坐标和y坐标作为参数。该方法可以在路径关闭之前任意时间点调用,来判断某个点是否在于路径之上,如下所示:
if (context.isPointInPath(100, 100)) { alert("Point(100, 100) is in the path."); }2D绘图环境的路径API十分强健,足够使用多种填充样式、画笔样式和其它样式创建复杂的图形。
3.cnavas绘制文本由于常常需要混合文本和图形,2D绘图环境提供了绘制文本的方法。有两个绘制文本的方法:fillText()和strokeText(),两者都接受4个参数:要绘制的字符串、X坐标、Y坐标和可选的最大像素度。两者都根据一下3个属性进行绘制。
各个属性都有一个默认的值,所以并非每次绘制文本都要对它进行设置。fillText()方法使用fillStyle()属性绘制文本,而strokeText()方法使用strokeStyle属性。大多数时候可能是使用fillText(),因为它能在网页上模仿普通的文本呈现。例如,在上一篇文章实例中为闹钟添加文字“12”:
var drawing = document.getElementById("drawing"); //确保完全支持<canvas> if (drawing.getContext) { var context = drawing.getContext("2d"); //填充画布 context.fillStyle = "#EEEEFF"; context.fillRect(0, 0, 200, 200); //路径开始 context.beginPath(); //绘制外圆 context.arc(100, 100, 99, 0, 2 * Math.PI, false); //绘制内圆 context.moveTo(194, 100); context.arc(100, 100, 94, 0, 2 * Math.PI, false); //绘制分针 context.moveTo(100, 100); context.lineTo(100, 15); //绘制时针 context.moveTo(100, 100); context.lineTo(35, 100); //路径描边 context.stroke(); //绘制文本 context.font = "bold 10px Arial"; context.textAlign = "center"; context.textBaseline = "midddle"; context.fillText("12", 100, 18); }文本绘制是比较复杂的一个绘图操作,所以,尚未在支持<canvas>元素的主要浏览器中实现。
4.canvas变换环境变换允许对绘制在画布上的图像执行操作。2D绘图环境支持所有基本的绘图变换。当创建了绘图环境,,变形矩阵便已经初始化了默认值,可以让所有的绘图操作直接按照所描述的那样直接呈现。对绘图环境进行变换,可以让绘图操作应用一个不同的变换矩阵并产生一个不同的结果。
变换矩阵可以使用以下方法扩张。
变换可以根据需要简单或复杂。比如,如果能将原点变换到钟的中心,那么绘制钟的指针就更加容易了。如下:
var drawing = document.getElementById("drawing"); //确保完全支持<canvas> if (drawing.getContext) { var context = drawing.getContext("2d"); //填充画布 context.fillStyle = "#EEEEFF"; context.fillRect(0, 0, 200, 200); //路径开始 context.beginPath(); //绘制外圆 context.arc(100, 100, 99, 0, 2 * Math.PI, false); //绘制内圆 context.moveTo(194, 100); context.arc(100, 100, 94, 0, 2 * Math.PI, false); //转换到中心 context.translate(100, 100); //绘制分针 context.moveTo(0, 0); context.lineTo(0, -85); //绘制时针 context.moveTo(0, 0); context.lineTo(-65, 0); //路径描边 context.stroke(); }在转换原点到钟的中心(100,100)之后,绘制同一个方向上的直线就是简单的算数问题了。现在的计算都是基于(0,0)而不是(100,100)。更进一步,可以如下是使用rotate()方法旋转钟的指针:
var drawing = document.getElementById("drawing"); //确保完全支持<canvas> if (drawing.getContext) { var context = drawing.getContext("2d"); //路径开始 context.beginPath(); //绘制外圆 context.arc(100, 100, 99, 0, 2 * Math.PI, false); //绘制内圆 context.moveTo(194, 100); context.arc(100, 100, 94, 0, 2 * Math.PI, false); //转换到中心 context.translate(100, 100); //旋转指针 context.rotate(1); //绘制分针 context.moveTo(0, 0); context.lineTo(0, -85); //绘制时针 context.moveTo(0, 0); context.lineTo(-65, 0); //路径描边 context.stroke(); }由于原点已经转移到了钟的中心,所以旋转是根据点进行的。也就是说,两个指针都以中心为锚并顺时针旋转。
所有这些变换(包括像fillStyle和strokeStyle之类的属性)都保持环境设置直到显式更改。虽然没有明确的重置它们的方式,但有两个方法可以帮助追踪变化。一旦想要能回退到特定的属性和变换集合,可以调用save()方法。调用这个方法之后,当前所有的设置都会推到一个栈中保存,然后可以继续对环境进行其他更改。当你想回到之前的设置,可以调用restore(),它会从设置栈上弹出设置并恢复它。你可以不断调用save()存储更多的设置,然后系统地调用restore()回退。例子:
var drawing = document.getElementById("drawing"); //确保完全支持<canvas> if (drawing.getContext) { var context = drawing.getContext("2d"); //填充画布 context.fillStyle = "#EEEEFF"; context.fillRect(0, 0, 200, 200); context.fillStyle = "#ff0000"; context.save(); context.fillStyle = "#00ff00"; context.translate(100, 100); context.save(); context.fillStyle = "#0000ff"; context.fillRect(0, 0, 100, 200); //在(100,100)绘制一个蓝色的矩形 context.restore(); context.fillRect(10, 10, 100, 200); //在(100, 100)处绘制一个绿色的矩形 context.restore(); context.fillRect(0, 0, 100, 200); //在(0,0)处绘制一个红色的矩形 }这段代码中,fillStyle设成了红,然后调用了save()。接下来,fillStyle变成了绿色,然后坐标有移动到了(100,100)。然后再次调用save()来保存这些设置。