创建多条曲线
下面我们将目光转向创建多条曲线,而不仅是一条曲线,创建一条平滑的向各个方向弯曲的线。首先,来看一个错误的做法,是我原先尝试过的一种方法。从随便一个点位出发,经过第一个点到第二个点再到第三个点,经过第四个到达第五个,经过第六个到达第七个等等绘制一条曲线。这里是代码(文档类 MultiCurve1.as):
package { import flash.display.Sprite; public class MultiCurves1 extends Sprite { private var numPoints:uint = 9; public function MultiCurves1() { init(); } private function init():void { // first set up an array of random points var points:Array = new Array(); for (var i:int = 0; i < numPoints; i++) { points[i] = new Object(); points[i].x = Math.random() * stage.stageHeight; points[i].y = Math.random() * stage.stageHeight; } graphics.lineStyle(1); // now move to the first point graphics.moveTo(points[0].x, points[0].y); // and loop through each next successive pair for (i = 1; i < numPoints; i += 2) { graphics.curveTo(points[i].x, points[i].y,
points[i + 1].x, points[i + 1].y); } } } }
第一次循环在 init 方法中,建立一个数组存储九个点。每个点都是一个 object 拥有 x,y 属性,它们的值都是舞台尺寸的随机数。当然,在一个真正的程序中,点位也许不是随机的,只是用这种方法进行快速设置。
随后设置线条样式,将笔移动到第一个点位。下一个循环从1开始每次递增2,所以线条是经过第一点到达第二点,然后从第三点到第四点,再从第五点到第六点,最后从第七点到第八点。至此,循环停止,因为第八点是最后一个点。大家也许注意到了,这里至少要有三个点,而且点的数量必需为奇数个。
程序看起来还不错,测试一下试试。如图4-1所示,看起来不是非常平滑,有棱有角的,这是因为曲线之间没有进行协调,它们之间共用了一个点。
图4-1 多条曲线,错误的方法。我们可以清楚地看到曲线的结束和开始的位置。
我们也许不得不去加入更多的点才能使解决这个问题。这里有个策略:在每两对点之间,加入一个新点(中间点)放在这两点的正中间。然后使用这些中间点作为起点和终点,而把最初的那些点(原始点)作为控制点。
图4-2 说明了解决办法。在图中,白点为原始点,黑点为中间点。这里使用了三条 curveTo 方法,图中的点使用了不同的颜色,这样就能分辨出起点与终点了。(图4-2 是 multicurvedemo.fla 文件的一张截图,可以在 www.friendsofted.com 的 books 页面下载)
图4-2 带有中间点的多线条
注意,图4-2中第一个中间点和最后一个中间点都没有被使用,第一个和最后一个原始点留作曲线的两个端点,只需在第二个点和倒数第二个点之间进行连接。这里是前一个例子的升级版,文档类 MultiCurve2.as:
package { import flash.display.Sprite; public class MultiCurves2 extends Sprite { private var numPoints:uint = 9; public function MultiCurves2() { init(); } private function init():void { // first set up an array of random points var points:Array = new Array(); for (var i:int = 0; i < numPoints; i++) { points[i] = new Object(); points[i].x = Math.random() * stage.stageHeight; points[i].y = Math.random() * stage.stageHeight; } graphics.lineStyle(1); // now move to the first point graphics.moveTo(points[0].x, points[0].y); // curve through the rest, stopping at each midpoint for (i = 1; i < numPoints - 2; i ++) { var xc:Number = (points[i].x + points[i + 1].x) / 2; var yc:Number = (points[i].y + points[i + 1].y) / 2; graphics.curveTo(points[i].x, points[i].y, xc, yc); } // curve through the last two points graphics.curveTo(points[i].x, points[i].y, points[i+1].x, points[i+1].y); } } }
请注意,在新代码中, for 循环从1开始到 points.length -2 结束,也就避开了第一个点和最后一个点。程序要做的是,创建新的 x,y 点,这个点是数组中后面两个点位的平均值。然后从数组下一个点位开始画一条曲线到新的平均点(中间点)。当循环结束时, i 变量指向倒数第二个元素,因此,可以穿过这里向最后一个点画条曲线。
这时,就得到一个非常平滑的图形,见图4-3。注意,这时原始点的数量不再受奇数个的限制。
再加一点小小的变化,使用同样的技术创建一条封闭的曲线。首先,计算一个初始的中间点,并移动到这里。然后,进行循环,获得每一个中间点,最后,将最后一条曲线画回初始中间点。图4-4 为显示结果
图4-3 多条平滑曲线
package { import flash.display.Sprite; public class MultiCurves3 extends Sprite { private var numPoints:uint = 9; public function MultiCurves3() { init(); } private function init():void { var points:Array = new Array(); for (var i:int = 0; i < numPoints; i++) { points[i] = new Object(); points[i].x = Math.random() * stage.stageHeight; points[i].y = Math.random() * stage.stageHeight; } // find the first midpoint and move to it var xc1:Number = (points[0].x + points[numPoints - 1].x) / 2; var yc1:Number = (points[0].y + points[numPoints - 1].y) / 2; graphics.lineStyle(1); graphics.moveTo(xc1, yc1); // curve through the rest, stopping at midpoints for (i = 0; i < numPoints - 1; i ++) { var xc:Number = (points[i].x + points[i + 1].x) / 2; var yc:Number = (points[i].y + points[i + 1].y) / 2; graphics.curveTo(points[i].x, points[i].y, xc, yc); } // curve through the last point, back to the first midpoint graphics.curveTo(points[i].x, points[i].y, xc1, yc1); } } }
图4-4 多条封闭曲线
使用 beginFill 和 endFill 创建图形 beginFill(color, alpha) 方法非常简单,没有太多可说的。有一点值得注意,同 lineStyle 一样, alpha 的取值范围也变为了 0.0 到 1.0,而不是 0 到 100,这项也是可选的,默认为1.0。无论何时执行该帧的绘图代码 Flash 都会开始进行计算,无论何时遇到 endFill 指令 Flash 都会停止计算。总结一下,过程如下:
- moveTo
- lineStyle (如果有参数可以填入)
- beginFill
- 在一系列的 lineTo 和 curveTo 方法后,要在最初的点位结束
- endFill
事实上,使用前三个方法的顺序不会影响到绘图。我们不是必需要指定线条样式,请记住如果不指定线条样式就会得到一条看不见的线条,非常适合绘制填充色,当然两者同时绘制也不错。如果所绘制的线条没有回到最初开始的点位,一但调用了 endFill, Flash 将会自动绘制一条封闭线,是为了能封闭这个图形。调用 endFill 后,无论线条样式如何,都会自动将最后一条线绘制完成。当然,我们自己将线条封闭是个很好的习惯,这样一来,既确保了最后的能够正确绘制,又可以让看代码的人知道我们究竟想画的是什么图形。
下面来试一下绘制填充色,可以使用前面的封闭曲线示例(MultiCurve3.as)来完成,这里已生成了一个封闭的图形。只要将 beginFill 语句放在第一条 curveTo 前面的任何地方——如 beginFill(0xff00ff);,这样就创建了亮紫色的填充——最后使用 endFill() 结束。
出处:蓝色理想
责任编辑:bluehearts
上一页 渲染技术 [5] 下一页 渲染技术 [7]
◎进入论坛RIA设计与应用版块参加讨论
|