使用 beingGradientFill 创建渐变填充
ratios, matrix)。与线条样式相同,这个方法也有很多额外的可选参数——扩散方法
(spreadMethod),插补方法(interpolationMethod)及焦点位置比例(focalPointRatio)。这
些参数可用来调整渐变的属性,但是在大多数简单的应用中这些参数不是必需的,而这个方
法与 beginFill 有很多相似之处,同样也使用 endFill 作为结束。两者最大的不同是填充
的颜色,我虽不想说 beginGradientFill 是用来创建渐变填充的,但是,如果不这么说,
又感觉少了点什么。渐变填充至少要有两种颜色,图形的第一部分从第一种颜色开始,然后
逐渐混合成为另一种颜色,或者混合成一个或多个已定义的颜色。
指定填充类型
我们可以建立两种类型的渐变填充:线性(linear)和放射(radial)状。在线性填充时,渐变
的颜色沿着直线从一点到另一点。默认的情况,是从左向右的一条直线,也可以是从上到下
或其它角度的直线。
会从第一种颜色向第二种颜色渐变。如果指定了更多的颜色,
为第二种,然后再渐变到第三种……直到最后一种。
置开始创建渐变,以这点为基础向外进行放射,形成一个圆或椭圆。我们指定的第一种颜色
用做内圆,最后一种颜色作为外圆,唯一不需要的就是角度。图 4-6 是一个放射状填充。
对于 beginGradientFill(fillType, colors, alphas, ratios, matrix) 方法,第一个参
数为填充类型,非常简单,用一个字符串表示,这两个值中的一个: linear”
与第三章讲的事件类型很像,目前事件类型也被设置为 flash.display.GradientType 类的
静态属性,为的是避免错误输入。我们可以导入 GradientType 类然后输入
GradientType.LINEAR 或 GradientType.RADIAL。
设置 colors , alphas 及 ratios
255 中的一个数进行指定,0 表示填充的开始位置,255 表示填充结束位置。在这些数值中,
每一个数代表一个颜色的位置,这就是填充的比例。因此,如果有要填充两种颜色,那么应
该指定 0 和 255 作为 ratios,如果有三个颜色值,那么应该写成 0,128,255。这样就将第
二个颜色放到了另外两个颜色的中间。如果比例值为 0,20,255,那么第一种颜色会很快渐
变为第二种颜色,然后非常缓慢地渐变为第三种颜色。请记住这些数值不是像素值,而是指
在 255 中的某一个部分。
表示为 0 到 100。如果不需要透明度,那么就设置为 1.0。如果设置的透明度是从 1.0 到 0.0,
那么渐变的过程不仅是改变颜色,而且还有平滑淡出的效果。可以用做创建柔和的阴影(也
许比使用投影滤镜(drop shadow filter)还要好些)。
这里每一个参数都是一个数组,
我们可以先创建一个数组,然后写入每一个参数的值,如下:
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 值和三个比例值与之对应。如果有某些值多了或少了,那么就会引起会静默失
败——没有渐变,没有填充,没有错误信息。
下面只需要设置一下填充的起点、终点或角度了。也许大家已经猜到了,这就是神秘的
matrix(矩阵) 参数。
创建矩阵
阵此外还用于绘图(graphics)中,
我们需要为填充进行定位,设置它的大小,或是进行旋转。使用 matrix 时,需要创建一个
matix 对象,这是一个 flash.geom.Matrix 类的对象。(实际上, Matrix 类不仅用于操
作渐变填充,但这里我们只介绍它在渐变中的应用。第 18 章中介绍了更多的矩阵使用)。
型,这个方法名为 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 {
}
在不同的地方绘制这个正方形(见 GradientFill2.as):
graphics.drawRect(100, 100, 100, 100);
宽,而正方形是从 100 像素开始的,渐变色已经到达了全红色,红色从这里开始已经出界了。
因此,如果想让矩阵的 x,y 在正方形的左上角开始,应该这样写:
matrix.createGradientBox(100, 100, 0, 100, 100);
填充观察创建的填充是什么效果。首先,试一下三种颜色:
var colors:Array = [0xffffff, 0x0000ff, 0xff0000];
var alphas:Array = [1, 1, 1];
var ratios:Array = [0, 128, 255];
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)的版本。
颜色转换
类不允许创建图形,仅仅用于改变已存在于影片或显示对象实例中图形的颜色。让我们去看
看它是怎样工作的。
使用 ColorTransform 类改变颜色
和 setTransform 这样的方法。Flash 8 中就引用了 ColorTransform 类,同时 Color 类
就不再被推荐使用,但是想大多数人仍然继续使用 Color 类,因为这已经成为习惯了。Color
类已经不是 AS 3 的一部分了,现在是学习新方法的最佳时机。ColorTransform 的方法与
Color 类的方法本质上是非常像,两者差不太多,只是语法上略有不同。
transform。这是 flash.geom.Transform 类的一个实例,其中包括一些不同的属性用于缩
放,旋转,定位和改变影片颜色,影响颜色属性的就是 colorTransform。要知道这是一个
显示对象属性的属性,访问方法如下;
mySprite.transform.colorTransform
或使用一个继承自 Sprite 的类,可以直接获得类自身的 transform 属性:
transform.colorTransform
问,什么是 ColorTransform 对象?如果大家使用过 AS 2 的 Color 方法:setTransform,
就知道我们需要传入一个 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 包中的一部分,所以需要导入类。
图(位图类的实例)。因为位图类是一个显示对象,拥有 transform 属性,代码设置了位图
的 transform 的 colorTransform 属性,使用构思好的设置来制作一张底片效果的图像:
package {
}
测试这个影片时,请改变这行代码
[Embed(source="picture.jpg")]
这张图片,为ActionScript 导出,并输入类名为 Picture。重要的一句是 ColorTransform
的设置。
滤镜(Filter)
板或使用时间轴的 ActionScript 来使用滤镜,由于这本书是关于 ActionScript 的,所以
只能简单地讨论一下应用滤镜的方法。在 AS 3 中包括以下几种滤镜:
■ Drop shadow(投影滤镜)
■ Blur(模糊滤镜)
■ Glow(发光滤镜)
■ Bevel(斜角滤镜)
■ Gradient bevel(渐变斜角滤镜)
■ Gradient glow(渐变发光滤镜)
■ Color matrix(颜色矩阵滤镜)
■ Convolution(卷积滤镜)
Displacement map(置换图滤镜)
有很多滤镜使用的例子,所以在这里只介绍一下滤镜使用的总体方法和两个具体实例。
创建滤镜
filter(模糊滤镜),最简单的一种滤镜,写法入下:
var blur:BlurFilter = new BlurFilter(5, 5, 3);
参数分别为 blurX,blurY,quality。这个例子会将对象在 x 和 y 轴上模糊 5 个像素,模糊
的品质为中等。
另一点需要知道的是滤镜在其名为 flash.filters 的包中。所以要在文件的开始处将它们
导入进来:
如果希望导入包中所有的滤镜,可以使用简写:
import flash.filters.*;
部分滤镜,否则最好避免使用通配符(*),而是明确地导入所需要的类。这样做只是为了能
够清楚,哪些是真正想要导入的而哪些不是。好了,现在已经创建了一个模糊滤镜,但怎么
才能使它去模糊一个对象呢?
因为如果一个对象要应用多个滤镜,那么只需要再将模糊滤镜放到数组中即可。乐观地看,
应用滤镜应该可以像使用基本数组操作那样简单,push,就像这样
mySprite.filters.push(blur);,但是很遗憾,没有这么简单。在整个数组赋值为 filters
之前,Flash 不关心 filters 数组的变化。
滤镜粘在上面,再将这个新数组赋给 filters 属性就可以了。先来试一下,下面一个文档
类 Filters.as,创建了一个 sprite 影片并且在里面绘制了一个黄色的正方形,然后,创
建一个滤镜,加入数组中,最后将数组赋给 sprite 的 filters 属性:
package {
}
瞧!出现了一个模糊的黄色方块儿。重要的部分用黑体着重,我们可以简写一点:
var blur:BlurFilter = new BlurFilter(5, 5, 3);
var filters:Array = [blur];
sprite.filters = filters;
或再短一点:
sprite.filters = [new BlurFilter(5, 5, 3)];
兴。
办呢?在 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));
属性就足够了。
动态滤镜
现在我们已经基本上知道了如何在 ActionScript 中使用滤镜了。
识,制作一个动态滤镜。这个效果,使用文档类 AnimatedFilters.as:
package {
}
添加一个 enterFrame 事件的侦听器及处理函数:
及使用三角函数计算 sprite 影片与鼠标的距离(distance)。使用 angle 和 distance 设
置投影滤镜的 angle 和 distance 属性,最后将这个滤镜再应用到 sprite 上。请注意,
我们不需要每次都创建一个新的滤镜,可以继续使用同一个滤镜,只需要改变它的属性即可。
然而,只是改变这些属性也不能更新 sprite 影片的显示。因此,还需要再将变化过的滤镜
效果赋值给 filters 属性。
位图(Bitmaps)
与滤镜相同,可以用整本书来介绍 Bitmap 和 BitmapData 类,看起来也不错,但是这并不
是本书的目的。我们将通过一些简单的例子,用来指出 AS 2 与 AS 3 中位图处理的变化。
new BitmapData (width:Number,
height:Number,
transparent:Boolean,
fillColor:Number)
flash.display.BitmapData。所以需要导入包,对于 width 和 height 参数则非常显而易
见, transparent 参数表示创建的图像是否包涵一个 alpha 通道, 选择 true 或 false ,
fillColor 是创建图像的初始颜色,如果 transparent 为 true 的话,那么位图就用 32 位
色表示,0xAARRGGBB,如果为 false 的话,就可以使用 24 位安全色表示。
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);
忘记导入 flash.display.Bitmap 和 flash.display.BitmapData,运行后就会看到一个红
色的正方形。乍看上去,与使用绘图 API 所画的图形没什么不同,但是要知道这并不是矢
量图绘制法:填充一个红色的正方形。这是张位图图像,在位图中每一个像素都要分别指定
而且是可变的。事实上,每一个像素值都可以使用 getPixel,getPixel32 和
setPixel,setPixel32 进行读取和设置。两个版本的不同之处在于 getPixel 和 setPixel
使用 24 位色彩值忽略了 alpha 通道,而 “32”版的则使用 32 位色彩值其中包括了透明
度信息。让我们来做个例子,制作一个简单的喷漆工具,就像所有位图喷漆程序一样。
这里是文档类,SprayPaint.as:
package {
}
过,只不过又使用了一遍而已。一步步来看,首先,创建了一些类变量,包括 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 绘出
成千上万的独立图像后,会发习画得越多,速度越慢。画过几百个图形后,慢下来的速度会
变得非常明显,这个程序也就费掉了,使用加载影片剪辑的方式也是如此。但是,使用位图
就完全不同了,我们可以使用这个程序喷上一天,都不影响程序的速度或效率。
如果想看到更酷的效果,就把下面一行代码加在位图对象 bmp 的后面:
bmp.filters = [new BlurFilter(2, 2, 3)];
对象能做的最简单的操作之一。除了获取和设置像素,BitmapData 对象还有其它二十多种
方法,这些方法可用来复制像素,设置阈值,分解,合并,滚动,等等。我个人最喜欢的一
个是 perlinenoise 方法,该函数允许我们创建一个随机的有组织的图案。对于制造烟,云
和水波纹效果都非常有用。有兴趣的话大家可以试验一下。
读取和嵌入资源
两种方法,一种是在动画播放时将资源读入,这就是我们所熟知的读取(loading)。另一种
方法是在 SWF 编译时嵌入(embed)资源。
读取资源
loader 是个显示对象,意味着可以使用 addChild() 方法将它加入到显示列表中,就像
sprite 和 bitmap 一样。然后告诉这个 loader 去读取一个外部 SWF 或外部位图,如
JPEG,PNG,等等。
在 AS 3 中,则需要创建一个 flash.net.URLLoader 实例,传入表示路径的字符串,并且
还需要一个额外的步骤,虽然有些烦人,但是我们还是要习惯这种用法。
这里是一个在运行时读取外部资源的例子(文档类 LoadAsset.as):
package {
}
嵌入资源
加载到 SWF 自里面。这时,如果使用 Flash IDE,可以简单地导入这个对象到库中并设置
为“为 ActionScript 导出”。但在使用 Flex Builder 2 或 Flex 2 SDK 命令编译器时,
没有库,那么如何在 SWF 中加载外部资源呢?
ActionScript 文件中的非正式 ActionScript 语句。另外,它们指示编译器在编译过程中
去做某种事情, [Embed]标签告诉编译器在最终的 SWF 文件中加载一个特殊的外部资源,资
源可以是位图或外部 SWF 文件。告诉编译器要嵌入的资源所在的 source 路径的属性,如
下:
[Embed(source="picture.jpg")]
在元数据语句的后面,直接声明一个 Class 类型的变量,如下:
[Embed(source="picture.jpg")]
private var Image:Class;
现在可以使用这个变量创建一个新的资源实例,如下:
var img:Bitmap = new Image();
象应该是 Sprite 类型的,如下:
[Embed(source="animation.swf")]
private var Anim:Class;
var anim:Sprite = new Anim();
这里是一个在 SWF 中嵌入外部 JPEG 的例子:
package {
}
一个类名就可以了。不需要使用 [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里面涉及到颜色的要素都将明白了 哈哈 灵活运用会有很多意想不到的功能