Flash绘图.docx
《Flash绘图.docx》由会员分享,可在线阅读,更多相关《Flash绘图.docx(14页珍藏版)》请在冰豆网上搜索。
Flash绘图
Flash快速入门:
AS3编程
使用ActionScript3的绘图命令
AdobeFlashPlayer10(及其后续版本)为ActionScript中的程序化绘图功能提供了一组扩展的显示类支持。
在这些新添图形类的帮助下,您现在有两种途径可以进行图形脚本的编辑:
∙基本的点到点式的命令集,用于绘制围绕图形边沿的线条以及填充图形。
∙一种新的,高级的绘图命令集,允许接受绘图属性的Vector(向量)对象(数组类型)作为参数
如果您感兴趣于使用有限数量的坐标系快速编辑简单图形,请使用flash.display.Graphics类中的基本绘图命令。
如果您计划使用许多坐标点来创建一个较为复杂的图形,或者想要通过编程方式来快速改变图形的点、颜色填充或者笔划的属性,亦或打算将成型的图形及其属性应用到其它图形中,那么请使用更高级的图形数据类和命令。
本文的焦点在于高级绘图API,但我们还是应该先看一个基本绘图API的例子,这对我们理解整个绘图API的发展历程很有帮助。
这篇文章并没有介绍到程序中能应用到的所有ActionScript类。
如果想了解更多信息,请参阅ActionScript3.0Reference中的AdobeFlashPlatform(AdobeFlash开发平台)以及ActionScript3.0Developer'sGuide(ActionScript3.0开发者指南)中的UsingthedrawingAPI(使用绘图API)章节。
基本绘图命令
ActionScript3通过使用Graphics类,为我们提供了绘制直线和曲线功能。
Graphics类*中的基本命令允许您定义线条类型,以及在一系列的点上移动线条,还有为图形填充颜色等。
示例
//定义线条类型
graphics.lineStyle(2,0x000000);
//定义填充色
graphics.beginFill(0x666699)
//设置线条起点
graphics.moveTo(10,10);
//通过一系列坐标点移动线条
graphics.lineTo(10,100);
graphics.lineTo(100,100);
graphics.lineTo(100,10);
//graphics.lineTo(10,10)
结果
注意:
即使脚本将graphics.lineTo(10,10)这条命令注释掉了,但是此图形仍然可以封闭并填充色彩。
Graphics类也包括了一些用于渐变填充、位图填充、线条类型,以及比如圆和椭圆等特殊图形的API。
但是如果您想绘制一个拥有许多坐标点的极其复杂的图形时,该怎么办呢?
或许您需要定义一个笔划或者填充色彩以供您多次应用到同一项目中不同部分的图形中,亦或需要图形能够随着从函数或用户交互输入的数据动态地变化。
您会看到,如果使用一长串的lineTo()命令以及精确的起始结束笔划和填充设置,绘制过程将会变得很难处理。
所以,现在flash.display包中已包含了一些新类,允许您创建绘图数据对象并将其作为参数传递给一些新的Graphics类命令。
高级绘图命令
在基本绘图API中,您设置了线条类型和填充类型,同时开始使用一条条的命令来绘制图形直至最终成型。
在高级绘图API的帮助下,您可以建立用来描绘一个图形的所有数据(坐标、线条属性、填充属性等),然后使用单条绘图命令来处理数据和描绘图形。
这种数据驱动型的绘图API基于以下三个组成块:
∙绘图数据:
像Graphics.lineTo()这样的绘图命令现在在GraphicsPathCommand类中被表示为常量(0~5)。
您可以在一个数组——即被称为向量对象的类型数组——中存储一系列这样的常量。
向量对象允许您将一组单一类型的数据捆绑到一起。
然后,您就可以使用这些向量作为绘图命令的参数来描绘一个图形了。
∙绘图类型数据:
绘图类型数据包括所有用来确定线条(笔划)、填充或轨迹的外形的属性集合,这些属性集合通过使用那些执行flash.display.IGraphicsData界面的类来确定上述的外形。
执行了IGraphicsData界面的类可以创建含有将要用到的笔划、填充或轨迹信息在内的对象。
例如,您可以使用GraphicsGradientFill类*创建一个具有渐变填充属性的对象。
请注意,GraphicsGradientFill类的属性与您在基本绘图API中用作Graphics.beginGradientFill()函数的参数十分相似。
同时也要注意的是,其它执行IGraphicsData的类也相当于基本绘图API中的一些现有函数。
在ActionScript3.0Developer'sGuide中的Usinggraphicsdataclasses中,您可以找到一个关于新数据类和封装的Graphics类方法的完整说明表格。
∙使用绘图数据的新图形类函数:
Graphics类有了新的方法来解释从向量对象和IGraphicsData类型对象中得来的数据,并把这些数据用于图形的描绘。
这些新函数包括Graphics.drawPath(),Graphics.drawGraphicsData()和Graphics.drawTriangles()。
使用绘图数据
此例中,我们将设置一些绘图数据并将其传递到Graphics.drawPath()函数中,以此来介绍如何在新的绘图API中使用绘图数据。
Graphics.drawPath()函数具有三个参数(前两个参数是向量对象):
drawPath(commands:
Vector.,data:
Vector.,winding:
String="evenOdd"):
void
命令向量对象是一系列用于定义每段绘图路径的绘图命令的GraphicsPathCommand*值。
正如我之前所言,GraphicsPathCommand将一组线条绘制命令抽象成为一组常量。
所以Graphics.moveTo()变成了1,Graphics.lineTo()变成了2。
现在您就可以将一系列代表绘图命令的常量填充到一个向量对象中,同时还能使用此向量作为Graphics.drawPath()的参数来描绘一条图形轨迹。
特别地,请看看先前"基本绘图命令"部分中的例子,它有一个moveTo()命令,其后跟随有几个lineTo()命令,这几个命令中的每一个都指向一个坐标系。
每一个命令都被简单抽象成为一个数字,这意味着您现在可以在一个向量对象(例如1,2,2,2)存储一系列命令,而不必一次只能执行一个命令了。
然后您可以将向量对象作为Graphics.drawPath()的命令参数进行传递。
数据向量对象是一系列坐标点,它们对应于命令参数中用于绘制轨迹的一个个绘图命令常量。
每一对参数确定了一个x/y坐标对,所以,两个数值就是一个坐标点,四个数值就是两个坐标点,以此类推。
数据向量对象中每两个条目与命令向量对象中一个条目相匹配,从而生成一条通向某个坐标点的轨迹(或动作)。
winding值决定了是否填充以及如何填充交叉部分的图形。
对于绘制像正方形那样的简单图形,winding就不是那么重要了。
然而当您开始使用交叠线条绘制较为复杂的图形时,winding值决定了是填充整个图形,还是仅填充其中一部分。
如果想了解更多信息,请参阅ActionScript3.0Developer'sGuide中的Definingwindingrules。
还是以跟前面"基本绘图命令"部分中使用Graphics.drawPath()绘图的同一个正方形为例。
(现在,我们继续使用基本API绘制线条和填充类型,这样我们可以重点关注用于绘图命令和坐标的数据的使用)。
此例首先使用Vector.push()函数将一系列绘图命令填入square_commands向量对象。
然后将一系列坐标对填入square_coord向量对象。
最后,Graphics.drawPath()函数使这两组数据匹配并作为参数来描述这个正方形。
示例
//定义线条类型
graphics.lineStyle(2,0x000000);
//定义填充
graphics.beginFill(0x666699);
//设置颜色
//为命令参数建立新的向量对象
varsquare_commands:
Vector.=newVector.();
//使用向量数组push()函数添加moveTo()和lineTo()值。
//一个moveTo命令,后跟三个lineTo命令
square_commands.push(1,2,2,2,2);
//为数据参数建立一个新的向量对象
varsquare_coord:
Vector.=newVector.();
//使用向量数组push()函数添加一组坐标对
square_coord.push(10,10,10,100,100,100,100,10,10,10);
graphics.drawPath(square_commands,square_coord);
对于如同简单正方形这样的图形绘制,新的API似乎并未为我们节省了多少工作。
然而,对于一个较为复杂的图形,你可以发现新的API简化了代码编写:
示例
//定义线条类型。
graphics.lineStyle(2,0x000000);
//定义填充色
graphics.beginFill(0x666699);
//设置颜色
//为数据参数建立新的向量对象
varstar_commands:
Vector.=newVector.();
//使用向量数组push()函数添加moveTo()和lineTo()值
//一个moveTo()命令,后面跟随三个lineTo()命令
star_commands.push(1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2);
//为数据参数建立一个新的向量对象
varstar_coord:
Vector.=newVector.();
//使用向量数组push()函数添加一组坐标对
star_coord.push(0,0,75,50,100,0,125,50,200,0,150,75,200,100,150,125,200,200,125,150,100,200,75,150,0,200,50,125,0,100,50,75,0,0);
graphics.drawPath(star_commands,star_coord);
结果
此星型图案使用了16条lineTo()命令,它们都被抽象成了一行独立的数值,并使用Vector.push()函数添加到了star_commands向量中。
在Graphics.drawPath()加载两个向量对象的同时,您可以改变向量对象的属性值,还可以用新的属性值重新绘图,或者让某个函数将属性值传递到向量对象,然后重新绘图,这样您或者其他用户都可以在程序运行期间随意改变图形。
在下一部分中,我们将介绍一个添加用户交互的例子,但是首先我们也应该了解怎样使用向量对象设置笔划和填充属性。
使用绘图类型数据
在"使用绘图数据"部分,我们为Graphics.drawPath()函数载入了可作为绘图数据的向量对象。
现在,我们将定义一些绘图类型对象用作Graphics.drawGraphicsData()函数的参数。
Graphics.drawGraphicsData()函数在运行新绘图API方面的功能十分强大。
它使用了运行flash.display.IGraphicsData界面的类所创建的对象。
这些类具体如下:
∙GraphicsBitmapFill
∙GraphicsEndFill
∙GraphicsGradientFill
∙GraphicsPath
∙GraphicsShaderFill
∙GraphicsSolidFill
∙GraphicsStroke
∙GraphicsTrianglePath
每一个类都能够创建定义填充类型、笔划或相应轨迹的属性对象。
它们都可以将那些对象作为参数传递到Graphics.drawGraphicsData(),从而按照已定义的属性进行图形描绘。
一旦您定义了绘图对象,就可以将它们重复应用到其他图形中,因此您的绘图属性就可以集中起来,而且可以转移到其他图形。
第一个例子仅在IGraphicsData对象中置入了填充和轨迹数据。
对于绘图数据,该例子使用了如下的类:
∙用于填充属性的GraphicsSolidFill类
∙用于图形轮廓的GraphicsPath类
示例
//创建填充属性
varmyFill:
GraphicsSolidFill=newGraphicsSolidFill();
myFill.color=0x33CCFF;
//创建轨迹属性
varmyPath:
GraphicsPath=newGraphicsPath(newVector.(),newVector.());
myPmands.push(1,2,2,2,2);
myPath.data.push(10,10,10,100,100,100,100,10,10,10);
//置入IGraphicsData向量数组
VectorarrayvarmyDrawing:
Vector.=newVector.();myDrawing.push(myFill,myPath);
//图形描绘
graphics.drawGraphicsData(myDrawing);
结果
现在,让我们使用GraphicsStroke类来定义一个笔划。
请记住,我们需要向IGraphicsData对象添加新的GraphicsStroke对象,以使Graphics.drawGraphicsData()得到笔划属性。
请注意,笔划也需要一个填充值来确定线条类型。
对于绘图数据,该例子使用了以下的类:
∙用于笔划属性的GraphicsStroke类和GraphicsSolidFill类(GraphicsStroke类其实也可以使用GraphicsGradientFill或GraphicsShaderFill类来确定线条外形。
)
∙GraphicsPath类
示例
//创建图形填充属性
varmyFill:
GraphicsSolidFill=newGraphicsSolidFill();
myFill.color=0x33CCFF;
//创建笔划及其填充属性
varmyStroke:
GraphicsStroke=newGraphicsStroke
(2);
myStroke.fill=newGraphicsSolidFill(0x000000);
//创建轨迹属性
varmyPath:
GraphicsPath=newGraphicsPath(newVector.(),newVector.());
myPmands.push(1,2,2,2,2);
myPath.data.push(10,10,10,100,100,100,100,10,10,10);
//置入IGraphicsData向量数组
varmyDrawing:
Vector.=newVector.();
myDrawing.push(myFill,myStroke,myPath);
//图形描绘
graphics.drawGraphicsData(myDrawing);
结果
下面是一个稍复杂一些的使用GraphicsGradientFill类的填充范例。
GraphicsGradientFill类和其属性很大程度上反映了Graphics.beginGradientFill()函数的参数。
实际上,许多图形数据类和其属性都在图形类函数中有对等的结构内容。
此例子也使用了flash.geom.Matrix.createGradientBox()函数用于对GraphicsGradientFill.matrix属性的设置。
示例
//创建填充属性
varmyFill:
GraphicsGradientFill=newGraphicsGradientFill();
myFill.colors=[0xEEFFEE,0x0000FF];
myFill.matrix=newMatrix();
myFill.matrix.createGradientBox(100,100,0);
/创建笔划属性
varmyStroke:
GraphicsStroke=newGraphicsStroke
(2);
myStroke.fill=newGraphicsSolidFill(0x000000);
//创建轨迹属性
varmyPath:
GraphicsPath=newGraphicsPath(newVector.(),newVector.());
myPmands.push(1,2,2,2,2);
myPath.data.push(10,10,10,100,100,100,100,10,10,10);
//置入IGraphicsData向量数组
varmyDrawing:
Vector.=newVector.();
myDrawing.push(myFill,myStroke,myPath);
//图形描绘
graphics.drawGraphicsData(myDrawing);
结果
重用绘图数据以及添加用户交互
到目前为止,我们已经完成了以下工作:
∙建立图形数据对象来定义笔划、填充和轨迹属性。
∙创建向量对象作为参数,传递到绘图命令
∙使用Graphics.drawPath()和Graphics.drawGraphicsData()函数绘制图形。
我们来将图形数据对象与一个比正方形稍复杂一些的图形联系起来,同时在运行时创建一个函数来改变图形。
示例
//创建一个帮助控制的显示对象
//显示列表中的图形
varmySprite:
Sprite=newSprite();
mySprite.x=10;
mySprite.y=10;
addChild(mySprite);
//创建绘图数据
//渐变填充对象
varmyFill:
GraphicsGradientFill=newGraphicsGradientFill();
myFill.colors=[0xEEFFEE,0x0000FF];
myFill.matrix=newMatrix();
myFill.matrix.createGradientBox(300,300,0);
//轨迹对象
varmyPath:
GraphicsPath=newGraphicsPath(newVector.(),newVector.());
myPmands.push(1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2);
myPath.data.push(0,0,75,50,100,0,125,50,200,0,150,75,200,100,150,125,200,200,125,150,100,200,75,150,0,200,50,125,0,100,50,75,0,0);
//组合对象从而完成绘制
varmyDrawing:
Vector.=newVector.();
myDrawing.push(myFill,myPath);
//图形描绘
mySprite.graphics.drawGraphicsData(myDrawing);
结果
现在让我们来添加一些用户交互。
在下面的例子中,随着用户在图形上拖动鼠标,星形图的底角点也会跟随光标移动。
星形图会时而叠起时而展开。
为了顺利完成这个例子,我们在平台上添加了一个鼠标事件检测器。
在鼠标事件控制器(即redraw()函数)上,清除掉旧的角坐标点,再用Vector.splice()函数添加由鼠标位置确定的数值。
同时也加入了if语句,使得图形能够在用户拖动边角一定距离后迅速跳回到它原来的位置。
注意:
redraw()事件操作函数在改变图形坐标和描绘新图形之前会使用Graphics.clear()函数删除当前的图形。
否则,您的新图形就会覆盖在其它图形之上。
//创建绘图数据
//渐变的填充对象
varmyFill:
GraphicsGradientFill=newGraphicsGradientFill();
myFill.colors=[0xEEFFEE,0x0000FF];
myFill.matrix=newMatrix();
myFill.matrix.createGradientBox(300,300,0);
//轨迹对象
varmyPath:
GraphicsPath=newGraphicsPath(newVector.(),newVector.());
myPmands.push(1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2);
myPath.data.push(0,0,75,50,100,0,125,50,200,0,150,75,200,100,150,125,200,200,125,150,100,200,75,150,0,200,50,125,0,100,50,75,0,0);
//组合对象从而完成绘制
varmyDrawing:
Vector.=newVector.();
myDrawing.push(myFill,myPath);
//图形描绘
graphics.drawGraphicsData(myDrawing);
stage.addEventListener(MouseEvent.MOUSE_MOVE,redraw);
functionredraw(event:
MouseEvent):
void{
//使用clear()命令删除旧坐标的图形
graphics.clear();
varx:
Number=event.stageX;
vary:
Number=event.stageY;
myPath.data.splice(16,2,x,y);
graphics.dr