スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | | スポンサー広告

アマゾンのトップページ風セレクト

正式には何て言うんだか知らないのですが、amazonのトップページにあらわれる商品画像がグルグル回るフラッシュ風のサンプルです。





マウスカーソルの位置によって、回転の速度/向きが変化します。あと、画像の上にマウスカーソルもってくと画像が青くふちどられます。

やってることは、透視変換を使った位置/サイズの調整、床反射、ロールオーバー時フィルタぐらいでしょうか。今回は、透視変換を使った位置/サイズの調整はクラスをわけてみました。

スクリプトですが、まずフレームアクションの方です。

// 回転速度係数
var speed:Number = 0.02;
// 回転半径
var r:Number = 250;
// 床反射アルファ
var reflectAlpha:Number = 0.6;
// 表示画像配列
var mc_array:Array = [image1_mc,
image2_mc,
image3_mc,
image4_mc,
image5_mc,
image6_mc];
// 表示スプライト配列を生成
var sp_array:Array = new Array();
for (var idx:uint = 0, iEnd = mc_array.length;
idx < iEnd;
idx++) {
sp_array.push(createSprite(mc_array[idx]));
}
// ロールオーバー時グローフィルタ
var gFilter:GlowFilter = new GlowFilter(0x0000FF,
0.6,
8,
8,
4,
1,
false,
false);
// 透視変換ボックス
var box:PerspectiveBox = new PerspectiveBox(300);
addChild(box);
box.x = stage.stageWidth / 2;
box.y = stage.stageHeight / 2;
// 回転処理
var angle:Number = 0;
addEventListener(Event.ENTER_FRAME,
function(e:Event) {
var dx:Number = stage.stageWidth / 2
- stage.mouseX;
angle += dx * speed;
var cnt:uint = sp_array.length;
for (var i:uint = 0; i < cnt; i++) {
var ang:Number = angle + i * 360 / cnt;
if (ang < 0) {
ang += 360;
} else if (ang > 360) {
ang -= 360;
}
var cos = Math.cos(ang * Math.PI / 180);
var sin = Math.sin(ang * Math.PI / 180);
box.removeObject(sp_array[i]);
sp_array[i].x = r * sin;
box.addObject(sp_array[i], r * -cos + 200);
}
});
// 指定したムービークリップを元に表示用スプライトを生成し、
// 戻します。
function createSprite(mc:MovieClip):Sprite {
var sp:Sprite = new Sprite();
// 床面反射
var bd:BitmapData
= new BitmapData(mc.width, mc.height, true, 0x000000);
var mtx:Matrix = new Matrix();
mtx.scale(1.0, -1.0);
mtx.ty = mc.height;
var rect:Rectangle = new Rectangle(0, 0, mc.width, mc.height);
bd.draw(mc,
mtx,
new ColorTransform(),
BlendMode.NORMAL,
rect,
true);
var bitmap:Bitmap = new Bitmap(bd);
bitmap.smoothing = true;
sp.addChild(bitmap);
bitmap.x = -mc.width / 2;
bitmap.y = 0;
// グラデーション
var msk:Sprite = new Sprite();
var g:Graphics = msk.graphics;
mtx = new Matrix();
mtx.createGradientBox(bitmap.width,
bitmap.height,
Math.PI / 2);
g.beginGradientFill(GradientType.LINEAR,
[0xFFFFFF, 0xFFFFFF],
[reflectAlpha, 1.0],
[0, 255],
mtx);
g.moveTo(0, 0);
g.lineTo(0, bitmap.height);
g.lineTo(bitmap.width, bitmap.height);
g.lineTo(bitmap.width, 0);
g.lineTo(0, 0);
g.endFill();
sp.addChild(msk);
msk.x = bitmap.x;
msk.y = bitmap.y;
// ムービークリップ
sp.addChild(mc);
mc.x = -mc.width / 2;
mc.y = -mc.height;
mc.addEventListener(MouseEvent.MOUSE_OVER,
function (e:Event) {
e.target.filters = [gFilter];
});
mc.addEventListener(MouseEvent.MOUSE_OUT,
function (e:Event) {
e.target.filters = [];
});
// y座標
sp.y = 100;
return sp;
}
image1_mc, image2_mc, ...というのは表示する画像をシンボル化したモノです。ですが、実際表示するのはコレ+床反射画像を含むスプライトで、これはcreateSpriteメソッドで作ってsp_array配列に入れてます。

createSpriteメソッドでは、表示画像を上下反転した画像を作ってその上に白いグラデーション画像をかぶせるのと、表示画像のマウスオーバーでフィルタをセット/マウスアウトでフィルタ解除の設定をしてます。あと、作ったスプライトのy座標も設定しています。サンプルではy座標に100を設定してるので、視点の中心よりも下に画像が表示されます。また生成したスプライトは、表示画像の下辺の中央が基準点になります。

画像マウスオーバー時のふちどりにはGlowFilterを使ってマス。パラメータはテキトーです。

PerspectiveBoxは今回作成したクラスで、子を透視変換して表示するスプライトです。コイツをステージ中央に配備しています。

回転についてはENTER_FRAMEイベントハンドラで、マウスカーソルの位置からx座標/z座標を算出しています。y座標は生成時のままです。ココで算出した座標をPerspectiveBoxが透視変換して最終的なx座標/y座標/幅/高さが決定します。

そんで、PerspacetiveBoxのソースコードです。
package {
import flash.display.*;
/**
* 表示オブジェクトを遠近法表現するボックス。
*/
public class PerspectiveBox extends Sprite {
/** 表示オブジェクトの配列 */
private var _obj_array:Array;
/** スクリーンまでの距離 */
private var _distance:Number;
/**
* コンストラクタ。
*/
public function PerspectiveBox(distance:Number = 100) {
_obj_array = new Array();
_distance = distance;
}
/**
* オブジェクトを追加します。
* @param obj 追加する表示オブジェクト
* @param z 表示オブジェクトのz座標
*/
public function addObject(obj:DisplayObject, z:Number) {
removeObject(obj);
var item:Object = new Object();
_obj_array.push(item);
addChild(obj);
item.obj = obj;
item.orgX = obj.x;
item.orgY = obj.y;
item.orgW = obj.width;
item.orgH = obj.height;
item.z = z;
doPerspective();
}
/**
* 指定したオブジェクトをボックスから削除します。
* @param obj 削除するオブジェクト
*/
public function removeObject(obj:DisplayObject) {
var idx:int = indexOf(obj);
if (idx >= 0) {
var item:Object = _obj_array[idx];
item.obj.width = item.orgW;
item.obj.height = item.orgH;
item.obj.x = item.orgX;
item.obj.y = item.orgY;
_obj_array.splice(idx, 1);
removeChild(item.obj);
}
}
/**
* 指定したオブジェクトのインデックスを戻します。
* @return オブジェクトのインデックス。
*/
public function indexOf(obj:DisplayObject):int {
for (var i:uint = 0, iEnd:uint = _obj_array.length;
i < iEnd;
i++) {
var item:Object = _obj_array[i];
if (item.obj == obj) {
return i;
}
}
return -1;
}
/**
* 遠近法に基づき表示オブジェクトの位置/サイズを調整します。
*/
private function doPerspective() {
for each (var item:Object in _obj_array) {
// 縮小率
var s:Number = _distance / (_distance + item.z);
// 位置
item.obj.x = item.orgX * s;
item.obj.y = item.orgY * s;
// サイズ
item.obj.width = item.orgW * s;
item.obj.height = item.orgH * s;
}
// depth
_obj_array.sortOn("z", Array.DESCENDING | Array.NUMERIC);
for (var i:uint = 0, iEnd:uint = _obj_array.length;
i < iEnd;
i++) {
setChildIndex(_obj_array[i].obj, i);
}
}
}
}
_obj_arrayフィールドは表示オブジェクトの情報の配列で、表示オブジェクト(サンプルではフレームアクションで生成したスプライト)/元の位置とサイズ/z座標を持つオブジェクトの配列です。_distanceは視点から表示スクリーンまでの距離でコンストラクタで指定します。透視変換で縮小率を決定するのに使いマス。

addObjectメソッドで、透視変換して表示するオブジェクトを追加します。このときにz座標も指定します。表示オブジェクトや元のサイズやz座標をプロパティに持つオブジェクトを生成して、_obj_arrayに追加しています。

removeObjectメソッドは、addObjectメソッドで追加した表示オブジェクトを透視変換の対象から外します。このとき、位置/サイズはaddObject時の状態に戻しています。

indexObjectメソッドは、指定した表示オブジェクトが_obj_array配列のどこに保持されているかを戻します。見つからなかったら-1デス。

doPerspectiveメソッドが透視変換をするメソッドです。_distanceとz座標から縮小率を算出して、位置とサイズを調整してます。あと、z座標に従って重なり順も調整しています。
スポンサーサイト

テーマ:Flash - ジャンル:コンピュータ

2007.07.22 | | Comments(1) | Trackback(0) | Flash CS3

コメント

管理人のみ閲覧できます

このコメントは管理人のみ閲覧できます

2009-02-12 木 18:29:50 | | # [ 編集]

コメントの投稿


秘密にする

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

名前:
メール:
件名:
本文:

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。