태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.
밤하늘의 실제별, 나도 가질 수 있다?!

[Flex] 회전하는 컴포넌트 위에 글자가 사라지지 않게 하는 방법

2007/08/08 23:53

 

[공지]이미지나 링크가 깨졌다면 댓글 부탁드립니다.

사용자 삽입 이미지

Flex에서 Button(mx.controls.Button)을 다루다 보면 버튼을 임의의 각도로 회전시키고 싶은 경우가 있다. ( 굳이 Button뿐 아니라 Label, TextField와 같은 컴포넌트도 모두 마찬가지이다.)
하지만 Button의 속성값인 rotation이 0이 아닌 순간 버튼안에 글자가 사라져버린다.
영어든, 한글이든 마찬가지이다. 버튼은 내부적으로 글자를 UITextField를 addChild해서 사용하는데...
회전만 했다하면 UITextField에 label 글자 내용은 있으나 View상에서는 사라진다.

의외로 이러한 부분에 많이 어려워하시는 분들이 계셔서 도와드리는 차원에서 간단하게 컴포넌트를 만들었다.
사실 나도 Flex를 초반에 공부할 때, 이것때문에 꽤나 고생한 기억이 있다. ^^;

이 문제를 해결하기 위해서 크게 2가지 해결방법이 있다.

  1. 실제 폰트를 Embed 하는 방법 (SWF용량이 늘어나는 단점이 있음)
    나는 예전에 관련 글을 작성했었다.
    http://blog.jidolstar.com/101 를 참고한다.

  2. Bitmap 을 이용하는 방법(Bitmap이라 회전하면 약간 일그러지는 단점 있음)

여기서 언급하는 방법은 바로 bitmap을 이용하는 방법이다.
아래는 실행 결과이다.

기본적으로 Button을 상속받아 사용했고 label과 rotation을 override시켜서 기능을 확장했다.
확장된 함수는 label과 rotation값이 바뀔 때마다 rotation된 label Bitmap을 만들어준다.

상속받은 Class는 RotationButton이라고 명명했다.


RotationButton.as (Language : java)
package
{
    import mx.controls.Button;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.AntiAliasType;
    import flash.text.TextFormat;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import mx.core.UITextField;
    import mx.events.FlexEvent;
    import flash.events.MouseEvent;

    public class RotationButton extends Button
    {
        public function RotationButton()
        {
            super();
            this.addEventListener( FlexEvent.CREATION_COMPLETE, onInit );
        }
       
        private function onInit( event:FlexEvent ):void
        {
            this.label = super.label;
        }
       
        override public function set label(value:String):void
        {
            super.label = value;
            setRotationLabel();
        }
       
        override public function set rotation(value:Number):void
        {
            super.rotation = value;
            setRotationLabel();
        }
       
        private function setRotationLabel():void
        {
            var tf:UITextField = super.textField;
            if( null == tf ) return;

            var bmp:Bitmap;
            bmp = Bitmap( this.getChildByName( "bitmapLabel" ) );
            if( null != bmp)
            {
                bmp.bitmapData.dispose();
                this.removeChild( bmp );
            }         
            var bmpData:BitmapData = new BitmapData( tf.width, tf.height, true, 0x00CCCCCC );
            bmpData.draw( tf );
           
            bmp = new Bitmap( bmpData, "auto", false );
            bmp.smoothing = true;
            bmp.name = "bitmapLabel";
            bmp.x = this.width/2 - tf.width/2;
            bmp.y = this.height/2 - tf.height/2;
            this.addChild( bmp );
        }
    }
}



아래 소스는 RotationButton을 활용한 예제이다.


RotationButtonTest.mxml (Language : xml)
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" creationComplete="startTimer()">
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import flash.utils.Timer;
            import flash.events.TimerEvent;

            public var r1:int = 0;
            public var r2:int = 50;
            public function startTimer():void
            {
                var timer:Timer = new Timer( 300, 0 );
                timer.delay = 100;
                timer.start();
                timer.addEventListener( TimerEvent.TIMER, onTick );
            }
           
            private function onTick( event:TimerEvent ):void
            {
                r1 += 4;
                r2 -= 6;
                if( r1 >= 360 ) r1 = 0;
                else if( r1 < 0) r1 = 359;
                if( r2 >= 360 ) r2 = 0;
                else if( r2 < 0) r2 = 359;
                rotationButton1.rotation = r1;
                rotationButton2.rotation = r2;
            }
        ]]>

    </mx:Script>
    <local:RotationButton id="rotationButton1"
        width="121" height="42" x="54.5" y="67"
        label="Hello Flex" 
        rotation="0"
        color="#ff0000" fontSize="12" fontFamily="굴림"
        click="mx.controls.Alert.show('1번 누름')"/>

    <local:RotationButton id="rotationButton2"
        width="121" height="42" x="100.5" y="175"
        label="안녕~ 플렉스"
        rotation="0" color="#ff00ff" fontSize="14" fontFamily="궁서"
        click="mx.controls.Alert.show('2번 누름')"/>

    <local:RotationButton id="rotationButton3"
        width="175" height="42" x="265" y="49"
        label="버튼에 마우스 올리면  이상해"
        rotation="355" color="#0000ff" fontSize="11" fontFamily="돋움"
        click="mx.controls.Alert.show('3번 누름')"/>

    <local:RotationButton id="rotationButton4"
        width="175" height="42" x="285" y="154"
        label="회전 0도"
        rotation="0" color="#0ffff" fontSize="12" fontFamily="돋움"
        click="mx.controls.Alert.show('3번 누름')"/>

</mx:Application>
 


회전이 된 버튼에 마우스가 올라가면 글자가 흐릿해지는데 왜 그런지는 아직 알 수 없었다.
혹시라도 이유를 안다면 함께 공유했으면 한다.

위의 예시처럼 버튼을 상속받지 않고 나만의 버튼을 하나 만들어 보는 것은 어떨까? Button도 어짜피 UIComponent를 상속받은 것이니 말이다.

한가지 더 언급할 것은 많은 수의 Sprite나 UIComponent가 Flex위에 동적으로 움직인다면 CPU부하가 심해진다. 만약 Sprite나 UIComponent와 같은 DisplayObject들이 함께 움직이는 경우라면 위와 같은 방식으로 BitmapData 만들어 사용하는 것이 속도 개선 및 CPU사용량을 줄이는데 큰 장점이 있다. 중요한 점은 BitmapData를 사용한 후 메모리에 반환할 때 dispose()함수를 수행하도록 하여 쓸데없이 메모리를 사용하는 것을 방지하자.

글쓴이 : 지돌스타(http://blog.jidolstar.com/189)

크리에이티브 커먼즈 라이선스
Creative Commons License

Adobe Flash Platform , , , , ,

Trackback 주소: http://blog.jidolstar.com/trackback/189
  1. 2008/11/26 23:05
    텍스트 돌려보아요.. Tracked from JINHOKIM.COM
  1. ㅎㅎ 텍스트 필드를 아이템화 해서 사용자가 마음대로 크기, 각도를 컨트롤 해야했었는데 이런 방법이..
    100% 같은 방법이 아니었지만 저한테 맞게 응용했네요 ㅎㅎ
    한수 배웠습니다! ^^

  2. 정말 오래전에 Flex공부하면서 썼던 글이네요.
    이걸 보니 컴포넌트 회전시 글자가 없어지는 문제로 고민했던 적이 생각이 납니다.
    다시한번 상기 시켜주셔서 감사~ ^^

  3. Blog Icon
    jun

    블로그 잘 보고 갑니다
    위의 소스 중에..
    setRotationLabel () 메소드 안에
    var tf:UITextField = super.textField; 이 부분에서
    형변환 오류가 발생하면서 컴파일이 안되네요..?

  4. Blog Icon
    지돌스타

    이 코드가 Flex2 시절에 만든거라 소스가 약간 수정될 수 있습니다.
    디버깅을 통해 super.textField가 null이 아니고 UITextField인지 확인해보세요.