Actionscript3.02011.05.01 16:29


 ApplicationDomain 에 대한 개념만 잘 이해 하고 있다면, 이 포스팅은 보지 않으셔도 됩니다. 최근까지 ApplicationDomain 에 대한 개념 자체를 다르게 이해 하고 있어서 어렵다고 생각했던 부분들은 정리 합니다.


 Flash/Flex 를 사용하면서 가장 많이 사용하는 클래스중 하나는 Loader 일 것 입니다. Loader 클래스는 SWF 나, 이미지 (JPG, PNG 등등) 을 로드 하는데 사용 합니다. 많은 분들이 이미지를 로드 하는데 자주 사용하고 있을거라 생각 합니다. 외부에서 이미지를 로드 하면 로드된 리소스는 Bitmap 으로 처리가 되어 BitmapData 의 clone 메소드를 통해서 해당 이미지를 재사용 할 수 있습니다. 코드는 아래와 같습니다.


 // 이미지 로드

package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest; public class ApplicationDomainTest extends Sprite { public function ApplicationDomainTest() { var loader:Loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler); loader.load(new URLRequest("TestAsset.png")); } private function loadCompleteHandler(event:Event):void { var image:Bitmap = event.target.content as Bitmap; var imageData:BitmapData = image.bitmapData.clone(); trace(imageData); } } }



이미지는 위와 같이 재사용하면 되고, 이미지가 아닌 SWF 파일은 어떻게 재사용 할까요? 제가 사용한 방법은 ApplicationDomain 을 이용한 것 입니다. ApplicationDoamin 에 대한 자세한 내용은 다음 블로그에 잘 정리 되어 있으니 참고해 주세요.


Flex 모듈 프로그래밍의 기초 - Application domain의 이해

http://blog.jidolstar.com/469

http://blog.jidolstar.com/346 


 Loader 를 통해 외부 리소스를 로드 하면 해당 리소스는 load 메소드의 LoaderContext 의 ApplicationDomain 설정에 따라 새로운 ApplicationDoamin 또는 로드를 객체의 ApplicationDoamin 에 정의가 저장 됩니다.


 load(request:URLRequest, context:LoaderContext = null):void


LoaderContext 에서 applicationDoamin 값을 (new ApplicationDoamin, ApplicationDomain.currentDoamin 등) 어떤 값으로 설정하는가에 상관 없이 로드된 외부 리소스는 자신의 ApplicationDomain 을 알 수 있습니다. 


 // 로드된 리소스 ApplicationDomain 알기

package {    

    import flash.display.Loader;    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;        

    public class ApplicationDomainTest extends Sprite {        

        public function ApplicationDomainTest()    {

            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
            loader.load(new URLRequest("TestAsset.swf"));    
        }

        private function loadCompleteHandler(event:Event):void {

            var swf:* = event.target.content;

            trace(swf.loaderInfo.applicationDomain);
        }
    }
}


이 ApplicationDomain 에는 로드된 자기 자신의 정의 들을 가지고 있기 때문에 해당 정의(클래스)를 불러와서 사용 할 수 있습니다. 예를 들어 아래와 같이 작성 되어 있는 외부 SWF 를 로드 한다고 하면 각각의 객체 정의 들은 불러 오는 방법은 다음과 같습니다. 


// TestAsset

package { import com.ddongkang.AssetLoader; import com.ddongkang.Circle; import com.ddongkang.List; import flash.display.Sprite; public class TestAsset extends Sprite { private var loader:AssetLoader; private var circle:Circle; private var list:List; public function TestAsset(){ }

} 


 // Main

package {    

    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;

    public class ApplicationDomainTest extends Sprite {
        

        public function ApplicationDomainTest()    {

            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
            loader.load(new URLRequest("TestAsset.swf"));    

        }

        private function loadCompleteHandler(event:Event):void {
            var swf:* = event.target.content;
            trace(ApplicationDomain(swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.AssetLoader"));
            trace(ApplicationDomain(swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.Circle"));

            trace(ApplicationDomain(swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.List"));

        }

    }

}



getDefinition 으로 불러온 정의는 클래스 정의 이기 때문에 객체를 생성 할 수 있습니다. 


// 외부에서 로드한 Circle 객체 생성

var circle:* = new ((swf.loaderInfo.applicationDomain).getDefinition("com.ddongkang.Circle"))();
addChild(circle);            
trace(circle); 


로드된 TestAsset.swf 는 AssetLoader, Circle, List 정의를 가지고 있기 때문에 컴파일 될때 해당 정의도 SWF 에 포함됩니다. 로드한 클래스는 TestAsset 이지만, TestAsset 이 가지고 있는 정의들이 같은 ApplicationDomain 안에 포함되어 있기때문에 이러한 접근이 가능 합니다. 여기서 SWF 자체인 TestAsset.swf 도 다음 코드를 통해 접근 가능 합니다.


// TestAsset 접근 

var asset:* = new ((swf.loaderInfo.applicationDomain).getDefinition("TestAsset"))(); 


주의할 점은 getDefinition 에 사용한 이름이 package 까지 포함된 이름이라는 점 입니다. getDefinition 을 통해 해당 클래스 정의에 접근 할때는 해당 정의가 ApplicationDomain 에 존재 하지 않을수도 있기 때문에 hasDefinition 를 통해 있는지 확인 후 접근해야 런타임 에러를 방지 할 수 있습니다.


// hasDefinition 사용


 private function createAssetByName(loaderInfo:LoaderInfo, name:String):* {

            
     var applicationDomain:ApplicationDomain = loaderInfo.applicationDomain;
     if(applicationDomain.hasDefinition(name)) {
          return new (applicationDomain.getDefinition(name))();                
     }
            
     return null;
            
}


로드할 자원을 만들때, Flash Builder/ Flex Builder 를 사용할 경우 컴파일 된 자원 이름 (위의 경우에는 TestAsset.swf)이 클래스 이름(TestAsset)과 동일 하기 때문에 외부 리소스가 단일 자원으로 컴파일 될 때는 swf 이름으로 클래스를 접근해도 무방 합니다. 해당 swf 이름을 이용하여 Dictionary 를 만들어서 정의를 저장해 놓고 사용할 수도 있습니다. (http://mrdoob.com/blog/post/612


 하지만 Flash IDE 로 외부 리소스를 만들때는 반드시 Document 클래스를 지정하고 지정된 Document 클래스 이름을 통해 클래스를 접근해야 합니다. Flash/Flex Builder 에서 만든 리소스는 swf 자체가 클래스가 되지만 Flash IDE 에서는 Document 클래스로 연결이 안되어 있는 swf는 swf 자체가 클래스가 아니기 때문에(?) 정의를 불러 올 수 없습니다. 그러나Flash IDE 를 통해 Linkage 를 이용하여 클래스를 정의한 경우에는 Builder 에서 만들때와 마찬가지로 컴파일된 SWF 에 Linkage 를 통해 클래스화 된 객체 정보들을 가지고 있기 때문에 접근이 가능 합니다.  정리해 보면 다음과 같습니다.


로드할 자원 만들 때 주의 사항

1. 클래스 이름을 package 까지 포함하여 알고 있어야 한다.

2. Flash IDE 로 자원을 만들때는 Document 클래스를 연결해 주고 Document 클래스의 이름을 알아야 한다.

3. Flash IDE 의 라이브러리 Linkage 를 사용하여 클래스를 만들면 컴파일된 swf 에서 해당 정의를 불러올 수 있다. ( http://goo.gl/xrY8q ) 


로드한 자원 (클래스) 를 재사용하기 위해서는 로드된 클래스 이름을 알아야 한다는게 핵심입니다. 그 클래스정의는 로드된 swf 의 ApplicationDomain 안에서 있고 해당 클래스 이름을 통해서 가져 올 수 있습니다. 그리고 그 정의를 통해 new 를 통해 객체를 생성하여 사용 합니다.


잘못된 내용이나 개발 중 고민하고 있는 부분들은 댓글을 통해 공유 주세요~ 






Posted by Flash 동강
Actionscript3.02010.06.13 20:43

Actionscript 3.0 의 Event Model 은 이벤트를 dispatch 하는 방식으로 이루어져 있습니다. 많은 클래스들이 클래스 내부적으로 "어떠한 행동"에 대해 이벤트를 외부로 알려주는 방식을 사용하고 있습니다. 예를 들어 Loader 클래스를 사용할때, 이미지나 파일들을 로드한 후에 Loader 클래스 내부적으로 이벤트 dispatch 가 일어나서 사용자나 개발자는 그 상황에 따른 후 처리를 할 수 있습니다.


import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;

var ld:Loader = new Loader();
ld.addEventListener(Event.COMPLETE, hnLoaded);

function hnLoaded( e:Event ):void{   
	// 로드끝
}

// Loader 내부
public class Loader extends EventDispatcher{
	public function Loader(){}
	private function loaded(){
		dispatchEvent(new Event(Event.COMPLETE));
	}
}

개발자들은 addEventListener 를 이용하여 내부적으로 dispatchEvent 되는걸 청취(addEventListener) 하고 있다가 반응이 오면 다운로드 된 데이터에 접근 가능 하게 됩니다. 이렇게 대부분의 AS3 이벤트 모델은 dispatch event 에 근거 하고 있습니다.


저도 AS3을 공부하고 초기에는 dispatchEvent 의 개념에 익숙하지 않아, 바보 같은 짓을 하곤 했는데요. 예를 들어 Event.ENTER_FRAME 으로 이벤트가 끝날때 까지 기다린다던지, Timer 를 이용하여 비슷한 방법을 사용하곤 했습니다. 

var ld:Loader = new Loader();
ld.addEventListener(Event.ENTER_FRAME, hnLoaded);

function hnLoaded( e:Event ):void{    
   // 로드끝
   if(ld.content) {

        // null 이 아니면 로드끝이라 판단
	ld.removeEventListener(Event.ENTER_FRAME, hnLoaded);
	
        // 로드후 후처리 로직 구현    
   } 
}



dispatch Event 는 그 밖에도 클래스의 재사용성에 대한 강점을 가지고 있습니다. 내부적으로 dispatch 되는 이벤트(행동)들을 addEventListener를 이용하여 청취하기만 하기 때문에 객체 유연성이 높습니다. 그 밖에도 여러 장점이 있지만, 자랑은 여기까지 하겠습니다.



dispatchEvent를 사용하지 않고 대안으로 사용할 수 있는 방법이 해당 행동에 대한 callback 메소드를 이용하는 것 입니다. Adobe에서 제공한 flashplatform optimizing content 문서를 보면 플래시 콘텐츠 최적화 방법중에 이벤트 구현을 dispatchEvent를 사용하기 보단 callback 을 사용하는게 더 효율적이라고 하고 있습니다. 이유는 여러가지가 있겠지만, 제가 생각하는 걸 나열해 보면 다음과 같습니다.


  • dispatchEvent 가 일어났다는걸 알기 위해서 addEventLister 를 등록해야 한다.
  • 너무 많은 addEventListener 사용은 메모리나 퍼포먼스에 영향을 줄수 있다.
  • 너무 많은 addEventListener 사용 코드를 지져분 하게 한다. (개인적 취향입니다.)

그래서 그 문서에서는 dispatchEvent 를 사용하지 말고 callback 메소드를 전달하여 이벤트 후처리를 수행하는게 퍼포먼스에 이점이 있다고 말하고 있습니다. 아래와 같은 방식으로요.


var ld:LoaderCallback = new LoaderCallback(hnLoaded);

public class LoaderCallback extends EventDispatcher{
	private var _callback:Function;   
	private var _ld:Loader;    
	
	public function LoaderCallback() {
		_ld = new Loader();
		_ld.addEventListener(Event.COMPLETE, loaded);
	}    
	public function load(url:String,callback:Function):void {
		_callback = callback;       
		_ld.load(new URLRequest(url));
	}    
	private function loaded(e:Event) {
		callback(e);
	}
}


callback 메소드를 로드를 수행하는 LoaderCallback의 load 메소드에 파라미터로 넘기기 때문에 따로 addEventListener를 등록할 필요도 없고 이벤트 관리를 효율적으로 할 수 있습니다.


프로젝트를 하면서 고민했던 부분이 바로 이 부분이었는데요. 퍼포먼스를 생각하면 (그밖에도 여러이점이 있겠지만) callback 을 사용해야 하지만, dispatchEvent 를 이용하면 나중에 API 로 변경 했을때 추가 작업없이 바로 사용 할 수 있다는 장점 때문에 두가지 선택 사항에서 고민을 많이 하였습니다. 그래서 내린 결론은 addEventLister 등록을 최소한으로 하고 API 로서 기능을 수행할 가능성이 적은 클래스는 callback 를 사용하고 API 의 기능을 수행해야 하는 객체에는 dispatchEvent 를 사용하였습니다. dispatchEvent 도 일일히 각각의 이벤트를 등록하여 청취하는 방법이 아니라, 하나의 이벤트를 수신하여 커스텀 이벤트에 있는 type 으로 이벤트 유형을 판단 하도록 하였습니다.


아래와 같은 방법은 3번의 addEventListener를 해야 되지만


stream.addEventListener(StreamEvent.PLAY,hnStreamPlay);
stream.addEventListener(StreamEvent.STOP,hnStreamStop);
stream.addEventListener(StreamEvent.PAUSE,hnStreamPause);

public class Stream extends EventDispatcher{ 
	public function Stream(){}
        public function play():void { 
		dispatchEvent(new StreamEvent(StreamEvent.PLAY));
	}  
	public function stop():void {
		dispatchEvent(new StreamEvent(StreamEvent.STOP));
	}
	public function pause():void {
		dispatchEvent(new StreamEvent(StreamEvent.PAUSE));
	}
}

function hnStreamPlay( e:StreamEvent ):void{}
function hnStreamStop( e:StreamEvent ):void{}
function hnStreamPause( e:StreamEvent ):void{}


아래 방법은 한개의 등록만으로 처리가 가능 합니다.

stream.addEventListener(StreamEvent.ECHO,hnStreamEcho);

public class Stream extends EventDispatcher{ 
	public function Stream(){}       
	public function play():void {
		dispatchEvent(new StreamEvent(StreamEvent.ECHO,StreamEvent.PLAY));
	}
	public function stop():void {
		dispatchEvent(new StreamEvent(StreamEvent.ECHO,StreamEvent.STOP));
	}
	public function pause():void{
		dispatchEvent(new StreamEvent(StreamEvent.ECHO,StreamEvent.PAUSE));
	}
}
function hnStreamEcho( e:StreamEvent ):void{ 
	// StreamEvent 에 label 을 구현함    
	if(e.label == StreamEvent.PLAY){} 
	else if(e.label == StreamEvent.STOP){}
	else if(e.label == StreamEvent.PAUSE){}
}


개인적으로 두번째 방법을 더 선호 하는데요. 그때 그때 상황에 따라 선택이 중요한것 같습니다.


Flashplatform 개발 작업이 다른 언어에 비해 이벤트를 관리해야 되는 상황이 많은데요. 사용하기 편한것도 좋지만, 메모리나 퍼포먼스, 코드 가독성을 생각하여 판단하는 능력이 필요 하다는 생각이 드네요.


posted by dongkang




Posted by Flash 동강
Actionscript3.02008.12.11 11:31

플래시를 시작 하고 나서 처음으로 만들어 보고 싶은 것을 꼽으라면 내 사진첩 이라는 말을 제일 많이 들어보았습니다. 

저 또한 플래시를 접하게 되고 처음으로 "내가 만든 것" 이라고 사람들에게 보여 준것도 사진첩이었습니다. 사진첩이라는 말이 거창하게 들릴지 모르겠지만, 사진첩이난 MP3 플레이어를 만들때 핵심이라 할수 있는 Loader Class 에 대해 끄적여 볼까 합니다.

Loader

Loader DisplayObjectContainer InteractiveObject DisplayObject EventDispatcher Object

Loader 클래스는 SWF 파일이나 이미지(JPG, PNG 또는 GIF) 파일을 로드하는 데 사용됩니다. load() 메서드를 사용하여 로드를 시작합니다. 로드된 표시 객체는 Loader 객체의 자식으로 추가됩니다.

텍스트 또는 이진 데이터를 로드하려면 URLLoader 클래스를 사용합니다. Loader 객체는 자식 표시 객체(Loader 객체가 로드하는 표시 객체)를 하나만 가질 수 있기 때문에 Loader 클래스는 자신이 상속하는 다음 메서드를 무시합니다. 따라서 addChild(), addChildAt(), removeChild(), removeChildAt()setChildIndex() 메서드를 호출하면 예외가 발생합니다. 로드된 표시 객체를 제거하려면 해당 부모 DisplayObjectContainer 자식 배열에서 Loader 객체를 제거해야 합니다.

레퍼런스에 적혀 있는 말이 어렵게만 느껴지는 군요;;  위의 말대로 Loader 는 파일을 로드 하기 위해 사용 됩니다.   

var testloader:Loader = new Loader();
testloader.load(new URLRequest("image.jpg");
addChild(testloader);   

로더 클래스에서 경로를 설정해 주기 위해서는 URLRequest 라는 클래스를 사용하게 되는데 URLRequest 클래스는 하나의 HTTP 요청에 포함된 모든 정보를 캡처합니다.

 

가장 기본이 되는 뼈대 입니다. 그렇다면 Loader 는 불러 오기만 하면 그 기능을 다 하는 것인가? Loader Class 에서는 그 해당 로더로 불러와 지는 데이터의 접근 기능을 가지고 있습니다. 이 기능으로 인해 예를 들어 사진을 로드 한다면 width 값이나 height 값을 바꿀수 있는 것이지요.  


testloader.contentLoaderInfo.addEventListener(Event.COMPLETE, fComplete);
function fComplete(ev:Event):void
{
    var mObject:DisplayObject = ev.target.content;
    mObject.width=100;
    mObject.height=100;

}


// ev.target.content 로 해당 로더로 불러와 지는 데이터에 대한 접근을 할수 있습니다. 그 후에 width 값과 height 를 바꿔주는 것이지요. 위의 예는 이미지 로드 뿐만 아니라 xml 로드 swf 로드 때에도 동일하게 적용이 됩니다.  


function  fComplete(ev:Event){
   var loader:URLLoader=URLLoader(ev.target);             
// URLLoader 에 대한 내용은 레퍼런스를 참고하세요

   var dataXML=new XML(loader.data);
   trace(dataXML);
  
  }

 LoaderEvent 에서는 load 가 끝났을때의 이벤트 뿐만 아니라 로드가 진행 될때의 이벤트도 제공 하고 있습니다.  


testloader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, fProcess);
function fProcess(ev:ProgressEvent):void
{
    var mPercent:Number =int( e.bytesLoaded/e.bytesTotal*100.0);
    trace(mPercent);
}

 위의 기능으로 이미지 로드시 로딩바를 만들수 있게 되는 것입니다. ( progressEvent 가 진행되고 있을때는 로딩 무비 클립을 addChild 해 주고 끝나면 그 무비 클립을 제거 해 주는 방식으로)  

이러한 이벤트들로 이미지를 불러오고 불러온 이미지를 조작하고 interaction 을 추가 하여 기본적인 겔러리를 구현할수 있습니다. 이 로드하는 방식을 간단하게 쓸수 있게 만들어 놓은 Class 를 소개 합니다.

( 새롭게 시작하는 Actionscript 3.0 -윤훈남 의 예제 소스 ) - 문제가 생기면 삭제 하겠습니다.  

 

  1. package {
  2.  
  3.  import flash.display.Loader;
  4.  import flash.display.DisplayObjectContainer;
  5.  import flash.events.ProgressEvent;
  6.  import flash.events.Event;
  7.  import flash.net.URLRequest;
  8.  import flash.display.DisplayObject;
  9.  
  10.  public class CLoaderUI extends CLoadAni {
  11.   var pLoader:Loader = new Loader();
  12.   var pRequest:URLRequest = new URLRequest();
  13.   var pContainer:DisplayObjectContainer;
  14.  
  15.  
  16.   var pWidth:Number,pHeight:Number;
  17.   var pX:Number,pY:Number;
  18.  
  19.   function CLoaderUI(mStage:DisplayObjectContainer,mURL:String,mWidth:Number,mHeight:Number,mX:Number=0, mY:Number=0):void {
  20.    pContainer = mStage;                      // mStage 는 어느 객체에 load 를 할지를 지정할수 있게 해 준다.
  21.    pX=mX;                                         // 위치 지정
  22.    pY=mY;                                          // 크기 지정
  23.    pWidth=mWidth;
  24.    pHeight=mHeight;  
  25.          
  26.    pRequest.url =mURL;                       // 해당 이미지 경로 지정
  27.    if(pRequest.url != "")
  28.     pLoader.load(pRequest);
  29.    else
  30.     pLoader.load(new URLRequest("noImage.jpg"));          // 이미지가 없을때는 정해진 이미지 로드
  31.    
  32.    pLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, fProcess);       // 진행중
  33.             pLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, fComplete)           // 완료
  34.    
  35.  }
  36.      function fProcess(e:ProgressEvent):void {
  37.      var mPercent:Number =int( e.bytesLoaded/e.bytesTotal*100.0);
  38.  
  39.      trace(mPercent);
  40.   }
  41.  
  42.   function fComplete(e:Event):void
  43.   {  
  44.     var mObject:DisplayObject = e.target.content;        //load 된 내용을 불러 와서
  45.     mObject.width=pWidth;                                       // 조작한다.
  46.     mObject.height=pHeight;
  47.     mObject.x=pX;
  48.     mObject.y=pY;
  49.     pContainer.addChild(mObject);
  50.     pContainer.removeChild(this);                  // 해제 시켜 준다.
  51.     pLoader =null;
  52.     pContainer=null;
  53.     pRequest=null;
  54.   }
  55.  }
  56. }

 위의 클래스를 사용하면 로드시에 겪는 불편을 조금 덜어 줍니다. 처음 사진첩 만들때 이미지 크기 조작을 어떻게 해야 할지 몰라 고생했던거 생각을 하면서 썼습니다.
조금이라도 도움이 되셨다면 좋겠네요.

Posted by Flash 동강
동강의AS3.0 강좌2008.12.11 01:36

요즘엔 구글링을 하면서, 이 사이트 저 사이트 많이 돌아 다니고 있는데, 정말 세상을 넓고, 대단한 사람들은 많다 라고 세삼 느껴지네요.  

월요일 입니다. 다들 피곤하시져?? 주말에도 일하신 분들도 있으실테고, 주말 동안 푹 쉬신 분들도 있을 겁니다.  월요일이고, 새롭게 시작하는 느낌으로 일주일을 시작하는것도 좋을듯 싶습니다.  

이번에 볼 내용은 Timer class 와 Loader class 입니다. 두 클래스 모두 강력한 기능으로 작업의 능률을 높여 주는 그런 클래스들 입니다. 우선 Timer class 부터 레퍼런스를 살펴 봅시다.  

 Timer 

클래스  public class Timer
상속 Timer  EventDispatcher  Object

언어 버전 :  ActionScript 3.0
Player 버전 :  Flash Player 9

 

 
  Timer(delay:Number, repeatCount:int = 0)
  지정된 지연 및 반복 횟수 상태를 사용하여 새 Timer 객체를 만듭니다.  
 
  1. var time:Timer = new Timer(1000,5);
  2. time.start();

  delay 시간은 ms 단위로 합니다. 1000 = 1초가 되는 거지요. repeatCount 는 이 timer을 몇번 반복해서 실행 시키겠는가?

  위에서는 5번 실행 시키고 실행을 중단하게 됩니다.

 꼭 start() 를 해줘야 시작이 되고, 멈추는건 stop(); 으로 멈출수 있습니다. 그러면 저거 두개만 으로 어떻게 Timer 를 활용하는가? 보통 TimerEvent 라는 Timer 가 가지고 있는 기본 이벤트와 함께 사용됩니다.

 

 
  1. package{
  2.        
  3.         import flash.display.Sprite;                  
  4.         import flash.events.TimerEvent;                // 기본 import
  5.         import flash.utils.Timer;
  6.        
  7.         public class TimerExample extends Sprite
  8.         {
  9.                 private var time:Timer;                   // 객체 정의
  10.                
  11.                 public function TimerExample():void
  12.                 {
  13.                         time = new Timer(1000,5);
  14.                         time.start();
  15.                         time.addEventListener(TimerEvent.TIMER,ontimerhandler);
  16.                         time.addEventListener(TimerEvent.TIMER_COMPLETE,onCompletehandler);
  17.                
  18.                 }
  19.                 private function ontimerhandler(event:TimerEvent):void
  20.                 {
  21.                         trace("1초");
  22.                        
  23.                 }
  24.                 private function onCompletehandler(event:TimerEvent):void
  25.                 {
  26.                         trace("타임 끝");
  27.                 }
  28.                
  29.         }
  30. }

 

time.addEventListener(TimerEvent.TIMER,ontimerhandler);
1초 마다 실행되는 함수를 정의합니다. 지정한 시간에 호출되는 함수를 정의(이벤트를 생성시켜줌)

time.addEventListener(TimerEvent.TIMER_COMPLETE,onCompletehandler);
time 이 모두 실행 된 후에 실행되는 함수를 지정 (이벤트를 생성시켜줌)

//output

1초
1초
1초
1초
1초
타임 끝

우리가 쓰고 있는 enterframe 이 fps 단위로 실행되는 반면, Timer 는 초 단위로 실행 됩니다. Timer 가 enterframe 에 비해서 정확할수 있다고 말하는것도 여기에 있는듯 합니다. 다른 속성도 있으나 잘 쓰이지 않으므로 레퍼런스를 한번 보시는것도 좋을듯  싶습니다.

 

 Loader

 

 
  클래스 public class Loader
  상속 Loader  DisplayObjectContainer InteractiveObject  DisplayObject  EventDispatcher  Object

 

 
 Loader()
 SWF, JPEG, GIF 또는 PNG 파일 등을 로드하는 데 사용할 수 있는 Loader 객체를 만듭니다.
 
 
  1. var ld:Loader = new Loader();
  2. ld.load(new URLRequest("image.jpg"));

 ld 라는 로더를 만들어서 URLRequest 로 정의된 주소값의 jpg나 gif png swf 파일을 로드 합니다.

 

참고 ) URLRequest

URLRequest 클래스는 하나의 HTTP 요청에 포함된 모든 정보를 캡처합니다.

말이 어려워지므로, 걍 주소를 정의하기 위해서는 URLRequest 타입으로 해야 된다는것만 알아 주세요

(2.0 과의 차이점입니다. )

 

 

 
  1. package{
  2.        
  3.         import flash.display.Sprite;
  4.         import flash.display.Loader;
  5.         import flash.events.*;
  6.         import flash.net.URLRequest;
  7.         import flash.display.DisplayObject;
  8.  
  9.         public class LoaderExample extends Sprite{
  10.                
  11.                 private var ld:Loader;
  12.                
  13.                 public function LoaderExample():void
  14.                 {
  15.                         ld = new Loader();
  16.                         var url:URLRequest = new URLRequest("image.jpg");
  17.                         ld.load(url);
  18.                         ld.contentLoaderInfo.addEventListener(Event.COMPLETE, completehandler);
  19.                         ld.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progresshandler);
  20.                        
  21.                         addChild(ld);                  
  22.                 }
  23.                 private function completehandler(event:Event):void
  24.                 {
  25.                          var mObject:DisplayObject = event.target.content;
  26.                          mObject.width=100;
  27.                          mObject.height=100;
  28.                        
  29.                 }
  30.                 private function progresshandler(event:ProgressEvent):void
  31.                 {
  32.                         var mPercent:Number =int( event.bytesLoaded/event.bytesTotal*100.0);
  33.  
  34.                         trace(mPercent);
  35.                 }
  36.                
  37.         }
  38.        
  39. }

 

같은 폴더에 image.jpg 라는 파일이 있어야 로드가 됩니다. 없으면 URL 에러를 일으킴니다.

 

//output

로드중
로드중
로드중
로드중
로드끝

 

여기서 contentLoaderInfo 는 뭔가?

  contentLoaderInfo : LoaderInfo
[read-only] 로드 중인 객체에 해당하는 LoaderInfo 객체를 반환합니다.
 

LoaderInfo 란 Loader 에 의해 불러와지는 데이터의 정보 입니다. 예를 들면 jpg 이미지라면 크기 (width, height 가 있겠지요?)

Loader 는 이러한 LoaderInfo 를 참조하여 그 값들을 변경할수 있습니다. 어쩌피 이미지가 swf 파일이 로드 되는 것도 bitmapdata 를 거쳐서 들어 오는것이기 때문에 변환이 가능합니다. ( 하지만 크로스 브라우징 문제가 발생할수도 있습니다 )

 

  1.  
  2. package{
  3.        
  4.         import flash.display.Sprite;
  5.         import flash.display.Loader;
  6.           import flash.display.DisplayObject;
  7.         import flash.events.*;
  8.     import flash.net.URLRequest;
  9.  
  10.         public class LoaderExample extends Sprite{
  11.                
  12.                 private var ld:Loader;
  13.                
  14.                 public function LoaderExample():void
  15.                 {
  16.                         ld = new Loader();
  17.                         var url:URLRequest = new URLRequest("image.jpg");
  18.                         ld.load(url);
  19.                         ld.contentLoaderInfo.addEventListener(Event.COMPLETE, completehandler);
  20.                         ld.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progresshandler);
  21.                        
  22.                         addChild(ld);                  
  23.                 }
  24.                 private function completehandler(event:Event):void
  25.                 {
  26.                          var mObject:DisplayObject = event.target.content;
  27.                          mObject.width=100;
  28.                          mObject.height=100;              // 로드된 이미지는 100 / 100 으로 사이즈 변경
  29.                        
  30.  
  31.                 }
  32.                 private function progresshandler(event:ProgressEvent):void
  33.                 {
  34.                         var mPercent:Number =int( event.bytesLoaded/event.bytesTotal*100.0);
  35.  
  36.                         trace(mPercent);                // 로드 되는 과정을 알수 있다.
  37.                 }
  38.  
  39.                
  40.         }
  41.        
  42. }

 

위의 completehandler 함수에서는 event.target.content 로 정보를 받은 뒤 변경을 해 주게 되고 progresshandler 에서는 byteLoaded 를 이용해서 실시간 로드된 값을 알수 있습니다. 이것을 이용해서 로딩 바를 만들수 있습니다.  앞으로 만들어 볼것의 기본이 되는 두 클래스를 설명해 보았습니다. 잘 이해 안되는 부분은 질문 날려 주시고요 . 잘못된 부분이나 추가 내용은 댓글이나 답글 달아 주세요. 이 공간의 저 만의 강좌 공간이 아니라, 강좌라는 주제에 대해 토의하는 공간입니다. 쑥스러워 하지 마시고, 참여 부탁드립니다. 그럼 두 클래스를 이용한 간단한 해보기 입니다.  

1. 5장의 이미지를 준비

2. 배열에 5장의 이미지를 저장

3. Timer class 를 이용해 2초에 한번씩 로드 되는 겔러리를 만든다.   

겔러리를 만들면서 Ctrl + Alt + del 을 눌러 메모리가 늘어 나는 상황을 관찰해 봅시다! 기초 스터디 팀에게는 미리 낸 해보기라, 미리 올라온 소스를 참고해 보시는것도 좋을듯 합니다. 다하신 분들은 꼭 메모리가 늘어 나는 상황을 관찰해 보시기 바람니다.   

수고 하셨습니다. 기분좋은 한주 시작 하세요!

 

Posted by Flash 동강