canvas教程

Canvas绘图中的路径描边与填充(2)

字号+ 作者:H5之家 来源:H5之家 2017-03-02 16:01 我要评论( )

现在考虑一下,如果将第二个beginPath()调用去掉,会怎么样呢?像是这样: context.beginPath();//Clear all subpaths from the//current pathcontext.rect(10,10,100,100);//Add a subpath with four pointscontex

现在考虑一下,如果将第二个beginPath()调用去掉,会怎么样呢?像是这样:

context.beginPath(); //Clear all subpaths from the //current path context.rect(10,10,100,100);//Add a subpath with four points context.stroke(); //Stroke the subpath containing //four points context.rect(50,50,100,100);//Add a second subpath with //four points context.stroke(); //Stroke both subpaths

面这段代码在一开始与刚才那段是一样的:先调用beginPath()来清除当前路径中的所有子路径,然后调用rect()来创建一条包含矩形4个点的子路径,再调用stroke()方法使得这个矩形出现在canvas之上。

接下来,这段代码再次调用了rect()方法,不过这一次,由于没有调用beginPath()方法来清除原有的子路 径,所以第二次对rect()方法的调用,会向当前路径中增加一条子路径。最后,该段代码再一次调用stroke()方法,这次对stroke()方法的 调用,将会使得当前路径中的两条子路径都被描边,这意味着它会重绘第一个矩形。

填充路径时所使用的“非零环绕规则”

如果当前路径是循环的,或是包含多个相交的子路径,那么Canvas的绘图环境变量就必须要判断,当fill()方法被 调用时,应该如何对当前路径进行填充。Canvas在填充那种互相有交叉的路径时,使用“非零环绕规则”(nonzero winding rule)来进行判断。图2-14演示了该规则的运用。

“非零环绕规则”是这么来判断有自我交叉情况的路径的:对于路径中的任意给定区域,从该区域内部画一条足够长的线段,使此线段的终点完全落在路径范围之外。图2-14中的那三个箭头所描述的就是上面这个步骤。

图 2-14 在填充路径时运用“非零环绕规则”来进行判断

接下来,将计数器初始化为0,然后,每当这条线段与路径上的直线或曲线相交时,就改变计数器的值。如果是与路径的顺时针 部分相交,则加1,如果是与路径的逆时针部分相交,则减1。若计数器的最终值不是0,那么此区域就在路径里面,在调用fill()方法时,浏览器就会对其 进行填充。如果最终值是0,那么此区域就不在路径内部,浏览器也就不会对其进行填充了。

可以从图2-14中看出“非零环绕规则”是如何运用的。左边的那个带箭头的线段,先穿过了路径的逆时针部分,然后又穿过 了路径的顺时针部分。这意味着其计数值是0,所以该线段起点所在的那个区域就不在范围内,在调用fill()方法时,浏览器也就不会对其进行填充。然而, 其余两条带箭头的线段,其计数值都不是0,所以它们的起点所在的区域就会被浏览器填充。

3. 剪纸效果

我们来运用一下所学到的路径、阴影以及非零环绕原则等知识,实现如图2-15所示的剪纸(cutout)效果。

图 2-15 用两个圆形做出的剪纸效果

图2-15所示的应用程序,其JavaScript代码列在了程序清单2-10之中。

这段JavaScript代码创建了一条路径,它由两个圆形所组成,其中一个圆形在另一个的内部。通过设定arc()方法的最后一个参数值,该应用程序以顺时针方向绘制了内部的圆形,并且以逆时针方向绘制了外围的圆形。绘制效果如图2-16上方所示。

图 2-16 运用“非零环绕规则”来实现剪纸效果

在创建好路径之后,图2-15中的那个应用程序对该路径进行了填充。浏览器运用“非零环绕规则”,对外围圆形的内部进行了填充,不过填充的范围并不包括里面的圆,这就产生了一种剪纸图案的效果。你也可以利用此技术来剪出任意想要的形状来。

程序清单2-10 图2-15所示应用程序的JavaScript代码

var context=document.getElementById("canvas").getContext("2d"); //Functions... function drawGrid(color,stepx,stepy){ //Listing omitted for brevity.See Example 2.13 //for a complete listing. function drawTwoArcs(){ context.beginPath(); context.arc(300,190,150,0,Math.PI*2,false);//Outer:CCW context.arc(300,190,100,0,Math.PI*2,true);//Inner:CW context.fill(); context.shadowColor=undefined; context.shadowOffsetX=0; context.shadowOffsetY=0; context.stroke(); function draw(){ context.clearRect(0,0,context.canvas.width, context.canvas.height); } } drawGrid("lightgray",10,10); context.save(); context.shadowColor="rgba(0,0,0,0.8)"; context.shadowOffsetX=12; context.shadowOffsetY=12; context.shadowBlur=15; drawTwoArcs(); context.restore(); } //Initialization... context.fillStyle="rgba(100,140,230,0.5)"; context.strokeStyle=context.fillStyle; draw();



更多关于 的文章

·上一篇:jQuery自定义事件
·下一篇:JavaScript设计模式之观察者模式

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • html5 Canvas画图2:画线条

    html5 Canvas画图2:画线条

    2017-03-02 14:00

  • HTML5 canvas绘图的redo和undo功能的实现

    HTML5 canvas绘图的redo和undo功能的实现

    2017-03-02 14:00

  • canvas画图--流畅没有齿痕的线,图像画线

    canvas画图--流畅没有齿痕的线,图像画线

    2017-03-02 13:01

  • Canvas -画图

    Canvas -画图

    2017-03-02 12:18

网友点评
o