特别鸣谢:帅帅の楠瓜 分享这样的好文章
文章出自:帅帅の楠瓜
A3D CoverFlow 图像展示效果:
作者:ssnangua 发布于:2011-9-12 17:45 Monday
这是一个类似 iTunes 的 CoverFlow 的效果,图片一字排开,某张图片被点击后滑出放大,顺畅而动感。另外,也可以通过滚动鼠标滚轮快速地切换图片。
这个例子的重点在图片要分成三部分处理:
1. 所选图片:角度为0(rotationZ=0)。移到舞台中间(x=0),并放大(减小y值)
2. 所选图片左边的图片:角度为正值(rotationZ>0)。根据与所选图片深度(index)的差值确定x值大小,差值越大,x值越小
3. 所选图片右边的图片:角度为负值(rotationZ<0)。根据与所选图片深度(index)的差值确定x值大小,差值越大,x值越大
package
{
import alternativa.engine3d.containers.ConflictContainer;
import alternativa.engine3d.core.Camera3D;
import alternativa.engine3d.core.View;
import alternativa.engine3d.materials.TextureMaterial;
import alternativa.engine3d.loaders.MaterialLoader;
import alternativa.engine3d.loaders.events.LoaderEvent;
import alternativa.engine3d.core.Object3DContainer;
import alternativa.engine3d.core.Object3D;
import alternativa.engine3d.core.MouseEvent3D;
import alternativa.engine3d.primitives.Plane;
import alternativa.engine3d.controllers.SimpleObjectController;
import gs.TweenLite;
import flash.display.*;
import flash.text.TextField;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.*
import flash.system.LoaderContext;
import flash.filters.BlurFilter;
/**
* Alternativa3D 7.8.0
* CoverFlow 图像展示效果
* @author www.ssnangua.com
*/
[SWF(backgroundColor="#CCCCCC", frameRate="100", width="980", height="470")]
public class CoverFlow extends Sprite
{
private var rootContainer:ConflictContainer = new ConflictContainer(); //3D根容器
private var camera:Camera3D = new Camera3D(); //3D摄像机
private var view:View; //视窗
private var imageNum:uint = 11; // 图片总数
private var radius:Number = 600; // 图片分布范围半径
private var imageLoadedNum:uint = 0; // 已加载图片数
private var loadProgressTxt:TextField; // 显示加载进度的文本
private var imageContainer:Object3DContainer; // 图片容器
private var materials:Vector.<TextureMaterial>; // 存放材质的数组
private var selectIndex:uint = 0; // 目前所选 Plane 序号
public function CoverFlow():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.scaleMode = "exactFit";
// 三维环境
view = new View(stage.stageWidth, stage.stageHeight);
view.hideLogo();
camera.view = view;
camera.y = -1200;
camera.rotationX = -90 * Math.PI / 180;
addChild(view);
rootContainer.addChild(camera);
// 平面容器
imageContainer = new Object3DContainer();
rootContainer.addChild(imageContainer);
// 加载进度显示
loadProgressTxt = new TextField();
loadProgressTxt.autoSize = "left";
stage.addChild(loadProgressTxt);
// 材质
materials = new Vector.<TextureMaterial>;
for(var i:int=0; i<imageNum; i++) {
var mat:TextureMaterial = new TextureMaterial();
mat.diffuseMapURL = "images/" + String(i) + ".jpg";
//mat.diffuseMapURL = "http://i1112.photobucket.com/albums/k483/ssnangua/pictureShow/" + String(i+1) + ".jpg";
materials.push(mat);
}
var context:LoaderContext = new LoaderContext(true);
var matLoader:MaterialLoader = new MaterialLoader();
matLoader.load(materials,context);
// 加载进度
matLoader.addEventListener(LoaderEvent.PART_COMPLETE, matLoading);
// 材质加载完成添加图片
matLoader.addEventListener(Event.COMPLETE, matLoadComplete);
// 渲染
addEventListener(Event.ENTER_FRAME, onRender);
}
// 渲染
private function onRender(e:Event):void
{
camera.render();
}
// 监测材质加载进度
private function matLoading(e:LoaderEvent):void {
imageLoadedNum ++;
loadProgressTxt.text = "Loading : " + imageLoadedNum + " / " + imageNum;
loadProgressTxt.x = (stage.stageWidth - loadProgressTxt.width) / 2;
loadProgressTxt.y = (stage.stageHeight - loadProgressTxt.height) / 2;
}
// 材质加载完成 创建平面
private function matLoadComplete(e:Event):void
{
stage.removeChild(loadProgressTxt);
for(var i:int=0; i<imageNum; i++) {
// 图片
var plane:Plane = new Plane(200,150);
plane.setMaterialToAllFaces(materials[i]);
imageContainer.addChild(plane);
plane.useHandCursor = true;
plane.rotationX = Math.PI / 2; // 将平面立起来
plane.addEventListener(MouseEvent3D.CLICK, selectPlane);
// 影子
var shadow:Plane = new Plane(200,150);
shadow.setMaterialToAllFaces(new TextureMaterial(reflect(materials[i].texture)));
imageContainer.addChild(shadow);
shadow.filters = [new BlurFilter()];
shadow.rotationX = Math.PI / 2;
shadow.z = -150;
}
// 初始化 跳到第6张图片
shiftToPlane(10);
// 添加舞台滚轮事件
stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheel);
}
// 点击平面变大 并移到舞台中间
private function selectPlane(e:MouseEvent3D):void {
shiftToPlane(imageContainer.getChildIndex(e.currentTarget as Plane));
}
// 舞台鼠标滚轮事件
private function mouseWheel(e:MouseEvent):void {
if(e.delta < 0) {
if (selectIndex < (imageNum-1)*2) shiftToPlane(selectIndex + 2);
} else {
if (selectIndex > 0) shiftToPlane(selectIndex - 2);
}
}
// 跳到指定 Plane
private function shiftToPlane(id:uint):void {
selectIndex = id;
var planeTemp1:Plane;
var planeTemp2:Plane;
var dis:int;
for(var i:uint=0; i<imageContainer.numChildren; i+=2) {
planeTemp1 = imageContainer.getChildAt(i) as Plane; //平面
planeTemp2 = imageContainer.getChildAt(i+1) as Plane; //影子
dis = i-id;
// 当前平面
if(i==id) {
TweenLite.to(planeTemp1, 0.5, {
x : 0,
y : -750,
rotationZ : 0
});
TweenLite.to(planeTemp2, 0.5, {
x : 0,
y : -750,
rotationZ : 0
});
}
// 当前平面左边的图片
else if(i<id) {
TweenLite.to(planeTemp1, 0.5, {
x : dis * 70 - 180,
y : 0,
rotationZ : 60 * Math.PI/180
});
TweenLite.to(planeTemp2, 0.5, {
x : dis * 70 - 180,
y : 0,
rotationZ : 60 * Math.PI/180
});
}
// 当前平面右边的图片
else {
TweenLite.to(planeTemp1, 0.5, {
x : dis * 70 + 180,
y : 0,
rotationZ : -60 * Math.PI/180
});
TweenLite.to(planeTemp2, 0.5, {
x : dis * 70 + 180,
y : 0,
rotationZ : -60 * Math.PI/180
});
}
}
}
// 倒影
/**
* pTarget : 需要被透明度渐变的 BitmapData
* pRatioFade : 开始渐变的透明度 值在[0,1]间
* pRatioEndFade: 结束渐变的透明度 值在[0,1]间
* _numMidLoc : 开始渐变的位置 值在[0,1]间
* 返回 : 透明度渐变后的 BitmapData
*/
private function reflect(pTarget:BitmapData, pRatioFade:Number = .6, pRatioEndFade:Number = 0, _numMidLoc:Number = .4 ):BitmapData
{
var _resultBmp :BitmapData = new BitmapData(pTarget.width, pTarget.height, true, 0);
var _matSkew :Matrix = new Matrix(1, 0, 0, -1, 0, pTarget.height);
var _recDraw :Rectangle = new Rectangle(0, 0, pTarget.width, pTarget.height);
var _potSkew :Point = _matSkew.transformPoint(new Point(0, pTarget.height));
_matSkew.tx = _potSkew.x * -1;
_matSkew.ty = (_potSkew.y - pTarget.height) * -1;
_resultBmp.draw(pTarget, _matSkew, null, null, _recDraw, true);
var _gradientShape:Shape = new Shape();
var _fillType :String = GradientType.LINEAR;
var _colorsArr :Array = [0, 0 , 0];
var _alphasArr :Array = [pRatioFade, (pRatioFade - pRatioEndFade) / 2, pRatioEndFade];
var _ratiosArr :Array = [0, 0xFF * _numMidLoc, 0xFF];
var _gradientMat :Matrix = new Matrix();
var _spreadMethod :String = SpreadMethod.PAD;
_gradientMat.createGradientBox(pTarget.width, pTarget.height / 2, Math.PI / 2);
_gradientShape.graphics.beginGradientFill(_fillType, _colorsArr, _alphasArr, _ratiosArr, _gradientMat, _spreadMethod)
_gradientShape.graphics.drawRect(0, 0, pTarget.width, pTarget.height);
_gradientShape.graphics.endFill();
_resultBmp.draw(_gradientShape, null, null, BlendMode.ALPHA);
_gradientShape = null;
return _resultBmp
}
}
}