http://www.gotoandlearn.com/ 站里有一个旋转木马的效果(carousel 的英译),
源文件的下载地址是:
http://gotoandlearn.com/files/carousel.zip
该源文件为 AS2.0 版的代码,代码如下:
var numOfBalls:Number = 10;
var radiusX:Number = 250;
var radiusY:Number = 75;
var centerX:Number = Stage.width / 2;
var centerY:Number = Stage.height / 2;
var speed:Number = 0.05;
for(var i=0;i<numOfBalls;i++)
{
var t = this.attachMovie("ball","b"+i,i+1);
t.angle = i * ((Math.PI*2)/numOfBalls);
t.onEnterFrame = mover;
}
function mover()
{
this._x = Math.cos(this.angle) * radiusX + centerX;
this._y = Math.sin(this.angle) * radiusY + centerY;
var s = this._y /(centerY+radiusY);
this._xscale = this._yscale = s*100;
this.angle += this._parent.speed;
this.swapDepths(Math.round(this._xscale) + 100);
}
this.onMouseMove = function()
{
speed = (this._xmouse-centerX)/1500;
}
在尝试改写为 AS3.0 代码的过程中,发现层深的调整是最麻烦的部分,根据 y 轴上的分布关系来调整层深,就必须进行排序的处理,于是想到了冒泡法排序,有了下面的代码:
// 全局参数
var numOfBalls:Number = 10;
var radiusX:Number = 250;
var radiusY:Number = 75;
var centerX:Number = stage.stageWidth / 2;
var centerY:Number = stage.stageHeight / 2;
var speed:Number = 0.05;
var arr = new Array();
//创建对象
for (var i=0; i<numOfBalls; i++) {
var t = new Ball();
addChild(t);
t.angle = i * ((Math.PI*2)/numOfBalls);
t.addEventListener(Event.ENTER_FRAME, mover);
arr.push( t );
}
//冒泡法排序
function sortArr() {
var i,bound;
var j =arr.length - 1;
while ( j>0 ) {
bound = j;
j = 0;
for ( i= 0; i<= bound -1; i++) {
if ( arr[i+1].y < arr[i].y ) {
swapChildrenAt(i,i+1);
var xt = arr[i];
arr[i] = arr[i+1];
arr[i+1] = xt;
j = i;
}
}
}
}
//摆放对象
function mover(evt:Event) {
var t = evt.target;
t.x = Math.cos( t.angle) * radiusX + centerX;
t.y = Math.sin( t.angle) * radiusY + centerY;
var s = t.y /(centerY+radiusY);//求出缩放比
t.scaleX = t.scaleY = s;
t.angle += speed;//设置移动速度
sortArr();
}
//鼠标侦听
addEventListener(MouseEvent.MOUSE_MOVE, onMM);
function onMM(evt:MouseEvent) {
speed = ( mouseX - centerX)/1500;
}
上面的代码,除了增加了一个数组,和一个排序函数以外,其它结构与 AS2 版的代码相同,从执行的效率来看,还是蛮不错的。
排序函数不易理解,于是考虑有没有更简便的方法。详读数组的排序函数之后,终于知道这样两种方案:
方案一 使用 数组的 sort 方法,指定比较函数,从而得到按 y 值进行排序的数组:
function sortArr() {
arr.sort(sortOnY);
for (i=0; i<numOfBalls; i++) {
swapChildrenAt(getChildIndex(arr[i]),i);
} }
function sortOnY(a:Light, b:Light):Number {
var aValue:Number = a.y;
var bValue:Number = b.y;
if (aValue > bValue) {
// swapChildren(a,b);
// 测试中发现,此函数中直接加入交换层深代码,得不到正确的结果。原因可能是 sort 的内部交换算法的先后次序未知,造成。
return 1;
} else if (aValue < bValue) {
return -1;
} else {
//aValue == bValue
return 0;
}
}
方案二 使用 数组的 sortOn 方法,指定比较的属性“y”,从而得到按 y 值进行排序的数组:
function sortArr() {
arr.sortOn("y");
for (i=0; i<numOfBalls; i++) {
swapChildrenAt(getChildIndex(arr[i]),i);
}
}
第二个方案的办法,结构比较简单,效率不如直接用冒泡法高,在赶时间的情况下,可以考虑采用。
最终效果如下: