转 第四章 渲染技术(2)(as3.0)

使用 beingGradientFill 创建渐变填充
    下面开始学习绘图 API 的强大函数:beginGradientFill(fillType, colors, alpha,
ratios, matrix)。与线条样式相同,这个方法也有很多额外的可选参数——扩散方法
(spreadMethod),插补方法(interpolationMethod)及焦点位置比例(focalPointRatio)。这
些参数可用来调整渐变的属性,但是在大多数简单的应用中这些参数不是必需的,而这个方
法与 beginFill 有很多相似之处,同样也使用 endFill 作为结束。两者最大的不同是填充
的颜色,我虽不想说 beginGradientFill 是用来创建渐变填充的,但是,如果不这么说,
又感觉少了点什么。渐变填充至少要有两种颜色,图形的第一部分从第一种颜色开始,然后
逐渐混合成为另一种颜色,或者混合成一个或多个已定义的颜色。
指定填充类型
我们可以建立两种类型的渐变填充:线性(linear)和放射(radial)状。在线性填充时,渐变
的颜色沿着直线从一点到另一点。默认的情况,是从左向右的一条直线,也可以是从上到下
或其它角度的直线。

    为了能够看到线性渐变,需要至少两种不同的颜色。如果指定了两种颜色,那么填充将
会从第一种颜色向第二种颜色渐变。如果指定了更多的颜色,  填充色将会从第一种颜色渐变
为第二种,然后再渐变到第三种……直到最后一种。
    放射状填充与线性填充使用的参数大致相同,  只是在解释上有所不同。从指定的中心位
置开始创建渐变,以这点为基础向外进行放射,形成一个圆或椭圆。我们指定的第一种颜色
用做内圆,最后一种颜色作为外圆,唯一不需要的就是角度。图 4-6 是一个放射状填充。
对于 beginGradientFill(fillType, colors, alphas, ratios, matrix) 方法,第一个参
数为填充类型,非常简单,用一个字符串表示,这两个值中的一个: linear”
                                                            ”        或”radial”。
与第三章讲的事件类型很像,目前事件类型也被设置为 flash.display.GradientType 类的
静态属性,为的是避免错误输入。我们可以导入 GradientType 类然后输入
GradientType.LINEAR 或 GradientType.RADIAL。

设置 colors , alphas 及 ratios
    使用 colors 参数设置颜色,当然也必需设置每一个颜色所要填充的位置,使用 0 到
255 中的一个数进行指定,0 表示填充的开始位置,255 表示填充结束位置。在这些数值中,
每一个数代表一个颜色的位置,这就是填充的比例。因此,如果有要填充两种颜色,那么应
该指定 0 和 255 作为 ratios,如果有三个颜色值,那么应该写成 0,128,255。这样就将第
二个颜色放到了另外两个颜色的中间。如果比例值为 0,20,255,那么第一种颜色会很快渐
变为第二种颜色,然后非常缓慢地渐变为第三种颜色。请记住这些数值不是像素值,而是指
在 255 中的某一个部分。
    我们同样必须指定渐变色的透明度,这就是 alpha 值,从 0.0 到 1.0,而在 AS 2 中
表示为 0 到 100。如果不需要透明度,那么就设置为 1.0。如果设置的透明度是从 1.0 到 0.0,
那么渐变的过程不仅是改变颜色,而且还有平滑淡出的效果。可以用做创建柔和的阴影(也
许比使用投影滤镜(drop shadow filter)还要好些)。
这里每一个参数都是一个数组,   因为需要传入至少两个以上的 colors, alphas 及 ratios。
我们可以先创建一个数组,然后写入每一个参数的值,如下:
var colors:Array = new Array();
colors[0] = 0xffffff;
colors[1] = 0x000000;
    下面是一个更简单作法,我们可以在创建数组的同时,为数组的每个元素赋值,直接写
在方括号中,以逗号作为分隔:
var colors:Array = [0xffffff, 0x000000];
事实上,我们甚至可以不去使用 colors 变量。直接把右边的数组写入 beginGradientFill
表达式中作为参数。因此,可以写成这样:
graphics.beginGradientFill(GradientType.LINEAR,
[0xffffff, 0x000000],
[1, 1],
[0, 255],
matrix);
    这里定义了两个颜色值,两个 alpha 值(均为 100%)和比例值的开始位置与结束位置,
所以渐变将以白色为开始最后逐渐变化为黑色。 当然,也可以为每个参数设置一个对应的变
量,如果定义了很多个颜色值的话,这样写会更清楚些。如果定义了三个颜色值,就必需有
三个 alpha 值和三个比例值与之对应。如果有某些值多了或少了,那么就会引起会静默失
败——没有渐变,没有填充,没有错误信息。
下面只需要设置一下填充的起点、终点或角度了。也许大家已经猜到了,这就是神秘的
matrix(矩阵) 参数。

创建矩阵
      矩阵(Matrix)就是一个二维表格,每行每列中包括不同的数,可以出计算不同的值。矩
阵此外还用于绘图(graphics)中,  用作旋转,缩放和移动物体。在这里,用于对渐变的控制,
我们需要为填充进行定位,设置它的大小,或是进行旋转。使用 matrix 时,需要创建一个
matix 对象,这是一个 flash.geom.Matrix 类的对象。(实际上, Matrix 类不仅用于操
作渐变填充,但这里我们只介绍它在渐变中的应用。第 18 章中介绍了更多的矩阵使用)。
      在使用 Matrix 类时有一点复杂,这里有一个特殊的方法用于创建渐变填充的矩阵类
型,这个方法名为 createGradientBox,必要参数为 width 和 height,可选参数为
rotation 及渐变的起点的 x,y 位置。首先创建一个 Matrix 类的实例,然后调用它的
createGradientBox 方法自动设置内部参数值。形式如下:
var matrix:Matrix = new Matrix();
matrix.createGradientBox(width, height, rotation, x, y);
不要忘记在类的开始处导入 flash.geom.Matrix 类。如果仅指定 width 和 height,最后
三个值默认为 0。来看一下代码,这里是文档类 GradientFill.as:
package {
  import flash.display.GradientType;
  import flash.display.Sprite;
  import flash.events.MouseEvent;
  import flash.geom.Matrix;
  public class GradientFill extends Sprite {
   public function GradientFill() {
     init();
   }
   private function init():void {
     graphics.lineStyle(1);
     var colors:Array = [0xffffff, 0xff0000];
     var alphas:Array = [1, 1];
     var ratios:Array = [0, 255];
     var matrix:Matrix = new Matrix();
     matrix.createGradientBox(100, 100, 0, 0, 0);
     graphics.beginGradientFill(GradientType.LINEAR, colors,
     alphas, ratios, matrix);
     graphics.drawRect(0, 0, 100, 100);
     graphics.endFill();
   }
  }
}
     测试影片后,会看到一个从白色到红色渐变的正方形。现在,我们改变一下绘图代码,
在不同的地方绘制这个正方形(见 GradientFill2.as):
graphics.drawRect(100, 100, 100, 100);
     现在这个正方形为全红色,为什么会这样?渐变在 x 为 0 处开始,但它只有 100 像素
宽,而正方形是从 100 像素开始的,渐变色已经到达了全红色,红色从这里开始已经出界了。
因此,如果想让矩阵的 x,y 在正方形的左上角开始,应该这样写:
matrix.createGradientBox(100, 100, 0, 100, 100);
     这样, x,y 坐标就与正方形的起点相同。请使用同样的正方形,通过改变矩阵和渐变
填充观察创建的填充是什么效果。首先,试一下三种颜色:
var colors:Array = [0xffffff, 0x0000ff, 0xff0000];
var alphas:Array = [1, 1, 1];
var ratios:Array = [0, 128, 255];
     不要忘记改变 alphas 和 ratios ,将中间的比例移动一下看看对渐变色的影响。 试用
64 或 220 代替 120。
下面是一个直接 alpha 变化的例子,使用相同的颜色,只改变 alpha 的值:
var colors:Array = [0x000000, 0x000000];
var alphas:Array = [1, 0];
var ratios:Array = [0, 255];
试着改变一下角度,下面是 45 度角:
matrix.createGradientBox(100, 100, Math.PI / 4, 100, 100);
使用 Math.PI/2 旋转 90 度形成一个垂直填充。- Math.PI/2 形成向上填充, Math.PI 左
                                                                    
是从右向左填充,默认为从左向右填充。
beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix);
现在,将这些应用在线性填充(linear)的技巧改为放射状填充(radial)的版本。

颜色转换
    下面一个渲染工厂是 flash.geom.ColorTransform 类及其方法。与绘图 API 不同,该
类不允许创建图形,仅仅用于改变已存在于影片或显示对象实例中图形的颜色。让我们去看
看它是怎样工作的。

 

使用 ColorTransform 类改变颜色
    在 ActionScript 2 中,操作影片剪辑颜色最常用的方法是 Color 类,拥有像 setRGB
和 setTransform 这样的方法。Flash 8 中就引用了 ColorTransform 类,同时 Color 类
就不再被推荐使用,但是想大多数人仍然继续使用 Color 类,因为这已经成为习惯了。Color
类已经不是 AS 3 的一部分了,现在是学习新方法的最佳时机。ColorTransform 的方法与
Color 类的方法本质上是非常像,两者差不太多,只是语法上略有不同。
     首先,要知道 Sprite 影片,影片剪辑,或其它任何显示对象都有一个属性叫作
transform。这是 flash.geom.Transform 类的一个实例,其中包括一些不同的属性用于缩
放,旋转,定位和改变影片颜色,影响颜色属性的就是 colorTransform。要知道这是一个
显示对象属性的属性,访问方法如下;
mySprite.transform.colorTransform
或使用一个继承自 Sprite 的类,可以直接获得类自身的 transform 属性:
transform.colorTransform
     通过为一个 ColorTransform 对象的颜色属性赋值可以改变一个对象的色彩。 你也许会
问,什么是 ColorTransform 对象?如果大家使用过 AS 2 的 Color 方法:setTransform,
就知道我们需要传入一个 object(对象) ,  在这个 object 中有各种属性,需要告诉它如何
变换颜色。 ColorTransform 与这个方法非常相似,但不是使用一个普通的对象(object),
而现在这个方法已经拥有了官方的类。在 AS 2 中,是这样做的:
myTransform = new Object();
myTransform.ra = 50;
myTransform.ga = 40;
myTransform.ba = 12;
myTransform.aa = 40;
myTransform.rb = 244;
myTransform.gb = 112;
myTransform.bb = 90;
myTransform.ab = 70;
在 AS 3 中,应该创建一个同样的 ColorTransform 对象,像这样:
myTransform = new ColorTransform(0.5, 0.4, 0.12, 0.4, 244, 112, 90, 70);
     前四个值为乘数,后四个值为偏移量,马上会介绍这个公式,然后就会知道为什么它们
这样命名了。大家也许注意到了乘数的比例值为十进制范围 -1.0 到 1.0,而不是 -100 到
100。事实上,帮助文档说是从 0.0 到 1.0,但还可以使用负数做为乘数实现一些有趣的效
果(稍后会看到),偏移量依然是从-255 到 255。ColorTransform 对象的构造函数如下:
ColorTransform(redMultiplier,
greenMultiplier,
blueMultiplier,
alphaMultiplier,
redOffset,
greenOffset,
blueOffset,
alphaOffset)
转换一个特殊颜色通道的公式如下,以红色通道为例:
newRed = oldRed * redMultiplier + redOffset;
在使用 ColorTransform 时,记得它是 flash.geom 包中的一部分,所以需要导入类。
     给大家一个例子,下一个文档类:TransformColor.as,在 SWF 中嵌入一张图片作为位
图(位图类的实例)。因为位图类是一个显示对象,拥有 transform 属性,代码设置了位图
的 transform 的 colorTransform 属性,使用构思好的设置来制作一张底片效果的图像:
package {
  import flash.display.Bitmap;
  import flash.display.Sprite;
  import flash.geom.ColorTransform;
  public class TransformColor extends Sprite {
   [Embed(source="picture.jpg")];
   public var Picture:Class;
   public function TransformColor() {
     init();
   }
   private function init():void {
     var pic:Bitmap=new Picture    ;
     addChild(pic);
     pic.transform.colorTransform=new ColorTransform(-1,-1,1,1,
     255,255,255,0);
   }
  }
}
测试这个影片时,请改变这行代码
[Embed(source="picture.jpg")]
      请匹配这个路径为所使用图片的路径,如果在 Flash IDE 中编辑,只需要在库中导入
这张图片,为ActionScript 导出,并输入类名为 Picture。重要的一句是 ColorTransform
的设置。
滤镜(Filter)
    滤镜是一些位图的效果,可以应用于任何显示对象。在 Flash IDE 中可以通过滤镜面
板或使用时间轴的 ActionScript 来使用滤镜,由于这本书是关于 ActionScript 的,所以
只能简单地讨论一下应用滤镜的方法。在 AS 3 中包括以下几种滤镜:
■ Drop shadow(投影滤镜)
■ Blur(模糊滤镜)
■ Glow(发光滤镜)
■ Bevel(斜角滤镜)
■ Gradient bevel(渐变斜角滤镜)
■ Gradient glow(渐变发光滤镜)
■ Color matrix(颜色矩阵滤镜)
■ Convolution(卷积滤镜)
Displacement map(置换图滤镜)
    虽然不能一一介绍每种滤镜的使用细节,但大家可以通过帮助文档来学习。在书中还会
有很多滤镜使用的例子,所以在这里只介绍一下滤镜使用的总体方法和两个具体实例。

 

创建滤镜
    通过使用 new 关键字及滤镜名来创建滤镜,并给出所需的参数。例如,创建一个 blur
filter(模糊滤镜),最简单的一种滤镜,写法入下:
var blur:BlurFilter = new BlurFilter(5, 5, 3);
参数分别为 blurX,blurY,quality。这个例子会将对象在 x 和 y 轴上模糊 5 个像素,模糊
的品质为中等。
另一点需要知道的是滤镜在其名为 flash.filters 的包中。所以要在文件的开始处将它们
导入进来:
    import flash.filters.BlurFilter;
如果希望导入包中所有的滤镜,可以使用简写:
import flash.filters.*;
      现在,我们可以直接创建任何类型的滤镜了,但是一般来说,除非要使用这个包中的大
部分滤镜,否则最好避免使用通配符(*),而是明确地导入所需要的类。这样做只是为了能
够清楚,哪些是真正想要导入的而哪些不是。好了,现在已经创建了一个模糊滤镜,但怎么
才能使它去模糊一个对象呢?
      任何一个显示对象都有一个名为 filters 的属性,这是一个包括了所有滤镜的数组,
因为如果一个对象要应用多个滤镜,那么只需要再将模糊滤镜放到数组中即可。乐观地看,
应用滤镜应该可以像使用基本数组操作那样简单,push,就像这样
mySprite.filters.push(blur);,但是很遗憾,没有这么简单。在整个数组赋值为 filters
之前,Flash 不关心 filters 数组的变化。
      如果已知对象没有应用任何的滤镜,或想要重写它们,只需要新建一个数组,将我们的
滤镜粘在上面,再将这个新数组赋给 filters 属性就可以了。先来试一下,下面一个文档
类 Filters.as,创建了一个 sprite 影片并且在里面绘制了一个黄色的正方形,然后,创
建一个滤镜,加入数组中,最后将数组赋给 sprite 的 filters 属性:
package {
  import flash.display.Sprite;
  import flash.filters.BlurFilter;
  public class Filters extends Sprite {
   public function Filters() {
     init();
   }
   private function init():void {
     var sprite:Sprite = new Sprite();
     sprite.graphics.lineStyle(2);
     sprite.graphics.beginFill(0xffff00);
     sprite.graphics.drawRect(100, 100, 100, 100);
     sprite.graphics.endFill();
     addChild(sprite);
     var blur:BlurFilter = new BlurFilter(5, 5, 3);
     var filters:Array = new Array();
     filters.push(blur);
     sprite.filters = filters;
   }
  }
}
瞧!出现了一个模糊的黄色方块儿。重要的部分用黑体着重,我们可以简写一点:
var blur:BlurFilter = new BlurFilter(5, 5, 3);
var filters:Array = [blur];
sprite.filters = filters;
或再短一点:
sprite.filters = [new BlurFilter(5, 5, 3)];
      在创建数组的同时,将滤镜放进去,并应用 filters 属性,这样一来,Flash 会很高
兴。
      但是如果已经有了滤镜并希望继续使用,这时,但又不确定是否有滤镜存在,那该怎么
办呢?在 Flash 8 中,这是件很麻烦的事,因为一个显示对象的 filters 属性如果没有应
用滤镜,那么它将是未定义(undefined)的。但在 AS 3 中, filters 数组总是保持为一个
空数组,只需要给数组赋值,将滤镜 push 进去,并将其赋给对象的 filters 属性即可,
方法如下:
var filters:Array = sprite.filters;
filters.push(new BlurFilter(5, 5, 3));
sprite.filters = filters;
    如果使用这种方法,那么无论是否有滤镜存在都没有问题,滤镜只是被加入到数组列表
中而已。因为 filters 属性是一套成熟的数组,所以可以使用不同的数组操作方法。比如,
使用 concat 方法:
sprite.filters = sprite.filters.concat(new BlurFilter(5, 5, 3));
    我不认为这是个“正确”的做法,大家只要知道将一个包涵有滤镜的数组赋给 filters
属性就足够了。

 

动态滤镜
现在我们已经基本上知道了如何在 ActionScript 中使用滤镜了。  接下来,用已经学过的知
识,制作一个动态滤镜。这个效果,使用文档类 AnimatedFilters.as:
package {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.filters.DropShadowFilter;
  public class AnimatedFilters extends Sprite {
   private var filter:DropShadowFilter;
   private var sprite:Sprite;
   public function AnimatedFilters() {
     init();
   }
   private function init():void {
     sprite = new Sprite();
     sprite.graphics.lineStyle(2);
     sprite.graphics.beginFill(0xffff00);
     sprite.graphics.drawRect(-50, -50, 100, 100);
     sprite.graphics.endFill();
     sprite.x = 200;
     sprite.y = 200;
     addChild(sprite);
     filter = new DropShadowFilter(0, 0, 0, 1, 20, 20, .3);
     addEventListener(Event.ENTER_FRAME, onEnterFrame);
   }
   private function onEnterFrame(event:Event):void {
     var dx:Number = mouseX - sprite.x;
     var dy:Number = mouseY - sprite.y;
     filter.distance = -Math.sqrt(dx * dx + dy * dy) / 10;
     filter.angle = Math.atan2(dy, dx) * 180 / Math.PI;
     sprite.filters = [filter];
   }
  }
}
    首先在 sprite 中画一个正方形, 正方形在 sprite 的居中位置, 然后将 sprite 移动
      到舞台中间,用一些默认属性创建投影滤镜(DropShadowFilter)。
添加一个 enterFrame 事件的侦听器及处理函数:  onEnterFrame 方法,用于计算角度(angle)
及使用三角函数计算 sprite 影片与鼠标的距离(distance)。使用 angle 和 distance 设
置投影滤镜的 angle 和 distance 属性,最后将这个滤镜再应用到 sprite 上。请注意,
我们不需要每次都创建一个新的滤镜,可以继续使用同一个滤镜,只需要改变它的属性即可。
然而,只是改变这些属性也不能更新 sprite 影片的显示。因此,还需要再将变化过的滤镜
效果赋值给 filters 属性。

 

位图(Bitmaps)
与滤镜相同,可以用整本书来介绍 Bitmap 和 BitmapData 类,看起来也不错,但是这并不
是本书的目的。我们将通过一些简单的例子,用来指出 AS 2 与 AS 3 中位图处理的变化。
    在 AS 2 中,通过调用 BitmapData()函数,新建一个 BitmapData 对象使用如下参数:
new BitmapData (width:Number,
height:Number,
transparent:Boolean,
fillColor:Number)
    你也许猜到了, BitmapData 类同样也是嵌入在一个包中,完整的使用名称如下
flash.display.BitmapData。所以需要导入包,对于 width 和 height 参数则非常显而易
见, transparent 参数表示创建的图像是否包涵一个 alpha 通道, 选择 true 或 false ,
fillColor 是创建图像的初始颜色,如果 transparent 为 true 的话,那么位图就用 32 位
色表示,0xAARRGGBB,如果为 false 的话,就可以使用 24 位安全色表示。
    在创建 BitmapData 对象时,也许很想能看到它的样子。在 AS 2 中,使用
attachBitmap 命令在影片剪辑中添加一个位图。大家也许会想,现在是否可以使用
addChild 在显示对象中添加一个位图,但事实上并没有这么简单。问题在于 addChild 只
对继承自 DisplayObject 类的对象起作用,如 Sprite 影片,影片剪辑和文本框。然而,
如果我们研究一下类的结构,就会发现 BitmapData ,没有继承自 DisplayObject,所有不
能直接添加对象。这就是为什么要有 Bitmap 类的原因, Bitmap 类几乎始终都有一个函数
作为 BitmapData 实例的容器,可以这样创建:
var myBitmapData:BitmapData = new BitmapData(100, 100, false, 0xff0000);
var myBitmap:Bitmap = new Bitmap(myBitmapData);
现在就可以将对象加入到显示列表了:
addChild(myBitmap);
     使其可见后,Bitmap 实例也可以改变位置,进行缩放,增加滤镜等等。
     测试这个例子,只需要在第二章给出的类框架的 init 方法加入这三行就可以了,不要
忘记导入 flash.display.Bitmap 和 flash.display.BitmapData,运行后就会看到一个红
色的正方形。乍看上去,与使用绘图 API 所画的图形没什么不同,但是要知道这并不是矢
量图绘制法:填充一个红色的正方形。这是张位图图像,在位图中每一个像素都要分别指定
而且是可变的。事实上,每一个像素值都可以使用 getPixel,getPixel32 和
setPixel,setPixel32 进行读取和设置。两个版本的不同之处在于 getPixel 和 setPixel
使用 24 位色彩值忽略了 alpha 通道,而 “32”版的则使用 32 位色彩值其中包括了透明
度信息。让我们来做个例子,制作一个简单的喷漆工具,就像所有位图喷漆程序一样。
这里是文档类,SprayPaint.as:
package {
  import flash.display.Sprite;
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.events.MouseEvent;
  import flash.events.Event;
  import flash.filters.BlurFilter;
  public class SprayPaint extends Sprite {
   private var canvas:BitmapData;
   private var color:uint;
   private var size:Number = 50;
   private var density:Number = 50;
   public function SprayPaint() {
     init();
   }
   private function init():void {
     canvas = new BitmapData(stage.stageWidth,
     stage.stageHeight,
     true, 0x00000000);
     var bmp:Bitmap = new Bitmap(canvas);
     addChild(bmp);
     stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
     stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
   }
   private function onMouseDown(event:MouseEvent):void {
     color = Math.random() * 0xffffff + 0xff000000;
     addEventListener(Event.ENTER_FRAME, onEnterFrame);
   }
   private function onMouseUp(event:MouseEvent):void {
     removeEventListener(Event.ENTER_FRAME, onEnterFrame);
   }
   private function onEnterFrame(event:Event):void {
     for (var i:int = 0; i < density; i++) {
      var angle:Number = Math.random() * Math.PI * 2;
      var radius:Number = Math.random() * size;
      var xpos:Number = mouseX + Math.cos(angle) * radius;
      var ypos:Number = mouseY + Math.sin(angle) * radius;
      canvas.setPixel32(xpos, ypos, color);
     }
   }
  }
}
     这也许是目前为止最复杂的代码,但除了 BitmapData 的内容外,其它的知识前面都讲
过,只不过又使用了一遍而已。一步步来看,首先,创建了一些类变量,包括 canvas 变量,
用于存放 BitmapData 的实例。创建的实例尺寸等于舞台的尺寸,并使用透明的背景色。然
后使用 canvas 创建一个位图,并加入到显示列表。
鼠标事件处理函数中选择了一个随机的颜色, 并且带有添加和删除 enterFrame 事件处理函
数的功能。我们来回忆一下三角学,首先,从 0 到 Math.PI * 2 中计算出一个随机的角度,
不要忘记使用弧度制表示,相当于随机的 360 度。然后,计算出一个随机的半径后,再使用
三角函数将半径和角度转换为 x,y 值。最后使用 setPixel32 以鼠标位置加上随机的 x,y
值的像素点设置为喷漆色,每一次开始喷漆时随机决定颜色。在这个例子中有一个 for 循
环,每一帧都会进行循环,每次循环多少次由 density 的值决定。 color 的值为 24 位的
色彩值,然后加上 0xFF000000,为的是设置 alpha 通道为完全不透明,如果没有加上这个
值,那么所有的颜色就都为透明的。如果用 0xFFFFFFFF 乘以 Math.random(),那么颜色的
透明度是随机的,也许是你想要的,但不是我想要的。通过改变 density 和 size 的值再
测试一下, 看看会有些什么不同的效果。大家也许已经想到如何让用户来控制改变这些参数
了。
     刚刚看到这个程序时,你也许会想,“真是小题大作,完全可以用绘图 API 或通过加
载小影片剪辑并改变颜色来实现”。是的,完成可以这么做,但是如果使用绘图 API 绘出
成千上万的独立图像后,会发习画得越多,速度越慢。画过几百个图形后,慢下来的速度会
变得非常明显,这个程序也就费掉了,使用加载影片剪辑的方式也是如此。但是,使用位图
就完全不同了,我们可以使用这个程序喷上一天,都不影响程序的速度或效率。
如果想看到更酷的效果,就把下面一行代码加在位图对象 bmp 的后面:
bmp.filters = [new BlurFilter(2, 2, 3)];
    在位图中使用模糊滤镜比在矢量图中使用效果更加明显。当然,设置像素是 BitmapData
对象能做的最简单的操作之一。除了获取和设置像素,BitmapData 对象还有其它二十多种
方法,这些方法可用来复制像素,设置阈值,分解,合并,滚动,等等。我个人最喜欢的一
个是 perlinenoise 方法,该函数允许我们创建一个随机的有组织的图案。对于制造烟,云
和水波纹效果都非常有用。有兴趣的话大家可以试验一下。

 


读取和嵌入资源
      最后一个重点话题是获取外部资源的概念,如在影片中加载位图或外部 SWF 文件。有
两种方法,一种是在动画播放时将资源读入,这就是我们所熟知的读取(loading)。另一种
方法是在 SWF 编译时嵌入(embed)资源。

 


读取资源
      创建一个 Loader 对象来读取一个资源,这是 flash.display.Loader 类的一个实例。
loader 是个显示对象,意味着可以使用 addChild() 方法将它加入到显示列表中,就像
sprite 和 bitmap 一样。然后告诉这个 loader 去读取一个外部 SWF 或外部位图,如
JPEG,PNG,等等。
      在 AS 2 中,当处理外部文件路径或 URL 时,只需要使用一个简单的字符串表示路径。
在 AS 3 中,则需要创建一个 flash.net.URLLoader 实例,传入表示路径的字符串,并且
还需要一个额外的步骤,虽然有些烦人,但是我们还是要习惯这种用法。
这里是一个在运行时读取外部资源的例子(文档类 LoadAsset.as):
package {
  import flash.display.Sprite;
  import flash.display.Loader;
  import flash.net.URLRequest;
  public class LoadAsset extends Sprite {
   public function LoadAsset() {
     init();
   }
   private function init():void {
     var loader:Loader = new Loader();
     addChild(loader);
     loader.load(new URLRequest("picture.jpg"));
   }
  }
}

嵌入资源

     虽然在有些情况下,在运行时读取资源很合适,但是在有些情况下有一些外部图形只想
加载到 SWF 自里面。这时,如果使用 Flash IDE,可以简单地导入这个对象到库中并设置
为“为 ActionScript 导出”。但在使用 Flex Builder 2 或 Flex 2 SDK 命令编译器时,
没有库,那么如何在 SWF 中加载外部资源呢?
     答案是使用[Embed]元数据(metadata)标签嵌入资源,元数据标签是指加到
ActionScript 文件中的非正式 ActionScript 语句。另外,它们指示编译器在编译过程中
去做某种事情, [Embed]标签告诉编译器在最终的 SWF 文件中加载一个特殊的外部资源,资
源可以是位图或外部 SWF 文件。告诉编译器要嵌入的资源所在的 source 路径的属性,如
下:
[Embed(source="picture.jpg")]
在元数据语句的后面,直接声明一个 Class 类型的变量,如下:
[Embed(source="picture.jpg")]
private var Image:Class;
现在可以使用这个变量创建一个新的资源实例,如下:
var img:Bitmap = new Image();
     注意创建的这个对象是 Bitmap 类型的。如果嵌入一个外部 SWF 文件,创建的这个对
象应该是 Sprite 类型的,如下:
[Embed(source="animation.swf")]
private var Anim:Class;
var anim:Sprite = new Anim();
这里是一个在 SWF 中嵌入外部 JPEG 的例子:
package {
  import flash.display.Sprite;
  import flash.display.Bitmap;
  public class EmbedAsset extends Sprite {
   [Embed(source="picture.jpg")];
   private var Image:Class;
   public function EmbedAsset() {
     init();
   }
   private function init():void {
     var img:Bitmap = new Image();
     addChild(img);
   }
  }
}
      如果我们使用 Flash IDE ,只要将对象导入到库中并“为 ActionScript 导出”给出
一个类名就可以了。不需要使用 [Embed] 元数据标签及类变量,事实上,Flash IDE 编译
器甚至不支持 [Embed] 元数据标签。这里只作一个简单的介绍,因为在本书后面的内容中
不会用到这个技术,但是很显然这是个非常有用的方法。

 

本章重要公式
在本章中我们又收集了很多有价值的工具,大多都与颜色有关。

转换为十进制:
trace(hexValue);
十进制转换为十六进制:
trace(decimalValue.toString(16));
颜色合成:
color24 = red << 16 | green << 8 | blue;
color32 = alpha << 24 | red << 16 | green << 8 | blue;
颜色提取:
red = color24 >> 16;
green = color24 >> 8 & 0xFF;
blue = color24 & 0xFF;
alpha = color32 >> 24;
red = color32 >> 16 & 0xFF;
green = color32 >> 8 & 0xFF;
blue = color232 & 0xFF;
过控制点的曲线:
// xt, yt is the point you want to draw through
// x0, y0 and x2, y2 are the end points of the curve
x1 = xt * 2 – (x0 + x2) / 2;
y1 = yt * 2 – (y0 + y2) / 2;
moveTo(x0, y0);
curveTo(x1, y1, x2, y2);

 

 

这章基本把flash里面涉及到颜色的要素都将明白了 哈哈 灵活运用会有很多意想不到的功能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值