// forked from sandropaula's forked from: 万華鏡 - Kaleidoscope // forked from enok's 万華鏡 - Kaleidoscope // 万華鏡 (KaleidoscopeController) by enok // // 画像はJPG, GIF, PNGに対応してます。サイズは200KBまでです。 // 画像サイズを400~600pxぐらいにするといい感じ。縦横の長さが違うと効果あります。 // // その他詳細はこちら http://linkalink.jp/enok/?p=573 package { import flash.display.Sprite; [SWF(backgroundColor="0x000000", frameRate="24")] public class KaleidoscopeController extends Sprite { public function KaleidoscopeController():void { //背景をしく graphics.beginFill(0x000000); graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight); graphics.endFill(); //万華鏡を配置 var trick:Kaleidoscope = new Kaleidoscope(this); addChild(trick); } } } import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.DisplayObjectContainer; import flash.display.SimpleButton; import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.utils.Timer; //万華鏡本体 class Kaleidoscope extends Sprite { protected var _centerX:Number; //中心X protected var _centerY:Number; //中心Y protected var _imgBmp:Bitmap; //読込画像ビットマップ protected var _sec:Sector; //扇クラス protected var _partsBmpArray:Array; //万華鏡のパーツ配列 protected var _partsAngle:Number = 30; //一つの万華鏡の角度 protected var _ksRadius:Number = 0; //万華鏡の半径 protected var _imgParam:Object = new Object(); //画像のパラメータ配列 protected var _maskBmpData:BitmapData; //扇型マスクのビットマップデータ protected var _fileup:fileUpload; //ファイルアップクラス protected var _viewSp:Sprite; //万華鏡スプライト public function Kaleidoscope(s:DisplayObjectContainer):void { //中点 _centerX = s.stage.stageWidth / 2; _centerY = s.stage.stageHeight / 2; //初期画像の取得 var imgLoader:ImageLoader = new ImageLoader(this, "http://linkalink.jp/enok/wonderfl/kaleidoscope/images/sample/1.jpg"); imgLoader.addEventListener(ImageLoader.LOAD_COMPLETE, init); } //ロード画像の初期化 protected function init(e:Event):void { //画像変数初期化 _imgParam["angle"] = 0.0; _imgParam["scale"] = 1.0; _imgParam["vx"] = 0.0; _imgParam["vec"] = 1; //画像のビットマップ化 var loader:Loader = e.currentTarget.loader; var imgBmpData:BitmapData = new BitmapData(loader.width, loader.height); imgBmpData.draw(loader); _imgBmp = new Bitmap(imgBmpData); //長い方の片を万華鏡の半径にする _ksRadius = Math.min(Math.max(loader.width, loader.height), 420) / 2; //扇型クラス取得 _sec = new Sector(0, 0, _partsAngle, 0, _ksRadius); //扇型マスクのBitmap化 _maskBmpData = new BitmapData(_imgBmp.width, _imgBmp.height, true, 0x00000000); _maskBmpData.draw(_sec); //万華鏡パーツの設置 _viewSp = new Sprite(); _partsBmpArray = new Array() for (var i:uint = 0; i < Math.ceil(360 / _partsAngle); i++ ) { var partsBmp:Bitmap = new Bitmap(); _partsBmpArray.push(partsBmp); _viewSp.addChild(partsBmp); } //追加 addChild(_viewSp); addEventListener( Event.ENTER_FRAME, update ); //ファイルアップ系 _fileup = new fileUpload(this); _fileup.addEventListener(fileUpload.UP_COMPLETE, changeImgLoad); } //繰り返し処理 protected function update(e:Event):void { copyKsParts( createKsParts() ); } //扇型画像作成 protected function createKsParts():BitmapData { //画像ビットマップの変形処理 var mat:Matrix = new Matrix(); mat.translate( -_ksRadius, -_ksRadius); if (_ksRadius - stage.mouseX > 0) { _imgParam["vec"] = 1.0; }else { _imgParam["vec"] = -1.0; } var dist:Number = Math.sqrt(Math.pow(_centerX - stage.mouseX, 2) + Math.pow(_centerY - stage.mouseY, 2)) _imgParam["vx"] = dist / _ksRadius * Math.PI * _imgParam["vec"]; _imgParam["angle"] += _imgParam["vx"] * 0.02; mat.rotate(_imgParam["angle"]); _imgParam["scale"] = Math.min(1 / (dist / _ksRadius), 1.0); mat.scale(_imgParam["scale"], _imgParam["scale"]); //画像ビットマップマップデータ化 var imgBmpData:BitmapData = new BitmapData(_imgBmp.height, _imgBmp.height, true, 0x00000000); imgBmpData.draw(_imgBmp, mat); //画像と扇型マスクを合体 imgBmpData.copyChannel(_maskBmpData, new Rectangle(0, 0, _imgBmp.width, _imgBmp.height), new Point(0, 0), BitmapDataChannel.ALPHA, BitmapDataChannel.ALPHA); //処理後のビットマップマップデータを返す return imgBmpData; } //扇型画像をコピー protected function copyKsParts(imgBmpData:BitmapData):void { for (var i:uint = 0; i < _partsBmpArray.length; i++) { var mat:Matrix = new Matrix(); //配置処理 if (i % 2 != 0) { mat.scale( 1.0, -1.0); mat.rotate(_partsAngle * Math.PI / 180); } mat.rotate((i * _partsAngle - 90) * Math.PI / 180); mat.translate(_centerX, _centerY); //反映 _partsBmpArray[i].transform.matrix = mat; _partsBmpArray[i].bitmapData = imgBmpData; } } //画像変更 protected function changeImgLoad(e:Event):void { //画像ロード var imgLoader:ImageLoader = new ImageLoader(this, "http://linkalink.jp/enok/wonderfl/kaleidoscope/images/users/"+_fileup.name); imgLoader.addEventListener(ImageLoader.LOAD_COMPLETE, changeImg); } //画像変更処理 protected function changeImg(e:Event):void { //画像のビットマップ化 var loader:Loader = e.currentTarget.loader; var imgBmpData:BitmapData = new BitmapData(loader.width, loader.height); imgBmpData.draw(loader); _imgBmp = new Bitmap(imgBmpData); //万華鏡半径算出 _ksRadius = Math.min(Math.max(loader.width, loader.height), 420) / 2; } } //扇型クラス //sketchbook参考にさせて頂きました class Sector extends Sprite { public function Sector(px:Number, py:Number, partsRotate:Number, startAngle:Number, ksRadius:Number):void { var points:Array = getArcPoints(px, py, ksRadius, partsRotate, startAngle, 180); points.unshift( new Point(x, y) ); drawLines(points); } //扇形、円弧と中心点を結んだ形状を算出 private function getArcPoints(x:Number, y:Number, radius:Number, degree:Number, fromDegree:Number=0, split:Number=36):Array{ var points:Array = new Array(); var fromRad:Number = fromDegree * Math.PI / 180; var dr:Number = (degree * Math.PI / 180) / split; for(var i:int=0; i<split + 1; i++){ var pt:Point = new Point(); var rad:Number = fromRad + dr * i; pt.x = Math.cos(rad) * radius + x; pt.y = Math.sin(rad) * radius + y; points.push(pt); } return points; } //扇を描画 public function drawLines(points:Array):void { graphics.lineStyle(1, 0xffffff); graphics.beginFill(0xffffff); graphics.moveTo(points[0].x, points[0].y); for(var i:Number=1; i<points.length; i++){ graphics.lineTo(points[i].x, points[i].y); } } } import flash.events.ProgressEvent; import flash.events.IOErrorEvent; import flash.events.TimerEvent; import flash.display.Loader; import flash.display.LoaderInfo; import flash.system.LoaderContext; import flash.net.URLRequest; //画像ローダーディスパッチャー class ImageLoader extends EventDispatcher { public static const LOAD_COMPLETE:String = "LOAD_COMPLETE"; public static const IOERROR:String = "IOERROR"; protected var _loader:Loader; protected var _sv:statusView; protected var _timer:Timer; public function ImageLoader(s:DisplayObjectContainer , url:String) { //登録 _loader = new Loader(); _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded); _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, error); //セキュリティ var loaderContext:LoaderContext = new LoaderContext(true); //画像ロード開始 var urlReq:URLRequest = new URLRequest(url); _loader.load(urlReq, loaderContext); //ステータス表示 _sv = new statusView(); _sv.view("IMAGE LOAD START"); s.addChild(_sv); s.setChildIndex(_sv, 0); } //画像ロード完了 protected function onLoaded(e:Event):void { _sv.view(""); dispatchEvent(new Event(LOAD_COMPLETE)); } //画像ロード中 protected function onProgress(e:ProgressEvent):void { _sv.view("IMAGE LOADING..."); //var per:Number = Math.round(e.bytesLoaded / e.bytesTotal * 100); } //エラー protected function error(e:IOErrorEvent):void { _sv.view("IMAGE LOAD ERROR"); _timer = new Timer(3000, 1); _timer.addEventListener(TimerEvent.TIMER, onTimer); _timer.start(); dispatchEvent(new Event(IOERROR)); } protected function onTimer(event:TimerEvent):void { _sv.view(""); _timer.removeEventListener(TimerEvent.TIMER, onTimer); } //プロパティ public function get loader():Loader { return _loader;} } import flash.events.EventDispatcher; import flash.events.MouseEvent; import flash.net.FileReference; import flash.net.FileFilter; //ファイルアップディスパッチャ class fileUpload extends EventDispatcher { public static const UP_COMPLETE:String = "UP_COMPLETE"; protected var s:DisplayObjectContainer; protected var fileRef:FileReference;; protected var uploadURL:URLRequest; protected var _sv:statusView; public function fileUpload(ps:DisplayObjectContainer):void { s = ps; //初期化 fileRef = new FileReference(); fileRef.addEventListener(Event.SELECT, onSelect); fileRef.addEventListener(ProgressEvent.PROGRESS , onProgress); fileRef.addEventListener(Event.COMPLETE, onComplete); uploadURL = new URLRequest(); uploadURL.url = "http://linkalink.jp/enok/wonderfl/kaleidoscope/upload.php"; //ボタン設置 var upBtn:customButton = new customButton(s); upBtn.x = 5; upBtn.y = s.stage.stageHeight - upBtn.height - 5; //ステータス表示 _sv = new statusView();; s.addChild(_sv); s.setChildIndex(_sv, 0); //追加 s.addChild(upBtn); upBtn.addEventListener(MouseEvent.MOUSE_DOWN, function(event:Event):void{ var fileFilter:FileFilter = new FileFilter("Images", "*.jpg;*.gif;*.png"); fileRef.browse([fileFilter]);}); } //ファイル選んだ時 protected function onSelect(e:Event):void { var fileRef:FileReference = FileReference(e.target); fileRef.upload(uploadURL); } //アップが完了 protected function onProgress(e:Event):void { _sv.view("FILE UPLOADING..."); } //アップが完了 protected function onComplete(e:Event):void { _sv.view(""); dispatchEvent(new Event(UP_COMPLETE)); } //プロパティ public function get name():String { return fileRef.name; } } import flash.geom.ColorTransform; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFieldAutoSize; //ボタンクラス class customButton extends SimpleButton { private var s:DisplayObjectContainer; public function customButton(ps:DisplayObjectContainer):void { s = ps; //ボタンの色とか設定 var state:Sprite = makeUpstate(); state.transform.colorTransform = new ColorTransform(1, 1, 1, 0.9, 0, 0, 0, 0); downState = upState = state; state = makeUpstate(); state.transform.colorTransform = new ColorTransform(1, 1, 1, 0.8, 0, 0, 0, 0); overState = state; useHandCursor = true; hitTestState = upState; } //ボタン画像作成 protected function makeUpstate():Sprite { var state:Sprite = new Sprite(); var w:Number = 50; var h:Number = 10; var margin:Number = 2; //枠系 state.graphics.lineStyle(1, 0xffffff); state.graphics.drawRect(0, 0, w + margin * 2, h + margin * 2); state.graphics.endFill(); state.graphics.beginFill(0xffffff); state.graphics.drawRect(margin, margin, w, h); state.graphics.endFill(); //テキスト系 var txtFormat:TextFormat = new TextFormat(); txtFormat.font = "_sans"; txtFormat.size = 10; txtFormat.color = 0xcc2222; txtFormat.bold = true; var txtField:TextField = new TextField(); txtField.defaultTextFormat = txtFormat; txtField.text = "CHANGE"; txtField.autoSize = TextFieldAutoSize.LEFT; txtField.x = 4; txtField.y = -1; state.addChild(txtField); return state; } } class statusView extends Sprite { protected var _txtField:TextField; public function statusView():void { //テキスト系 var txtFormat:TextFormat = new TextFormat(); txtFormat.font = "_sans"; txtFormat.size = 10; txtFormat.color = 0xeeeeee; //txtFormat.bold = true; _txtField = new TextField(); _txtField.defaultTextFormat = txtFormat; _txtField.text = ""; _txtField.autoSize = TextFieldAutoSize.LEFT; _txtField.x = 0; _txtField.y = 0; addChild(_txtField); } public function view(mess:String):void { _txtField.text = mess; } } forked from: forked from: 万華鏡 - Kaleidoscope