ADOBE/ ActionScript

액션스크립트 actionscript 플래시 swf를 여러개를 로드 할때 문제점 해결 관련(adobe 개발 데스크톱, 모바일[ios, android등등])

AlrepondTech 2020. 9. 22. 04:51
반응형

 

 

=================================

=================================

=================================

 

 

 

-----------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------

--방법 하나

private function test():void

{

var time:Date = new Date();

 var loadUrl:String = "app:/movies/"+_lecNum+".swf"+"?nf=" + time.getTime();

 			

 _urlRequest = new URLRequest(loadUrl);

  _loader = new Loader();



  _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, fProgress);

  _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,         completeHandler);

   _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,  errorHandler);

   _lcontext = new LoaderContext(false,null, null); //가운데값 ApplicationDomain.currentDomain 을쓰지않고 null 로 써준다.



			try

			{

				_loader.load(_urlRequest, _lcontext);

			}

			catch(e:Error)

			{

				trace(e.message);

			}

}


		private function completeHandler(e:Event):void
		{

			_displayObj = e.target.content;
                        this.addChild( _displayObj );

		}

-----------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------

--방법 하나

액션스크립트 여러가지의 인터렉티브가 들어간 swf를 여러번 로드 할때 제대로 로드가

되지 않고 프레임이 멈추거나 꼬이는 현상이 일어납니다. 

그런 부분을 해결하고자 이글을 쓰니다.

일단 swf의 모든 동작과 동일한것은 같은 fla에 심볼 하나에 담아

 아래와 같이 이름과 클래스와 같이 만듭니다.

 

 

 

위와같이 한뒤 액션스크립트 코드는 

 

// 몇몇 변수 선언 부분은 생략 합니다 보지않아도 아실거라 믿습니다~!

//처음 로드부분

 var time:Date = new Date();

 var loadUrl:String = "app:/movies/"+_lecNum+".swf"+"?nf=" + time.getTime();

 

 _urlRequest = new URLRequest(loadUrl);

  _loader = new Loader();

 

  _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, fProgress);

  _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,         completeHandler);

   _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,  errorHandler);

   _lcontext = new LoaderContext(false, ApplicationDomain.currentDomain, null);

 

try

{

_loader.load(_urlRequest, _lcontext);

}

catch(e:Error)

{

trace(e.message);

}

 

//------------------------------------------------------

// completeHandler 로드가 완료된부분

 

var swf:* = e.target.content;

swf.soundTransform = new SoundTransform(0.0);

swf.gotoAndStop(1);

 

var mvClass:Class = ((swf.loaderInfo.applicationDomain).getDefinition("g"+번호)) as Class; //번호부분은 1_1_1이나 1_1_2.등등

_displayObj = new mvClass();

 

        this.addChild(_displayObj);

 

- 여기서 swf를 부를때 swf부분에 스크립트 부분이 들어가고 Event.ENTER_FRAME 들어간 코드나 stage 를 관련한 코드는 주의해야 합니다.

  new class 할때 초기화 될때 초반에 에러가 날수 있습니다 예로들어 위에 부분은 "_displayObj = new mvClass();" 쪽에서 stage 가 초반에

  잠시 null로 되기 때문에 초기화때에 stage관련 부분이 에러가 날 수가 있습니다. 이러한 부분을 잘 생각하여 설정을 해야 합니다.

 

 

=================================

=================================

=================================

 

 

출처: http://kimkijeung.com/category/flash-as3/

Archive for the 'Flash-AS3.0' Category

Problems of AVM1 loaded by AVM2

Published on 2008/05/26 in Flash-AS3.0CommentsTags: avmloader.

flash 개발환경이 AS3.0 대체되고 있는 상황에서 기존에 개발되어 있던 AS1.0 또는 AS2.0 으로 개발된 컨텐츠의 병행사용은 어느정도 같이 가져가여 할 부분이다.
여기서 약간 문제가 되는 부분은 AS3.0 으로 제작된 부분에서  AS1.0 또는 AS2.0 제작된 부분을 로드할 경우 발생하는 이슈이다.

AS3.0 부터는 AVM2 라고 하는 성능이 대폭개선된 가상머신을 도입했다. 이전의 가상머신은 AVM1 이라고 하여 AS1.0 또는 AS2.0 이 실행될 수 있는 환경을 말한다.
이런 기본적인 환경의 차이로 인해 기본적으로 AVM1 과 AVM2 무비사이간의 어떠한 커뮤니케이션이 가능하지 않다. 물론 LocalConnection 을 사용하면 가능하다.

단지, AVM2 에서 AVM1 을 로드하여 어떠한 cross-scripting 없이 사용한다면 로드한다는 것 자체에 별다는 이슈가 없어야 할텐데 실제적으로는 몇가지 문제가 발행한다.

만약에 AVM2 기반에서 AVM1 의 파일을 로드해서 사용했을 경우 일반적으로는 별 이상없이 작동한다. 하지만 AVM1 파일의 depth 가 커지면 커질수록 다시말해 AVM1 파일의 구조가 서로다른 로더에 의해 여러개의 구조로 이루어졌을경우  이상하게도 이 AVM1 파일들간의 인스턴스 구조가 변경되는 문제가 발생한다. 이는 여러 다른 플래시 개발자에게도 발생한 현상이다.

이러한 결과로  로드한 무비가 제대로 제어가 되지않거나 unload 가 되지 않는 현상이 발생한다.

아직까지 원인이 무엇인지는 찾지는 못했지만 약간의 팁으로 이런 위기상황를 극복할 수 있다.

첫째로, AVM1 컨텐츠들 간에서 다른 AVM1 컨텐츠를 로드해서 제어할때는 반드시 새로운 무비클립을 동적으로 생성하여 로드를 하고 언로드할 경우에는 remove 를 한다.

 

둘째로, 로드를 하는 AVM2 에서는 로더를 DisplayContainer 에 직접 붙이지 말고 로더의 컨텐츠(loader.content)를 사용하여 추가한다.

 

 

=================================

=================================

=================================

 

 

출처: http://blog.grotesq.com/post/298

 

[AQuery] 로드한 swf 완전히 정지한 후 unloadAndStop 하기

댓글을 달아주세요

다음과 같은 방법으로 플래시 무비를 로드해 왔을 경우를 생각해 봅시다.

?

var loader:Loader = new Loader();
loader.load( new URLRequest( "ani.swf" ) );
addChild( loader );

그리고 애니메이션을 제거해야 하는 시점에 unloadAndStop()을 실행합니다.

?

loader.unloadAndStop();

이 경우 애니메이션이 정지되고 언로드 됩니다. 일반적으로는.
하지만 항상 그렇다고 장담을 할 수가 없죠.
AVM의 가비지 컬렉터는 임의로 호출할 수가 없습니다.
unloadAndStop은 로드된 애니메이션을 정지하고 가비지 컬렉팅의 우선순위를 높여줄 뿐이지 강제로 지워주진 않습니다.
그리고 가끔은 애니메이션이 정지되지 않아 사운드가 계속 재생이 된다든가 하는 문제가 발생하기도 합니다.
다음과 같이 처리를 해보도록 하겠습니다.

?

import com.grotesq.aquery.AQuery;
import com.grotesq.aquery.$;


// 모든 MovieClip을 탐색하고 stop()
$( "MovieClip" ).eachApply( function( $index:int, $element:DisplayObject ):void {
    MovieClip( $element ).stop();
} );
loader.unloadAndStop();

이 코드로도 제거되지 않는다면, 로드된 플래시 내에서 동적으로 무비클립이 생성되고 있는 경우일 겁니다.

이 글은 Flash개발 카테고리로 분류되었고 2013년 8월 15일에 작성됐습니다.

 

 

=================================

=================================

=================================

 

 

 

반응형

 

728x90

 

 

 

 

출처: http://blog.visualp.com/i/entry/137

 

Flash Player Internals v2

Flash | 2009/10/15 01:36 | by actionfigure

조금 많이 늦었지만 올초 열렸던 FITC Toronto 2009의 비디오 프레젠테이션들을 이제야 보았습니다. 
FITC의 프레젠테이션들은 너무 길어서 지루하네요,  질도 높이고 시간을 줄여서 역동적으로 만들면 참 좋을 듯 싶네요.
이런 멋진 커뮤니티가 있는게 부럽네요.

아무튼 제게 가장 흥미로웠던 세션은 새로운 플래시 플래이어의 내부에 대해서 조금 더 알게 해 주었던 Jim Corbett의 Flash Player Internals v2 이었습니다.

v1 프레젠테이션에서 몰랐던 많은 사실을 알게 되었어서 기대를 많이 했습니다.

흥미로운 몇 가지를 적어 보도록 하겠습니다.

  • Loader.unloadAndStop()


Grant Skinner에 의해서 제기되서 구현했다는 Loader.unloadAndStop() 관한 것입니다.
AS3에서 load한 무비 클립을 unload 해도  그 로드 되었던 무비 클립이 사용했던 사운드, 이벤트 핸들러, 자식 무비 클립들은 그 로드된 무비클립에서 제대로 처리해주지 않으면 그대로 메모리에 남게 됩니다. 로드 되는 무비 클립이 본인이 제작할 수 있는 것이라면 고쳐 주면 되겠지만, 다른 제작자들의 swf를 그냥 로드해야 하는 경우엔 어쩔 도리가 없습니다.  그 때 이 unloadAndStop()를 호출하면 로드된 무비 클립의 자식 디스플레이 노드들을 돌면서 사운드도 죽이고, 핸들러도 없애고, 언로드 시킨다고 합니다.
그냥 unload 함수를 고치지 않고 새로 함수를 만든 이유는 호환성 때문이랍니다.
Details


  • Timeline Improvements

 

 

 

=================================

=================================

=================================

 

 

출처: http://ddongkang.tistory.com/135

[AS3] 외부에서 로드된 객체 복제(재사용)

 

 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 를 통해 객체를 생성하여 사용 합니다.

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

 

 

=================================

=================================

=================================

 

 

반응형