11
2015
09

createGradientBox

createGradientBox是Matrix类中的一个方法,在做渐变填充(beginGradientFill)或渐变笔触(lineGradientStyle)的时候可能会用到。

createGradientBox有5个参数,如下,参数的涵义,官方API写的很清楚,可以看一下。

  • 渐变框宽度:渐变扩展到的宽度(以像素为单位)

  • 渐变框高度:渐变扩展到的高度(以像素为单位)

  • 渐变框旋转:将应用于渐变的旋转角度(以弧度为单位)

  • 水平平移:将渐变水平移动的距离(以像素为单位)

  • 垂直平移:将渐变垂直移动的距离(以像素为单位)

虽然写的很清楚,但是这几个参数到底是什么意思呢,下面,我们就结合flash中的渐变变形工具来理解一下。

在flash中,画一个矩形,填充选为线性渐变,用渐变变形工具选中刚才的矩形,如下。

为了看的清,我稍微拉伸了一下,可以看到两条蓝色的线,这两条蓝色的线组成的矩形,就是GradientBox(渐变框)。渐变框的宽度高度旋转角度就是矩形的宽度高度旋转角度,需要注意的是平移,平移值得是矩形框中间那个小圆点(flash中可以拖动改变位置)相对于父容器坐标原点的位移。其实,如果做过变形框,就很好理解了,变形框和元件是分离的,其实我们操作的是变形框,只是在变形框变形的时候,对可视元件也做了相同的变形操作。

下面是旋转之后的。

matrix对象调用createGradientBox之后,matrix对象的属性值就和这个渐变框的matrix属性值相同了。如此看来,其实我们可以直接创建matrix或者通过旋转平移缩放来得到GradientBox的matrix,而不必使用createGradientBox,createGradientBox只是提供了一些便利而已。

例1

下面是官方帮助文档中的例子。

 var myMatrix:Matrix = new Matrix();
             trace(myMatrix.toString());          // (a=1, b=0, c=0, d=1, tx=0, ty=0)
             
             myMatrix.createGradientBox(200, 200, 0, 50, 50);
             trace(myMatrix.toString());          // (a=0.1220703125, b=0, c=0, d=0.1220703125, tx=150, ty=150)
             
             var colors:Array = [0xFF0000, 0x0000FF];
             var alphas:Array = [100, 100];
             var ratios:Array = [0, 0xFF];
             
             this.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, myMatrix);
             this.graphics.drawRect(0, 0, 300, 200);

画出的图形如下:

createGradientBox的参数是(200, 200, 0, 50, 50),也就是一个宽200、高200的矩形框,没有旋转,沿x轴y轴分别平移50。

渐变框实际应该就是图中黑色的矩形框,flash中线性渐变沿高度方向平移不起作用。所以,你会看到flash中渐变框沿y轴没有平移。

那么这个矩形框的matrix值应该是多少呢?

把矩形框看做一个影片剪辑,影片剪辑的原点为中心(即小圆点坐在的位置),那么,它的matrix应该是(a=1, b=0, c=0, d=1, tx=150, ty=150)。

等一下,实际输出的matrix却是(a=0.1220703125, b=0, c=0, d=0.1220703125, tx=150, ty=150),tx、ty没有问题,a和d的值错了。

例2

如果我们把旋转角度改为30°试试。

myMatrix.createGradientBox(200, 200, Math.PI/6, 50, 50);

发现输出变成了(a=0.10571599167290512, b=0.06103515624999999, c=-0.06103515624999999, d=0.10571599167290512, tx=150, ty=150),

按照我们上面的理论,矩形框的matrix应该是d=a=cos(30°)=根号3/2=0.8660254037844387,b=sin(30°)=0.5,c=-b=-0.5;

仔细观察,上面的输出结果中,a和d还是相等的,c还是等于-b的,我们算一下:

0.8660254037844387/0.10571599167290512=8.192;

0.5/0.06103515624999999=8.192;

比值是相等的。

同样,对于第一个例子:

1/0.1220703125=8.192;

初步猜想:也就是说,两个matrix只是a/b/c/d值差了一个比例系数。我们在不使用createGradientBox计算出matrix之后,应该给abcd除以8.192,再用于beginGradientFill和lineGradientStyle就得到预期的结果了。

我们知道,ad乘以一个系数,代表的物理含义是缩放,bc乘以一个系数代表的物理含义是倾斜或剪切。

例3

上面的例子(用例2,因为可以看到bc的值),我们用的宽高都是200,如果我们改变宽高值,比如把高改为400,会怎么样呢?

试验发现输出变成了(a=0.10571599167290512, b=0.12207031249999999, c=-0.06103515624999999, d=0.21143198334581023, tx=150, ty=250)。

对比一下,发现,b和d都变成了原来的两倍。

按照我们上面的理论,矩形框的matrix还应该是a=cos(30°)=根号3/2=0.8660254037844387,b=sin(30°)=0.5,c=-b=-0.5;

再来分析一下:

我们上面没有考虑矩形框的缩放,矩形的宽高就是我们设置的宽高,matrix中是不涉及宽高的,矩形的宽高不同只会影响tx和ty,实际上我们发现,高变为原来的两倍,d会变为原来的两倍,也就是说,是有缩放的,既然有缩放,就要有一个scale=1时的基础宽高。高200的时候,d的比值是8.192,也就是说基础高应该是200*8.192=1638.4。b和d有着相同的缩放变化,所以我们不妨简单的理解为,高的缩放会影响bd的缩放,同样的,宽会影响ac。

同样,我们计算一下基础宽的值,同样为200*8.192=1638.4。

也就是说,变形框的初始宽高为1638.4,当我们创建的变形框,都是由一个宽高都是1638.4的矩形框变形得到的。对于宽是如何影响ac的值的,还不能解释。但是经过验证,确实是可行的。

总结一下:

matrix.a = Math.cos(r) * w / 1638.4;

matrix.d = Math.cos(r) * h / 1638.4;

matrix.b = Math.sin(r) * h / 1638.4;

matrix.c = -Math.sin(r) * w / 1638.4;

对于tx,ty常规处理即可。

其中,r是旋转角度,单位弧度,w、h为宽高。

例4

如myMatrix.createGradientBox(200, 400, Math.PI/6, 50, 50);

等价于:

myMatrix.a = Math.cos(Math.PI/6) * 200 / 1638.4;

myMatrix.d = Math.cos(Math.PI/6) * 400 / 1638.4;

myMatrix.b = Math.sin(Math.PI/6) * 400 / 1638.4;

myMatrix.c = -Math.sin(Math.PI/6) * 200 / 1638.4;

myMatrix.tx=200/2+50;

myMatrix.ty=400/2+50;

可自行验证。


继续。

如果createGradientBox创建的真的是falsh中我们看到的那个变形框的话,我们知道,对于线性渐变填充,改变高度,并不会改变填充效果。

试验一下:

var myMatrix:Matrix = new Matrix();
             trace(myMatrix.toString());          // (a=1, b=0, c=0, d=1, tx=0, ty=0)
             
             myMatrix.createGradientBox(200, 400,  Math.PI/6, 50, 50);
             trace(myMatrix.toString());          // (a=0.10571599167290512, b=0.12207031249999999, c=-0.06103515624999999, d=0.21143198334581023, tx=150, ty=250)
             
             var colors:Array = [0xFF0000, 0x0000FF];
             var alphas:Array = [100, 100];
             var ratios:Array = [0, 0xFF];
             
             this.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, myMatrix);
             this.graphics.drawRect(0, 0, 400, 200);
			 
myMatrix = new Matrix();             
             myMatrix.createGradientBox(200, 100, Math.PI/6, 50, 260);
             trace(myMatrix.toString());          //(a=0.10571599167290512, b=0.030517578124999997, c=-0.06103515624999999, d=0.05285799583645256, tx=150, ty=310)
             
             this.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, myMatrix);
             this.graphics.drawRect(0,210, 400, 200);

createGradientBox的参数,只有高度不一样(y方向平移是为了弥补画图位置的偏移),第一个是400,第二个是100。画出的图如下:

两个图的填充明显不一样。也就是说,我们前边关于createGradientBox创建的就是那个渐变框,以及渐变框的属性与createGradientBox中参数的对应关系,等等,都是错的,或者哪里有问题。我猜想,问题出在旋转那里,旋转并不是绕渐变框的中心那个小圆圈旋转。

越来越理不清了。

如果我们不管createGradientBox方法,就是想要按照我上面理解的变形宽来设置渐变填充的话,改为下面这样就可以了。

matrix.a = Math.cos(r) * w / 1638.4;

matrix.d = Math.cos(r) * h / 1638.4;

matrix.b = Math.sin(r) * w / 1638.4;

matrix.c = -Math.sin(r) * h / 1638.4;

对于tx,ty常规处理即可。

对于放射性渐变填充,上面的公式同样适用。

同样,对于渐变笔触也适用。


有空做个演示的demo放在这里。

。。。。。。

« 上一篇下一篇 »

相关文章:

闪电效果  (2017-11-28 15:4:19)

线段与椭圆的交点  (2017-1-6 14:43:41)

as3录制swf并保存flv视频  (2016-12-28 8:43:41)

解九连环  (2016-12-1 20:58:11)

as3实现setTimeout和trace  (2016-11-10 16:47:37)

registerCursor注册系统光标  (2016-9-14 9:49:40)

鼠标光标管理  (2016-9-13 17:44:3)

变形框(transform)实现  (2016-9-13 16:56:6)

flash文本消除锯齿不显示  (2016-8-25 11:43:31)

greenSock的easing曲线  (2016-8-24 18:30:11)

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。