AS3.0で3Dのお勉強(Imageを3次元に配置する)
こちらの本でActionScript3.0で3D表現のお勉強中。
ActionScript 3.0による三次元表現ガイドブック
- 作者: 野中文雄
- 出版社/メーカー: 毎日コミュニケーションズ
- 発売日: 2010/06/08
- メディア: 単行本(ソフトカバー)
- 購入: 1人 クリック: 23回
- この商品を含むブログ (5件) を見る
Flash CS4向けの本なので、Flash Builderで同じように動かそうとすると、そのまま動かなかったりしたりしなかったりしますが、「ポイントになるクラス」と「考え方」がわかればFlexアプリケーションとしても実装できます。(今のところ*1は。)
上記本で教えてもらったAdobeが提供するFlash CS4のサンプル(ProjectionDragger、サンプルはデベロッパーセンターからダウンロードできます)を元に、フォルダの下にある画像ファイルを読み込んで3次元空間に配置するコンポーネントを作ってみました。
なお、動作を確認した環境は以下の通り。
以下、ソースコードです。
<?xml version="1.0" encoding="utf-8"?> <s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300" enterFrame="group1_enterFrameHandler(event)" resize="group1_resizeHandler(event)"> <fx:Script> <![CDATA[ import mx.events.FlexEvent; import mx.events.ResizeEvent; import spark.components.Image; private var images:Vector.<Image> = new Vector.<Image>(); /** * フレームのヘッダ位置が更新されたときに呼ばれる。Flexアプリケーションはデフォルトで24fps。 */ protected function group1_enterFrameHandler(event:Event):void { if (this.root != null && this.root.transform != null && this.root.transform.perspectiveProjection != null) { // 消失点を現在のマウスカーソルの位置で更新 var point:Point = new Point(root.mouseX, root.mouseY); this.root.transform.perspectiveProjection.projectionCenter = point; // ↑↑↑ 今回重要なのはココ!!! ↑↑↑ } } protected function textinput1_enterHandler(event:FlexEvent):void { try{ load(new File(textinput.text)); }catch(error:Error){ trace(error.getStackTrace()); } } /** * 「開く」ボタンが押されたときに呼ばれる */ protected function button1_clickHandler(event:MouseEvent):void { var directory:File = File.documentsDirectory; directory.browseForDirectory("画像ファイルが含まれるフォルダを選択"); // ファイル選択イベントのリスナを登録 directory.addEventListener(Event.SELECT, function(event:Event):void{ // イベントのターゲットが選択されたファイルなので、`File`型に変換 var file:File = (event.target as File); textinput.text = file.nativePath; load(new File(textinput.text)); }); } /** * 指定されたディレクトリ下の画像ファイルを読み込む */ private function load(dir:File):void{ if(!dir.isDirectory){ return; } label.text = "画像を読み込み中です..."; for each(var image:Image in images){ this.removeElement(image); } images.splice(0, images.length); dir.addEventListener(FileListEvent.DIRECTORY_LISTING, directoryLlistingComplete); dir.getDirectoryListingAsync(); } /** * DirectoryListingが完了すると呼ばれる */ private function directoryLlistingComplete(event:FileListEvent):void{ var array:Array = event.files; var target:Vector.<File> = new Vector.<File>(); for each(var file:File in array){ var ext:String = file.extension; if(ext == null){ continue; } ext = ext.toLocaleLowerCase(); if(ext == "jpg" || ext == "jpeg" || ext == "png"){ target.push(file); } if(target.length > 100){ break; } } createImages(target); label.text = ""; } /** * 指定された画像ファイル一覧からImageオブジェクトを生成する */ private function createImages(files:Vector.<File>):void{ var numLayers:int = 10; var depthPerLayer:int = 100; for each(var file:File in files){ var i:int = Math.random() * 10; var x:Number = Math.random() * stage.width; var y:Number = Math.random() * stage.height; var z:Number = (numLayers - i) * depthPerLayer; images.push(createImage(x,y,z,file)); } //降順のソート(zが大きい順) images.sort(function(imgA:Image, imgB:Image):int{ //Aが先 if (imgA.z < imgB.z) { return -1; } //Bが先 if (imgA.z > imgB.z) { return 1; } return 0; }); for each(var image:Image in images){ this.addElementAt(image, 0); } } /** * Imageオブジェクトを生成 */ private function createImage(x:Number, y:Number, z:Number, file:File):Image { var image:Image = new Image(); image.x = x; image.y = y; image.z = z; image.source = file.url; return image; } /** * このコンポーネントの大きさが変わった際に、内部のImageオブジェクトの位置を更新する */ protected function group1_resizeHandler(event:ResizeEvent):void { var hRate:Number = this.height / event.oldHeight; var wRate:Number = this.width / event.oldWidth; for each(var image:Image in images){ image.x = image.x * wRate; image.y = image.y * hRate; } } ]]> </fx:Script> <s:TextInput id="textinput" left="10" right="88" bottom="10" enter="textinput1_enterHandler(event)"/> <s:Button right="10" bottom="10" label="開く..." click="button1_clickHandler(event)"/> <s:Label id="label" x="10" y="10"/> </s:Group>
*1:まだ2章しか読み終わってないけどね...