forked from: 3D Carousel
Papervision3Dで被写界深度
* 参照: http://clockmaker.jp/blog/2008/07/pv3d_gw_blur/
// forked from tkinjo's 3D Carousel
// forked from tkinjo's forked from: PV3D Carousel
// forked from tkinjo's PV3D Carousel
// forked from clockmaker's [PV3D] Field of Blur
/**
* Papervision3Dで被写界深度
* 参照: http://clockmaker.jp/blog/2008/07/pv3d_gw_blur/
*/
package
{
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Point;
import com.flashdynamix.motion.Tweensy;
[SWF( width=475, height=475, frameRate=60, backgroundColor="#000000" )]
/**
* 背景を白にしたい?
* それは…
*
* @author ...
*/
public class Main extends Sprite
{
private var imgData:String = "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDzOlwfQ0DqK7LvQBxuD6UYPpXabH/uN+Ro2P8A3G/I0AcXg+lGD6V2mx/7jfkaNj/3G/I0AcXg+lGD6V2mx/7jfkaNj/3G/I0AcXg+lGD6V2mx/wC435GjY/8Acb8jQBxeD6UmMV2hDDqCPrWPr3+qh/3jQBh0UUUAKOortE/1q/Ufzrix1Fdon+tX6/1oA3KKKKANTRtMj1J5llkdPLCkbcd8/wCFLrOlxaaYPKkd/M3Z3Y4xj0+tXPCn+tuv91P607xX1s/+2n/stAHOUUUUAFFFFAFPUf8AUp/vf0rlte/1UP8AvGup1L/Up/vf41y2vf6qH/eNAGHRRRQAo6iuzU4kUnoDXGDqK7LvQBs/aYP+eq/nR9pg/wCeq/nWNijFAHe+EZUklu9jBsBM4/GneLpEjNlvYLnzMZ/4DWf4C/11/wD7sf8A7NT/AB9107/tr/7JQBjfaYP+eq/nR9pg/wCeq/nWNikxQBtfaYP+eq/nR9pg/wCeq/nWLijFAGhfTRyRqEcMQ2eK5nXv9VD/ALxrXrI17/VQ/wC8aAMOiiigBR1Fdl3rjR1Fdl3oAMj1pMj1Fd34GRW0253KD++9M/wiup8pP+ea/lQBxfgIjzr/AJ/hj/8AZqd4+Izp3P8Az1/9krs1RVztUD1wMUMobGVB9MjNAHjWR6ijI9RXsnlJ/wA81/Kjyk/55r+VAHjeR6ijI9RXsnlJ/wA81/Kjyl/55r+VAHjlZGvf6qH/AHjXQ6rgazfYxj7RJj/vo1z2vf6qH/eNAGHRRRQAo6iuy71xo6iuy70AIQD2o2j0FLRQB1/gIATX/wDux/8As1O8fAZ07j/nr/7JSeAv9df/AO7H/wCzU7x9/wAw7/tr/wCyUAcZtHoPypNo9BTqKAG7R6CjaPQU6igArI17/VQ/7xrXrI17/VQ/7xoAw6KKKAFHUV2XeuMHBrc/t6P/AJ4N/wB9UAa9FZH9vR/88G/76o/t6P8A54N/31QBuQXVzakm3uJYS3UxuVz+VE93c3W37RcTTbfu+bIWx+dYf9vR/wDPBv8Avqj+3o/+eDf99UAa9FZH9vR/88G/76o/t6P/AJ4N/wB9UAa9FZH9vR/88G/76o/t6P8A54N/31QBr1ka9/qof940f29H/wA8G/76qlqGoLepGqxldpJ5OaAKFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB//9k=";
private static const ITEM_LENGTH:uint = 6;
private static const CAROUSEL_RADIUS:uint = 400;
private static const PROJECTION_Y:Number = 200;
private var carouselItems:Vector.<Sprite>;
private var carouselRotation:Number;
private var carouselFrontItem:uint;
private var container:Sprite;
private var perspectiveProjection:PerspectiveProjection;
public function Main()
{
Base64ImageLoader.load( imgData, complete );
}
/**
*
* @param event
*/
private function complete( event:Event ):void {
perspectiveProjection = root.transform.perspectiveProjection;
rotation = 0;
carouselItems = new Vector.<Sprite>();
container = new Sprite();
container.x = ( stage.stageWidth ) / 2;
container.y = ( stage.stageHeight ) / 2;
container.z = CAROUSEL_RADIUS;
addChild( container );
for ( var i:uint = 0; i < ITEM_LENGTH; i++ ) {
var img:Bitmap = event.target.content as Bitmap;
var carouselItem:Sprite = new Sprite();
/** --------------------
* carouselItemImg
*/
var carouselItemImg:DisplayObject = new Bitmap( img.bitmapData );
//carouselItemImg.scaleX = 100 / carouselItemImg.width;
//carouselItemImg.scaleY = 100 / carouselItemImg.height;
carouselItemImg.x = -carouselItemImg.width / 2;
carouselItemImg.y = -carouselItemImg.height / 2;
carouselItem.addChild( carouselItemImg );
/** --------------------
* carouselItemImgRef
*/
var carouselItemImgRef:DisplayObject = new Bitmap( img.bitmapData );
//carouselItemImgRef.scaleX = 100 / carouselItemImgRef.width;
//carouselItemImgRef.scaleY = 100 / carouselItemImgRef.height;
carouselItemImgRef.scaleY = -1;
carouselItemImgRef.x = -carouselItemImgRef.width / 2;
carouselItemImgRef.y = -carouselItemImgRef.height / 2 + carouselItemImgRef.height * 2 + 2;
carouselItemImgRef.alpha = 0.5;
carouselItemImgRef.cacheAsBitmap = true;
carouselItem.addChild( carouselItemImgRef );
var carouselItemImgRefMask:Sprite = new Sprite();
/*carouselItemImgRefMask.graphics.beginFill( 0x000000 );
carouselItemImgRefMask.graphics.drawRect( 0, 0, carouselItemImgRef.width, carouselItemImgRef.height );
carouselItemImgRefMask.graphics.endFill();
//*/
var matrix:Matrix = new Matrix();
matrix.createGradientBox( carouselItemImgRef.width, carouselItemImgRef.height / 2, Math.PI / 2, carouselItemImg.x, -carouselItemImg.y );
//matrix.createGradientBox( carouselItemImgRef.height, carouselItemImgRef.width, Math.PI / 2 );
carouselItemImgRefMask.graphics.beginGradientFill( GradientType.LINEAR, [ 0x000000, 0xffffff ], [ 1, 0 ], [ 0, 255 ], matrix );
//carouselItemImgRefMask.graphics.beginGradientFill( GradientType.LINEAR, [ 0x000000, 0xffffff ], [ 1, 1 ], [ 0, 255 ] );
carouselItemImgRefMask.graphics.drawRect( carouselItemImg.x, -carouselItemImg.y, carouselItemImgRef.width, carouselItemImgRef.height );
carouselItemImgRefMask.graphics.endFill();
carouselItemImgRefMask.cacheAsBitmap = true;
carouselItem.addChild( carouselItemImgRefMask );
carouselItemImgRef.mask = carouselItemImgRefMask;
/** --------------------
* carouselItem
*/
var angle:Number = 360 * i / ITEM_LENGTH + 180;
carouselItem.x = CAROUSEL_RADIUS * Math.sin( angle * Math.PI / 180 );
carouselItem.z = CAROUSEL_RADIUS * Math.cos( angle * Math.PI / 180 );
carouselItem.addEventListener(MouseEvent.MOUSE_DOWN, carouselItemDown );
carouselItem.addEventListener(MouseEvent.MOUSE_OVER, carouselItemOver );
container.addChild( carouselItem );
carouselItems.push( carouselItem );
carouselItem.graphics.beginFill( 0x000000 );
carouselItem.graphics.drawRect( carouselItemImg.x, carouselItemImg.y, carouselItem.width, carouselItem.height );
carouselItem.graphics.endFill();
//carouselItem.scaleX = 100 / carouselItem.width;
//carouselItem.scaleY = 100 / carouselItem.height;
}
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
}
private function enterFrameHandler( event:Event ):void {
perspectiveProjection.projectionCenter = new Point( stage.stageWidth / 2, stage.stageHeight / 2 - PROJECTION_Y )
//container.rotationY++;
var sortChildIndexArr:Array = new Array();
for ( var i:uint = 0; i < carouselItems.length; i++ ) {
var carouselItem:Sprite = carouselItems[ i ];
//carouselItem.rotationY--;
// this と carouselItem の相対的な位置(+方向)情報を取得
var matrix3D:Matrix3D = carouselItem.transform.getRelativeMatrix3D( this );
sortChildIndexArr.push( { carouselItem:carouselItem, z:matrix3D.position.z } );
}
// 昇順に並び替える
sortChildIndexArr.sortOn( "z", Array.NUMERIC | Array.DESCENDING );
for ( i = 0; i < sortChildIndexArr.length; i++ ) {
carouselItem = sortChildIndexArr[ i ].carouselItem;
container.setChildIndex( carouselItem, i );
}
}
private function carouselItemDown( event:MouseEvent ):void {
var pressedItem:Sprite = event.target as Sprite;
var container:Sprite = pressedItem.parent as Sprite;
/** --------------------
* pv3d 版と同様
*/
var pressedItemPositionDegree:Number = 360 * carouselItems.indexOf( pressedItem ) / carouselItems.length;
var containerRotationY:Number = ( container.rotationY % 360 > 0 ) ? container.rotationY % 360 : container.rotationY % 360 + 360;
var frontItemPositionDegree:Number = 360 - containerRotationY;
var relativeDegreeTemp:Number = pressedItemPositionDegree - frontItemPositionDegree;
var relativeDegree:Number = ( relativeDegreeTemp > 0 ) ? relativeDegreeTemp : 360 + relativeDegreeTemp;
// Math.round は 179.99... 対策
var rotation:Number = container.rotationY - ( ( Math.round( relativeDegree ) < 180 ) ? relativeDegree : -( 360 - relativeDegree ) );
Tweensy.to( container, { rotationY:rotation } );
for ( var i:uint = 0; i < carouselItems.length; i++ ) {
Tweensy.to( carouselItems[ i ], { rotationY:-rotation } );
}
/**
* /pv3d 版と同様
* --------------------
*/
}
private function carouselItemOver( event:MouseEvent ):void {
event.target.buttonMode = true;
}
}
}
/**
* Base64化された画像データを表示可能な形式に変換するクラス
*
* 使い方 :
* function main():void {
* Base64ImageLoader.load(data, complete);
* }
*
* function complete( event:Event ):void {
* var display:DisplayObject = event.target.content as DisplayObject;
* if (display != null)
* addChild(display);
* }
*/
class Base64ImageLoader
{
import flash.display.Loader;
import flash.events.Event;
import flash.utils.ByteArray;
import mx.utils.Base64Decoder;
static public function load( data:String, complete:Function = null ):Loader
{
var byteArray:ByteArray;
var base64Decoder:Base64Decoder;
var loader:Loader;
base64Decoder = new Base64Decoder();
base64Decoder.decode(data);
try {
byteArray = base64Decoder.toByteArray();
byteArray.position = 0;
} catch (e:Error) {
return null;
}
loader = new Loader();
if( complete != null )
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, complete );
loader.loadBytes(byteArray);
return loader;
}
}