2010년 4월 17일 토요일

BitmapData클래스

 

- BitmapData는 Object클래스에서 상속받는다. 이 BitmapData클래스는 bitmapData속성을 사용하여 Display

  패키지(DisplayObject) 안에 정의 되어 있는 Bitmap객체를 픽셀 데이터로 처리 할 수 있다. 또 Loader를 통

  해 로드한 비트맵 이미지에서도 액세스가 가능하다.

  Bitmap클래스는 구조가 InteractiveObject와 Shape와 같은 레벨에 있기 때문에 InteractiveObject에서

  정의되어 있는 마우스 이벤트 전달을 할 수 없다. 그러나 Bitmap를 포함하는 DisplayObjectContainer의

  addEventListener()로는 가능하다.

 

*BitmapData는 비트맵 이미지를 로드할 때 픽셀 제한이 있으므로 미리 크기를 고려하여 로드한다.

     Flash Player 10에서는 BitmapData 객체의 최대 높이 또는 폭의 크기가 8,192픽셀이며 총 픽셀 수는

     16,777,216픽셀을 초과할 수 없다. 따라서 객체의 폭이 8,192이고 높이가 2,048픽셀 이하인 이미지를 로드

     해야한다. Flash Player 9 이전 버전은 제한 픽셀이 2,880 * 2,880픽셀이다.

 

- BitmapData에서 이미지를 로드하는 과정을 보면 이렇다.

   플레시에서 이미지를 Load하는 순간 flash에서 비트맵 데이터로 분석하고 DisplayObect가 화면에 표시를

   해준다. 화면에 표시를 해준걸 Edit possible을 해줘. 편집이 가능 하도록 변경해준다.

   여기서 편집가능하다는 말이 비트맵 데이터로 분석한 과정에서 그 이미지를 Capture해서 우리가 포토샵

   같은 곳에서 핸들링 할수 있도록 해주는 기능과 같다는 것이다.

 

   예를 들어, 사진의 실제 크기가 2000 * 3000이라 치면 Load클래스에서 정의된 loader라는 객체는 실제로

   가벼운데 이 큰 사진을불러 오는 순간 무거워지게 된다. 그래서 불러오기 전에 크기를 stage의 크기로 줄

   여서 캡쳐를 뜨고 그 다음에 축소된 사진을 불러오는 것이다. 그럼 원래 크기인 2000 * 3000인 stage를 넘

   어서는 커다란 사진이 불러와서는 딱 stage크기만해지니 훨씬 가벼워질 수 있는 것이다.

 

   그러데 여기서 이렇게 크기를 scaelX속성을 사용하여 축소시키면 addChild()가 되지 않는다. 따라서 이럴

   떄에는 Graphics를 사용하여 그리면 되는데 Graphics에는 beginFill을 bitmap으로 대신 넣어서 그려넣는

   beginBitmapFill()메소드를 사용하면 된다.

 

   여기서 이미지를 불러오는 과정에 BitmapData에서 draw()라는 메소드가 있는데 여기에 파라미터값으로

   넘기는 값중에 soure라는 파라미터가 있다.

  

  

   그 값은 IBitmapDrawable이라는 인터페이스에서 구현되어져 있는데 이 인터페이스는 이미 DisplayObject

   에서 정의 되어져 있어서 그릴 수 있다. 눈에 보이는 모든 것들은 Sprite를 통해 DisplayObject를 상속 받아

   져 있기 때문에 source 매개변수에 loader를 써도 된다는 것이다.

 

* 여기서 인터페이스는 회사의 계약서라고 생각하면 된다. 명시만 해주는 것으로 아래와 같이 써준다.
[code as3]
public class Main extends Sprite implements IMain
[/code]

또 실제 인터페이스 인 IMain.as속 소스는..

[code as3]
public function a() : void{}

[/code]

이런식으로 메소드만 정의된 형태로 들어가있다.
여기서 접근자는 무조건 public이어야 한다.

아무내용이 없더라고 IMain에서 명시되어져 있는 함수를 무조건 Main에서 사용해야 한다. 형태 그대로..

파마미터가 있으면 있는대로...!!

 

인터페이스는 프로그래밍하는 개발자에게 길잡이 역할을 하는 것이나 다름 없다. 아직 완전히 와닿지는

않으나 여기까지만 알아두면 좋겠다.

 

 

2010년 4월 15일 목요일

MovieClip클래스 - play(),stop(),nextFrame(),prevFrame(),gotoAndStop()

 

- MovieClip 객체에는 이렇게 상속된다.

 

 

- MovieClip객체는 위와 같이 여러 클래스들을 상속받게되어 무겁다. 그래서 Sprite클래스를 Linkage에서

  Base클래스로 써도 무방하다. 그러나 프레임 제어를 할때에는 반드시 MovieClip을 상속받아야 한다.

  만약 프레임 제어를 하는데도 그대로 Sprite를 Base Class로 사용하게 된다면 함수를 사용할 수 없다고

  에러 메세지가 나타나게 된다. 위에서의 그림처럼 MovieClip에서 정의되어 있는 메소드들이 있는데 더적은

  범위에 있는 Sprite를 받은 상태에서 MovieClip에 메소드를 사용하려니 당연히 그 함수는 사용할 수 없다는

  에러 메세지가 나올 수 밖에 없는 것이다.

 

- 예를 들어 50프레임쯤에서 stop()을 하고 싶은데 stop()이라는 메소드가 MovieClip에 있다.

에러 메세지

 

레퍼런스에서의 정의

 

- 이런 것들을 고려하여 무비클립에 정의된 메소드들을 이용한 간단한 예제를 만들어 보았다.

 

 

 

MC_Animation.as

[code as3]
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;

public class MC_Animation extends Sprite
{
    public function MC_Animation()
    {
        super();

        config();
    }

    //-------------------------------------------------------------
    //
    //     Variables
    //
    //-------------------------------------------------------------
    private var isPlaying:Boolean = false; //재생버튼을 제어할 Boolean형의 객체 변수

    private var baseFps:int = stage.frameRate; //2배속재생버튼의 속도를 제어할 int형의 객체 변수

    //-------------------------------------------------------------
    //
    //     Properties
    //
    //-------------------------------------------------------------
    /**
     *    @private
     *    초기값 설정. 이벤트 등록과 버튼모양 변경
     */
    private function config() : void
    {
        pic.stop(); //모션이 들어간 무비클립 pic을 stop()으로 멈춤.

        //각종 버튼들에 버튼모드를 손모양으로 변경
        next_mc.buttonMode = true;
        prev_mc.buttonMode = true;
        play_mc.buttonMode = true;
        pause_mc.buttonMode = true;
        stop_mc.buttonMode = true;
        play_2_mc.buttonMode = true;

        //각종 버튼마다 움직임 정의할 이벤트 등록
        next_mc.addEventListener( MouseEvent.CLICK, nextClickHandler );
        prev_mc.addEventListener( MouseEvent.CLICK, prevClickHandler );
       
        play_mc.addEventListener( MouseEvent.CLICK, ppsClickHandler );
        pause_mc.addEventListener( MouseEvent.CLICK, ppsClickHandler );
        stop_mc.addEventListener( MouseEvent.CLICK, ppsClickHandler );

        play_2_mc.addEventListener( MouseEvent.CLICK, play2ClickHandler );
    }

    /**
     *    @private
     *    next_mc를 click하였을 때 움직임
     */
    private function nextClickHandler( e:MouseEvent ) : void
    {
        if( pic.currentFrame == pic.totalFrames ) //현재 프레임과 총 프레임수를 비교하여 같다면,
        {
            pic.gotoAndStop(1); //다시 처음 프레임으로 이동

            return; //if문을 빠져나온다
        }

        pic.nextFrame(); //처음 프레임으로 이동 후 계속 한 프레임씩 이동
    }

    /**
     *    @private
     *    prev_mc를 click하였을 때 움직임
     */
    private function prevClickHandler( e:MouseEvent ) : void
    {
        if( pic.currentFrame == 1 ) //현재 프레임이 1이라면,
        {
            pic.gotoAndStop( pic.totalFrames ); //다시 맨 끝 프레임으로 이동

            return; //if문을 빠져 나온 뒤,
        }

        pic.prevFrame(); //nextFrame()과 반대로 이전 프레임으로 한 프레임씩 이동
    }

    /**
     *    @private
     *
     *    @param e.target : play_mc, pause_mc, stop_mc 무비클립
     *    play_mc, pause_mc, stop_mc를 click하였을 때의 움직임
     */
    private function ppsClickHandler( e:MouseEvent ) : void
    {
        switch( e.target ) //이벤트로 넘겨받은 인스턴스가
        {
            case play_mc : //play_mc라면,

                if( isPlaying ) //isPlaying이 true라면, 즉 재생되고 있다면
                {
                    pic.stop(); //재생을 멈추고
                }
                else //isPlaying이 false라면, 즉 멈춰있다면
                {
                    stage.frameRate = baseFps; //초당 프레임 속도를 확인해주고

                    pic.play(); //다시 재생해줌
                }

                isPlaying = !isPlaying; //바뀐 Boolean값을 바꾸어 줌

                break; //빠져나옴

            case pause_mc : //e.target이 pause_mc 일시정지 버튼을 클릭했다면

                pic.stop(); //프레임 재생을 그대로 멈추어주고

                break; //빠져나옴

            case stop_mc : //e.target이 stop_mc 정지 버튼을 클릭했다면

                pic.gotoAndStop(1); //재생하고 있던 프레임을 맨 처음 프레임으로 가서 멈추게하고,

                break; //빠져나옴
        }
    }

    /**
     *    @private
     *    play_2_mc를 click하였을 때 움직임
     */
    private function nextClickHandler( e:MouseEvent ) : void
    {
        stgae.frameRate = 24; //현재 stgae에 정의되어 있는 초당 프레임 속도보다 2배 빠르게.

        pic.play(); //프레임 재생
    }
}
}
[/code]

- 106번째 줄에서 왜 다시 초당 프레임 속도를 다시 확인해주는가에 대한 것을 보면, 2배속으로 빠르게 재생

   하는 함수에서 24로 초당 프레임을 바꾸어 주었기 때문이다. 예를 들어, 재생 버튼을 눌러서 재생하다가

   중간에 2배속 재생 버튼을 누른 후 다시 재생 버튼을 눌러주게 되면 컴퓨터상에서는 stage의 frameRate를

   그전에 바꾸어 놓았던 24의 속도로 기억하고 있기 때문에 다시 한번 fla파일에서 원래 지정해 주었던 24의

   반의 속도인 baseFps 12의 속도로 넣어줘야 한다. 그래야 정상적인 재생 속도를 확인할 수 있다.

 

   또 2배속 재생 버튼을 누르다가 재생버튼을 누르면 멈추는 이유는 100번째 줄을 보면 알 수 있다. 재생할

   때에 편리성을 위해 재생버튼에 일시정지 기능도 함께 넣은 것이나 마찬가지 이다.

 

   isPlaying이라는 Boolean형의 객체변수를 20번째줄에서 false로 정의 내린 것을 if문을 활용하여 참, 거짓

   에 따라 재생해라, 멈춰라의 기능을 넣어준 것이다. 만약 20번째 줄에서 false를 true로 바꾸어 준 후, 재생

   버튼을 누르게 되면 두번을 클릭해야 원하는 재생을 할 수 있다.

 

* 참고로, pic을 그냥 막그린 저런 배경 틀에 맞게 나오게 하기 위해서는 Mask효과를 사용하였다.

  약간의 노가다 적인 배경에 맞춘 mask를 씌울 shape을 펜툴로 그린 다음 모션이 들어간 그림위에 레이어

  를 위치시킨 후, 마우스 오른쪽 클릭하여 Mask를 하면 펜툴로 그린 모양만큼만 효과가 적용되어 마치 배경

  그림을 따라 그림이 나오는 것 같은 효과를 볼 수 있다.

 

 

- 레퍼런스에서 Mask에 대한 정의를 잠깐 살펴보면, DisplayObject클래스에서 정의되어진 메소드이다.

 

이 메소드를 클래스로 만들어서 코드에 적용시켜보면 이렇다.

[code as3]
package
{
import flash.text.TextField;
import flash.display.Sprite;
import flash.events.MouseEvent;

public class maskSample extends Sprite
{
    public function maskSample()
    {
        super();

        config();
    }
 
    private var tf:TextField = new TextField();

    private var square:Sprite = new Sprite();

    /**
     *    @private
     *    화면에 나오는 요소들 초기값 설정
     */
    private function config() : void
    {
        //TextField로 생성한 객체 tf에 text를 넣음
        tf.text = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
                + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
                + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
                + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "

        tf.selectable = false; //텍스트필드 선택가능여부 false

        tf.wordWrap = true; //줄바꿈

        tf.width = 150; //텍스트 필드의 넓이

        addChild(tf); //화면에 붙임

        square.graphics.beginFill(0xFF0000); //Sprite로 생성한 객체에 빨간색 채움
 
        square.graphics.drawRect(0, 0, 40, 40); //가로 40 세로 40 크기의 사각형을 그림

        addChild(square); //화면에 붙임

        tf.mask = square; //텍스트 필드위에 Sprite형의 객체를 mask처리함

        tf.addEventListener(MouseEvent.MOUSE_DOWN, drag); //Drag를 위한 MouseDown 이벤트 등록
        tf.addEventListener(MouseEvent.MOUSE_UP, noDrag); //Drag를 위한 MouseUp 이벤트 등록
    }

    private function drag(event:MouseEvent):void
    {
        square.startDrag(); //사각형을 눌렀을 때 드래그 시작
    }

    private function noDrag(event:MouseEvent):void
    {
        square.stopDrag(); //사각형을 눌렀다 떼면 드래그 멈춤
    }
}
}
[/code]

예제 출처

 

 

- 코드에서는 Sprite형의 객체에 사각형을 그린후 빨간색으로 색을 채웠음에도 불구하고 안나오는 이유는

   mask처리를 해주었기 때문에 영역만 잡히고 색은 적용은 되었지만 화면상에서는 보이지 않는다.

   MC_Animation.as 예제에서 fla파일에 직접 빨간색의 Shape를 mask해준 것과 같은 것이다.

 

2010년 4월 10일 토요일

ScrollBar - 스크롤바2(슬라이더)

 

- 이번 예제는 스크롤바의 바닥 부분(?)도 클릭하였을때 bar가 클릭한 부분으로 이동되며 그 위치도

  TextField부분에 나오도록 바꾸어 보았다.

  그러기 위해서 stick부분이 원래 단순shape였는데 무비클립으로 바꾸어주고 Sprite로 Linkage해준다.

 

 

- 그리고 인스턴스 네임을 stick으로 준다.

 

 

- 우선 결과물을 보면 이렇다.

 

 

ScrollBarExample.as

[code as3]
package classes.SliderBotton
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Rectangle;

public class ScrollBarExample extends Sprite
{
    public function ScrollBarExample()
    {
         super();

        config();
    }

    //--------------------------------------------------------------
    //
    //     Variables
    //
    //--------------------------------------------------------------
    private var min:Number = 0; //stick의 최소값을 0으로 초기화

    private var max:Number = 200; //stick의 최대값을 200으로 초기화

    private var length:Number = 300; //stick의 길이를 300으로 초기화

    private var pos:Number;

    //--------------------------------------------------------------
    //
    //     Properties
    //
    //--------------------------------------------------------------
    /**
     *    @private
     *    초기값 설정
     */
    private function config() : void
    {
         bar.buttonMode = true; //bar의 마우스모양을 손모양으로 변경
 
         stick.buttonMode = true; //stick의 마우스모양을 손모양으로 변경

         bar.addEventListener( MouseEvent.MOUSE_DOWN, barDownHandler ); //마우스를 눌렀을 때 bar에 이벤트 등록

         stick.addEventListener( MouseEvent.CLICK, stickClickHandler ); //마우스를 클릭했을 때 stick에 이벤트 등록
    }

    /**
     *    @private
     *    bar를 눌렀을 때 움직이는 동작
     */
    private function barDownHandler( e:MouseEvent ) : void
    {
        bar.addEventListener( Event.ENTER_FRAME, showTxt ); //bar를 클릭했을 때 textField에 나올동작을 enterFrame으로 이벤트 등록

        var bounds:Rectangle = new Rectangle( 0, 0, 300, 0 ); //

        bar.startDrag( bounds );

        stage.addEventListener( MouseEvent.MOUSE_UP, stageUpHandler );
    }

    /**
     *    @private
     *    stage에서 MouseUp 이벤트 감지후 제거
     */
    private function stageUpHandler( e:MouseEvent ) : void
    {
         bar.removeEventListener( Event.ENTER_FRAME, showTxt ); //enterFrame이벤트 제거
         
         bar.stopDrag(); //Drag동작을 정지시킴

        stage.removeEventListener( MouseEvent.MOUSE_UP, stageUpHandler ); //stage에서 MouseUp이벤트 제거
    }

    /**
     *    @private
     *    TextField에 위치 출력
     */
    private function showTxt( e:Event ) : void
    {
        pos = Math.round( ( bar.x * ( max - min ) ) / length - min ); //pos변수에 stick과 bar의 위치를 구한 공식을 대입. 변수들이 다 Number로 선언되었기 때문에 round()로 정수로 변환후 대입

        txt.text = String( pos ); //textField에 pos를 String형으로 변환하여 대입
    }

    /**
     *    @private
     *    stick을 클릭했을 때 동작
     *
     *    @param e : EnterFrame동작의 Event
     */
    private function stickClickHandler( e:MouseEvent ) : void
    {
         bar.x = mouseX; //mouse의 x좌표를 bar의 x좌표로 변경

         showTxt(e); //showTxt() 함수를 호출. stick의 위치를 textField로 출력하기 위함
    }
}
}
[/code]

- 저번 예제와 또 다른점은 stick의 길이를 300으로 넓혀주었다. 저번 예제에서는 stick의 길이도 200으로

  하여 그냥 단순히 bar의 x좌표를 String으로 변환하여 textField로 넣어주었는데 이번에는 stick의 길이에

  상관없이 최소값과 최대값을 정하여 그 값으로 나오게 하는 것이다.

 

  이번에는 저번 예제에서 구한 pos라는 비율을 적용해 보았다. 그럼 stick의 길이가 300인데도 불구하고

  min값과 max값을 정하여 원래 값으로 나눠주는 과정에서 200의 비율로 textField값이 나오게 된다.

  또 84번째줄에서 이렇게 해주면 pos와 min, max 등이 Number값이기 때문에 소수점이 나오기 때문에

  Math함수에서 round()메소드를 사용하여 pos값을 0.5값이 나오면 가까운 정수로 올림하여 적용시켜 준다.

  *잠깐, Math.round()에 관한 내용을 보면 이렇다.

 

  93번째 줄에서는 stick 부분을 클릭하였을 때의 동작 부분으로 마우스로 stick부분을 클릭하였을 때 bar를

  이동시키는 방법은 단순히 stick부분을 클릭하는 동작을 마우스가 하게 되므로 마우스의 x좌표를 bar의

  x좌표로 대입시켜주면 bar의 위치가 이동되게 되는 것이다. 그리고 그 값을 bar의 값과 동일하기 때문에

  showTxt()함수를 호출하여 주었다. showTxt()는 위에 이벤트 등록시 매개변수 값으로 이벤트값을 가지고

  오게 되므로 매개변수 값도 함께 넣어서 호출해주었다.

 

 

 

2010년 4월 6일 화요일

scrollbar - 스크롤바(슬라이더)

 

- 스크롤바를 만들어 봄으로써 볼륨바, 컨텐스 스크롤, 다양한 조절기능을 할 수 있다.

 

 

 

sliderButton.as
[code as3]
package classes.SliderButton
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Rectangle;

public class SliderButton extends Sprite
{
    public function SliderButton()
    {
        super();

        bar.buttonMode = true; //버튼 모드 변경

        bar.addEventListener( MouseEvent.MOUSE_DOWN, downHandler ); //bar에 마우스이벤트 등록
    }

    /**
     *    @private
     *    bar를 mouseDown했을 때의 효과적용
     */
    private function downHandler( e:MouseEvent ) : void
    {
        bar.addEventListener( Event.ENTER_FRAME, showTxt ); //bar에 enterFrame이벤트 등록

        var bounds:Rectangle = new Rectangle( 0, 0, 200, 0 ); //Rectangle클래스 객체 생성 및 초기화

        bar.startDrag( true, bounds ); //lockCenter를 가운데로 true, bounds값 적용, drag 시작

        stage.addEventListener( MouseEvent.MOUSE_UP, upHandler ); //stage에 마우스이벤트 등록
    }

    /**
     *    @private
     *    마우스를 뗐을때 효과적용
     */
    private function upHandler( e:MouseEvent ) : void
    {
        bar.removeEventListener( Event.ENTER_FRAME, showTxt ); //bar에 등록되었던 이벤트 제거

        bar.stopDrag(); //drag 멈춤

        stage.removeEventListener( MouseEvent.MOUSE_UP, upHandler ); //stage에 등록된 이벤트 제거
    }

    /**
     *    @private
     *    텍스트 필드에 값 적용
     */
    private function showTxt () : void
    {
        txt.text = String( bar.x ); //화면에 Text가 bar의 x좌표 값으로 적용
    }
}
}
[/code]


- 이 예제는 네모난 무비클립 bar를 움직일 때 마다 그 위치가 텍스트 필드에 찍히게 하는 예제이다.

  화면에 미리 무비클립을 생성하고 Linkage를 SliderButton으로 해주고, 텍스트 필드는 Dynamic Text로

  설정해준다. Dynamic TexFeild로 해주어야 다른 값들을 받아 올 수 있다.

 

  startDrag에서 bounds를 지정해준 것은 width가 200인 영영안에서만 동작할 수 있도록 보이진 않지만

  드래그의 위치를 bar의 무비클립 시작지점에서 200만큼만 지정해준 것이다.
  그리고 밑에 stage에 이벤트를 등록해준 이유는 3.0에서는 onReleaseOutside라는 이벤트가 없어졌기

  때문에 마우스가 bar의 영역을 벗어나더라도 어디서나 감지 할 수 있도록 더 넓은 범위인 stage로 감지하

  여 remove하도록 이벤트를 걸어주었다.
 

  showTxt함수에서 TextField값을 bar의 x좌표로 적용해줄때 bar.x의 값은 소스에서 정의되어 있지 않아도

  자동 Number값이기 때문에 텍스트로 들어가기 위해서 String으로 변환하여 적용해주는 것이다.

 

  여기서 만약 드래그를 하는데 있어서 0~200의 값이 아닌 0~200범위 안에서 0~100의 범위를 갖게 하려면

  [code as3]
   txt.text = String( bar.x / 2 );
  [/code]
  이런식으로.. 그렇다면 -100~100의 범위를 갖게 하고 싶다면?

  [code as3]
   txt.text = String( ( bar.x / 2 ) * 2 - 100 );
  [/code]
  조금씩 난해해진다.. 그래서 이것을 공식으로 완성시켜보면!

  비례식으로 풀어보면,

  200 : bar.x = ( max - min ) : ( pos - min ) 이 되는데

 

 pos = ( bar.x * ( max - min ) ) / 200 - min

 

  이라는 식이 나온다.

 

  이렇게 나온 결과값으로 showTxt에 bar.x가 아닌 pos를 대입해보면 0~200이 아닌 min과 max의 값에 따라

  원하는 값을 얻을 수 있게 된다.

 

 

2010년 4월 5일 월요일

FileReference클래스

 

- FileReference클래스는 사용자 컴퓨터와 서버 사이에서 파일을 업로드, 다운로드 할 수 있는 방법을 제공

  한다. 우리가 흔히 파일을 받아서 저장하는 기능을 플래시에서도 구현할 수 있다는 것이다.

  FileReference도 일종의 PC와 서버사이의 통신을 하는 것에 속하므로 flash.net 패키지에 포함된다.

  FileReference에도 여러가지 메소드들이 있는데 그중 browser()라는 메소드를 보면,

 

 

  업로드할 파일을 선택할 수 있는 운영체제 대화 상자를 뜨게하는 메소드이다. 이 메소드는 한번에 하나만

  수행할 수 있다. 만약 FileReference.browser(); 하게되면 이런 창이 뜨는 것이다.

 

 

여기에서 매개변수로 browse(typeFilter:Array = null)typeFilter라는 배열객체로 들어가는데

파일을 필터링하는데 사용되는 인스턴스 배열이라고 한다. 파일을 필터링하는 것은 사용자가 선택할

수 없고 지정되지 않은 확장명이라던지 파일형에 관한 필터링을 하는 것을 말한다.

예를 들어 FileFilter는 이런식이다.

[code as3]
var imageFilter:FileFilter = new FileFilter( "Image", "*.jpg, *.gif, *.png" );
var myfr:FileReference = new FileRefence();
myfr.browser( [imageFilter] );
[/code]

* 업로드와 다운로드는 Flash Player에서 파일의 크기를 제한하지 않지만, 공식적으로 100MB이하

업로드 또는 다운로드를 지원한다고 한다. upload()와 download()메소드는 비차단 방식으로 만일

FileReference 객체의 범위를 벗어나는 경우 즉 업로드와 다운로드 파일전송이 완료되지 않은 상태에서

범위를 벗어나면 취소가 된다.

 

업로드는 upload(request:URLRequest, uploadDataFieldName:String = "Filedata", testUpload:Boolean = false)이렇다.

- request는 통신객체로 HTTP post 형식의 호출을 통한 url이 포함되어 있어야 한다.

- uploadDataFieldName은 파일 데이터 앞에오는 필드이름이다. null이면 안된다.

- testUpload는 Boolean값으로 true인 경우, 파일크기가 10KB보다 크면 FlashPlayer는 내용의 길이가 0인

  테스트 파일 업로드 POST를 한다.

 

다운로드는 download(request:URLRequest, defaultFileName:String = null)이렇다.

- request는 로컬 컴퓨터로부터 다운로드할 파일의 URL이 포함되어야 한다. 이 매개변수가 null일 경우 예외

  가 발생하므로 반드시 써줘야한다. 또 일반 브라우저에서 URL문자열의 길이가 제한이 있으므로 256보다 긴

  경우는 다운로드를 실패할 수도 있다.

- default는 다운로드할 파일의 기본 파일 이름으로 / | : * ? " < > 등 특수문자는 포함될 수 없다.

 

download()메서드는 운영체제 대화상자를 열어서 파일을 선택하고 저장할 위치를 선택하고 다운로드를 하겠다는 버튼을 누르면 서버에서 바로 다운로드를 실시하게 된다. 이 과정에서 다운로드를 하면서 파일을 선

택하여 저장하는 과정이 있는데 이 과정에서 save()메소드가 그 중요한 역할을 한다.

 

저장 메서드는 save(data:*, defaultFileName:String = null) 이런값이 있다.

- data는 저장할 데이터로 이 값도 null이 되면 ArgumentError 예외를 발생시킨다. 이 매개변수는 다양한 형

  태에 따라 다르게 처리 되는데 그 다양한 형식을 보면,

  값이 String인 경우 UTF-8 텍스트 파일로 저장되어지고 XML인 경우는 텍스트 파일에 XML형식으로 유지해

  주고, ByteArray객체인 경우라도 그대로 기록해주고 그외의 값인 경우는 save()메서드가 toStrng()메서드를

  호출하여 데이터를 문자열로 변환하여 텍스트 파일에 저장한다. 이작업이 실패가 되면 예외가 발생한다.

 

 

 

 

2010년 4월 3일 토요일

callBack - 콜백함수를 이용한 paricle예제

 

기존에 쓰던 parent속성은 종속관계가 있어 강한 결합을 만들기 때문에 대신 약한 결합인 콜백함수를 써보자

 

 

Particle.as

[code as3]
package
{
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.events.MouseEvent;

import classes.display.Seed;

public class Particle extends Sprite
{
    public function Particle()
    {
        super();
   
        config();
    }

    /**
     *    @private
     *    stage에 MouseMove이벤트 등록
     */
    private function config() : void
    {
        stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMoveHandler );
    }

    /**
     *    @private
     *    seed객체 생성과 초기화
     */
    private function mouseMoveHandler( e:MouseEvent ) : void
    {
        var seed:Seed = new Seed(); //seed객체 Sprite로 생성

        seed.onTransParent = seedTransParent; //Seed.as에 함수에 seedTransParent 대입

        seed.x = mouseX; //seed의 x좌표값을 현재 마우스의 x좌표로 대입
        seed.y = mouseY; //seed의 y좌표값을 현재 마우스의 y좌표로 대입

        var ratio:Number = Math.random(); //ratio라는 변수에 랜덤값 생성

        seed.scaleX = ratio; //seed의 scaleX를 ratio로 대입
        seed.scaleY = ratio; //seed의 scaleY를 ratio로 대입

        seed.alpha = Math.random(); //seed의 alpha값을 랜덤하게 만듦

        addChild( seed ); //화면에 seed를 붙임
    }

    /**
     *    @private
     *    display라는 매개변수로 표시객체를 제거
     */
    private function seedTransParent( display:DisplayObject ) : void
    {
        removeChild( display );
    }
}
}
[/code]


Seed.as
[code as3]
package classes.display
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;

public class Seed extends Sprite
{
    public function Seed()
    {
        super();

        vx = Math.random() * 10 - 5; //x좌표의 속도를 -5~5사이
        vy = Math.random() * 10; //y좌표의 속도를 0~10사이

        gravity = 1; //중력가속도의 값은 1

        addEventListener( Event.ENTER_FRAME, alphaEnterFrameHandler );
    }

    //-----------------------------------------------------
    //    variables
    //-----------------------------------------------------
    private var vx:Number; //x 속도
    private var vy:Number; //y 속도
  
    private var gravity:Number; //중력가속도 변수

    private var _onTransParent:Function; //function객체 생성. _onTransParent = null

    //-----------------------------------------------------
    //     properties
    //-----------------------------------------------------
    public function set onTransParent( value:Function ) : void
    {
        _onTransParent = value;
    }

    public function get onTransParent() : Function
    {
        return _onTransParent;
    }

    /**
     *    @private
     *    중력가속도와 속도, alpha와 scaleX scaleY, color 등 효과 적용
     */
    private function alphaEnterFrameHandler( e:Event ) : void
    {
        vy = vy + gravity; //속도y좌표에 중력가속도를 더함

        this.x += vx; //seed의 x좌표에 속도x씩 더함
        this.y += vy; //seed의 y좌표에 속도y씩 더함

        this.alpha -= 0.05; //seed의 alpha를 0.05씩 감소시킴

        this.scaleX += 0.05; //seed의 scaleX에 0.05씩 더함
        this.scaleY += 0.05; //seed의 scaleY에 0.05씩 더함

        var ct:ColorTransform = this.transform.colorTransform; //colorTransform객체 생성

        ct.color = Math.random() * 0xFFFFFF; //위에서 생성한 ct에 랜덤 색상을 넣어줌

        this.transform.colorTransform = ct; //seed의 색상을 ct의 랜덤컬러로 변경

        if( alpha < 0 ) //seed의 알파가 0.05씩 줄어서 0보다 작으면 true, 아니면 false
        {
            removeEventListener( Event.ENTER_FRAME, alphaEnterFrameHandler ); //alpha가 0이면 enterFrameEvent제거

            if( _onTransParent != null )
            {
                _onTransParent( this );
            }
        }
    }
}
}
[/code]


- Particle클래스에서 Seed클래스에 있는 Function으로 생성된 함수를 참조하는 것이다.

  마치 매개변수를 넘겨주듯이 하면 된다. 데이터를 넘겨줄 때 이벤트를 써서 하는 방법도 있는데

  그 방법은 이벤트 클래스를 만들고 dispatch해주는 작업에서 딜레이가 되기 때문에 보다 빠르고

  다이렉트한 방법으로 콜백함수를 쓴다
 

  Particle클래스에서 26번째줄에 stage에 MouseMove이벤트를 등록해준 것은 마우스를 stage어느 곳에서

  이리저리 움직일 때마다 원이 나왔다 사라지게 하기 위해 MouseMove이벤트를 등록해준 것이다.

  mouseMoveHandler함수는 앞에 예제에서 해보았던 것들 처럼 seed의 객체를 생성해서 그 seed에 여러

  가지 color, alpha, x와 y좌표 등의 효과를 적용시키는 부분이다.


  객체는 여는 중괄호와 닫는 중괄호로만 존재한다면 객체라 할 수 있다. 따라서 function도 객체에 속하기

  때문에 변수로 선언하여 값을 넘겨주는게 자연스럽게 이루어진다.

 

2010년 4월 2일 금요일

Duplicate - 다양한 객체 만들기(복제-패턴2)

 

- 한 무비클립을 복제하여 패턴을 만드는 예제를 하였었는데, 스터디 선생님의 권유로 약간 변형을 해보았다

 

 

  랜덤으로 색이 바뀌게 하는 네번째 버튼을 없애고 애초에 페이지에 진입하면 Timer 이벤트로 저절로 색이

  바뀌도록 바꿔보았다.

 

 

[code as3]
package
{
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.MouseEvent;
import flash.events.IEventDispathcer;
import flash.geom.ColorTransform;

public class Duplicate_pattern extends Sprite
{
    public function Duplicate_pattern()
    {
        super();

        seedBox = new Sprite();

        seedBox.x = 80;
        seedBox.y = 20;

        addChild( seedBox );

        createButton();

        colorTimerConfig(); //타이머 이벤트 함수 호출
    }

    private var seedBox:Sprite;

    private var normalBtn:Sprite;

    private var alphaBtn:Sprite;

    private var scaleBtn:Sprite;

    private var colorBtn:Sprite;

    private var row:int = 8;

    private var col:int = 10;

    private var tot:int = row * col;

    private var gap:Numer = 30;

    /**
     *   @private
     *   랜덤컬러로 나오는 함수에 타이머 이벤트 등록
     */
    private function colorTimerConfig() : void
    {
        var timer:Timer = new Timer( 400, 10 ); //400/1000초, 10번 Timer객체 생성

        timer.start(); //타이머 시작

        timer.addEventListener( TimerEvent.TIMER, createColor ); //timer객체에 이벤트 등록
    }

    private function createButton() : void
    {
        var g:Graphics;

        if( !normalBtn )
        {
            normalBtn = new Sprite();

            g = normalBtn.graphics;

            g.clear();
            g.beginFill( 0xFFFFFF, 1 );
            g.drawRect( 0, 0, 50, 20 );
            g.endFill();

            normalBtn.x = 20;
            normalBtn.y = 20;

            normal.buttonMode = true;

           addChild( normalBtn );

           configListener( normalBtn );
        }

        if( !alphaBtn )
        {
            alphaBtn = new Sprite();

            g = alphaBtn.graphics;

            g.clear();
            g.beginFill( 0xFFFFFF, 1 );
            g.drawRect( 0, 0, 50, 20 );
            g.endFill();

            alphaBtn.x = 20;
            alphaBtn.y = normalBtn.y + gap;

            alphaBtn.buttonMode = true;

           addChild( alphaBtn );

           configListener( alphaBtn );
        }

        if( !scaleBtn )
        {
            scaleBtn = new Sprite();

            g = scaleBtn.graphics;

            g.clear();
            g.beginFill( 0xFFFFFF, 1 );
            g.drawRect( 0, 0, 50, 20 );
            g.endFill();

            scaleBtn.x = 20;
            scaleBtn.y = alphaBtn.y + gap;

            scaleBtn.buttonMode = true;

           addChild( scaleBtn );

           configListener( scaleBtn );
        }

        if( !colorBtn )
        {
            colorBtn = new Sprite();

            g = colorBtn.graphics;

            g.clear();
            g.beginFill( 0xFFFFFF, 1 );
            g.drawRect( 0, 0, 50, 20 );
            g.endFill();

            colorBtn.x = 20;
            colorBtn.y = scaleBtn.y + gap;

            colorBtn.buttonMode = true;

           addChild( colorBtn );

           configListener( colorBtn );
        }
    }

    private function configListener( dispatcher:IEventDispatcher ) : void
    {
        dispatcher.addEventListener( MouseEvent.CLICK, btnClickHandler );
    }

    private function btnClickHandler( e:MouseEvent ) : void
    {
        switch( e.target )
        {
            case normalBtn :
                createNormal();
                break;

            case alphaBtn :
                createAlpha();
                break;

            case scaleBtn :
                createScale();
                break;

            case colorBtn :
                createColor(e); //TimerEvent매개변수를 createColor함수에 넘김
                break;
        }
    }

    private function removeAllChild() : void
    {
        while( seedBox.numChildren )
        {
            seedBox.removeChildAt( 0 );
        }
        removeEventListener( TimerEvent.TIMER, createColor ); //버튼을 클릭할때마다 TimerEvent 제거
    }

    private function createNormal() : void
    {
        removeAllChild();

        var i:int = 0;

        for( i = 0; i < tot; i++ )
        {
            var temp:Sprite = new Seed();

            temp.x = ( i % col ) * 40 + gap;
            temp.y = Math.floor( i / col ) * 40 + gap;

            seedBox.addChild( temp );
        }
    }

    private function createAlpha() : void
    {
        removeAllChild();

        var i:int = 0;

        for( i = 0; i < tot; i++ )
        {
            var temp:Sprite = new Seed();

            temp.x = ( i % col ) * 40 + gap;
            temp.y = Math.floor( i / col ) * 40 + gap;

            temp.alpha = i / tot;

            seedBox.addChild( temp );
        }
    }

    private function createScale() : void
    {
        removeAllChild();

        var i:int = 0;

        for( i = 0; i < tot; i++ )
        {
            var temp:Sprite = new Seed();

            temp.x = ( i % col ) * 40 + gap;
            temp.y = Math.floor( i / col ) * 40 + gap;

            temp.scaleX = temp.scaleY = i / tot;
         
            seedBox.addChild( temp );
        }
    }

    private function createColor() : void
    {
        removeAllChild();

        var i:int = 0;

        for( i = 0; i < tot; i++ )
        {
            var temp:Sprite = new Seed();

            temp.x = ( i % col ) * 40 + gap;
            temp.y = Math.floor( i / col ) * 40 + gap;

            var ct:ColorTransform = new ColorTransform();
           
            ct.color = Math.random() * 0xFFFFFFFF;

            temp.transform.colorTransform = ct;

            seedBox.addChild( temp );
        }
    }
}
}
[/code]

- TimerEvent를 걸어준 부분은 앞 예제와 동일하고, TimerEvent를 추가하여 생성자에서 타이머 객체가 있는

  함수를 호출한다. 그래서 바로 0.4초마다 createColor함수를 10번 호출한다.

 

2010년 4월 1일 목요일

Duplicate - particle

 

- particle은 아주 작은 조각을 의미하는 것으로 seed를 마치 조각처럼 사용하여 또다른 복제를 표현.

 

 

 

[code as3]
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;

public class Duplicate_particle extends Sprite
{
    public function Duplicate_particle()
    {
        super();

        config();
    }

    /**
     *   @private
     *   fps 변경 및 이벤트 등록
     */
    private function config() : void
    {
        stage.frameRate = 48; //1초당 프레임 속도를 48로 변경

        stage.addEventListener( MouseEvent.MOUSE_DOWN, downHandler );
        stage.addEventListener( MouseEvent.MOUSE_UP, upHandler );
    }

    /**
     *   @private
     *   마우스 DOWN시, EnterFrame 이벤트 등록
     */
    private function downHandler( e:MouseEvent ) : void
    {
        stage.addEventListener( Event.ENTER_FRAME, particle );
    }

    /**
     *   @private
     *   마우스 UP시, EnterFrame 이벤트 제거
     */
    private function upHandler( e:MouseEvent ) : void
    {
        stage.removeEventListener( Event.ENTER_FRAME, particle );
    }

    /**
     *   @particle
     *   마우스 x, y좌표를 객체에 대입
     */
    private function particle( e:Event ) : void
    {
        var temp:Sprite = new Seed(); //Sprite 객체 생성

        temp.x = mouseX; //현재 마우스의 x좌표를 생성한 객체의 x좌표에 대입.
        temp.y = mouseY; //현재 마우스의 y좌표를 생성한 객체의 y좌표에 대입.

        temp.alpha = Math.random(); //alpha값은 0~1사이 랜덤값
       
        temp.scaleX = temp.scaleY = Math.random() * 3; //temp의 크기는 0~3사이 랜덤값

        addChild( temp ); //화면에 표시객체를 붙여줌
    }
}
}
[/code]

 

- 앞에서 했던 예제중에 버튼을 누르면 크기와 알파값이 랜덤으로 조정되어져 찍히는 것과 같은 결과이지만,

  사용자가 마우스를 클릭하는 순간 그 위치에서만 생기는게 다른점이다.

  따라서 복제하는 방식은 같고 단지 Sprite객체로 생성해준 temp의 x와 y좌표에 현재 클릭상태로 움직여지고

  있는 stage상에서의 x와 y 좌표를 EnterFrame이벤트가 발생할 때마다 넣어주는 것이다.

  여기서 스치고 지나갈뻔한 소스는 43번째줄에 upHandler함수에서의 removeEventListener() 이다.

  통상 addEventListener만 해보았지 등록한 이벤트를 제거한적은 없었던 것 같다.

  이 메서드 역시 addEventListener()메서드 처럼 EventDispatcher클래스에 의해서 정의 되어져 있다.

  등록되어있던 것을 제거해주는 것이므로 매개변수도 등록했던 것을 지우려는 것과 동일한 조건으로 써준다

 

 만약 일치하지 않는다면 이 메서드를 호출해도 아무 영향도 없기 때문이다.