Dead Code Preservation :: Archived AS3 works from wonderfl.net

Button HitArea Demo

ボタンのヒット領域を設定する色々な方法

第一回東京ひよこの会( http://www.project-nya.jp/modules/weblog/details.php?blog_id=1350 )にて発表したデモをまとめたもの
btn2とbtn4はチェックボックスをOFFにすることで期待通りの動作をします
各ボタンの詳しい説明はソースコードのコメントに記述しています

ブログ記事 http://blog.alumican.net/2011/03/07_013518
/**
 * Copyright alumican_net ( http://wonderfl.net/user/alumican_net )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lN4J
 */

/**
 * ボタンのヒット領域を設定する色々な方法
 * 
 * 第一回東京ひよこの会( http://www.project-nya.jp/modules/weblog/details.php?blog_id=1350 )にて発表したデモをまとめたもの
 * btn2とbtn4はチェックボックスをOFFにすることで期待通りの動作をします
 * 各ボタンの詳しい説明はソースコードのコメントに記述しています
 * 
 * @see http://blog.alumican.net/2011/03/07_013518
 * @author Yukiya Okuda <alumican.net>
 */
package {
    import com.bit101.components.*;
    import flash.display.*;
    import flash.geom.*;
    import flash.text.*;
    import flash.events.*;
    public class ButtonHitAreaDemo extends Sprite {
        public function ButtonHitAreaDemo():void {
            
            //----------------------------------------
            //CASE 1
            //ボタンを生成する場合, もっとも単純な方法はボタン自身に直接イベントハンドラを登録すればよい.
            //しかし, ボタンの形状とは異なるボタンヒット領域を設定する場合, この方法では対応できない.
            
            //ボタンSpriteを生成する
            var btn1:Sprite = addBox(Sprite, this, "root.btn1", posX, posY) as Sprite;
            
            //ボタンSpriteにMouseEventハンドラを登録する
            addAction(btn1);
            
            
            //----------------------------------------
            //CASE 2
            //SpriteのhitAreaプロパティを設定すると, ボタン自身に直接イベントハンドラを登録しつつ
            //ボタンの形状とは独立したボタンヒット領域を設けることができる.
            
            //ボタンSpriteを生成する
            var btn2:Sprite = addBox(Sprite, this, "root.btn2", posX, posY += margin) as Sprite;
            
            //ヒット領域Spriteを, ボタンSpriteと同階層に生成する
            var btn2Area:Sprite = addBox(Sprite, this, "root.area2", posX + 120, btn2.y) as Sprite;
            
            //ボタンSpriteのヒット領域を設定する
            btn2.hitArea = btn2Area;
            
            //【重要】hitAreaを設定した場合は, ヒット領域SpriteのmouseEnabledをfalseにする.
            //これをしないとボタンSpriteに代わってヒット領域Sprite自身がマウスイベントを
            //受け取ってしまい, 正常に動作しなくなる.
            
            //このコメントを外すと期待通りに動くようになる
            //btn2Area.mouseEnabled = false;
            
            //ボタンSpriteにMouseEventハンドラを登録する
            addAction(btn2);
            
            
            //----------------------------------------
            //CASE 3
            //前述の例ではボタンと同階層にヒット領域を生成したが, ボタンの子階層にヒット領域があったほうが便利なので.
            //この例ではボタンの子としてヒット領域と子Shapeを作る.
            
            //ボタンSpriteを生成する
            var btn3:Sprite = addContainer(this, "btn3", posX, posY += margin);
            
            //ヒット領域Spriteを, ボタンSpriteの子として生成する
            var btn3Area:Sprite = addBox(Sprite, btn3, "btn3.area", 120, 0) as Sprite;
            
            //Shapeを, ボタンSpriteの子として生成する
            var btn3Shape:Shape = addBox(Shape , btn3, "btn3.shape", 0, 0) as Shape;
            
            //ボタンSpriteのヒット領域を設定する
            btn3.hitArea = btn3Area;
            
            //ボタンSpriteにMouseEventハンドラを登録する
            addAction(btn3, btn3Shape);
            
            
            //----------------------------------------
            //CASE 4
            //ボタンの子としてヒット領域と子Spriteを生成してみる.
            //すると前回はうまくいっていたのに, Spriteにもボタンが反応するようになってしまった.
            
            //ボタンSpriteを生成する
            var btn4:Sprite = addContainer(this, "btn4", posX, posY += margin);
            
            //ヒット領域Spriteを, ボタンSpriteの子として生成する
            var btn4Area:Sprite = addBox(Sprite, btn4, "btn4.area", 120, 0) as Sprite;
            
            //Spriteを, ボタンSpriteの子として生成する
            var btn4Sprite:Sprite = addBox(Sprite, btn4, "btn4.sprite", 0, 0) as Sprite;
            
            //ボタンSpriteのヒット領域を設定する
            btn4.hitArea = btn4Area;
            
            //【重要】ボタンSpriteの子としてSpriteやMovieClipなどのInteractiveObjectが存在する場合, 
            //ボタンSpriteのmouseChildrenをfalseにする.
            //これをしないとhitAreaで設定したSprite以外のInteractiveObjectにもボタンが反応してしまう.
            //子Spriteとヒット領域Spriteそれぞれを個別にmouseEnabled=falseしてもいいけど,
            //面倒なので一括mouseChildren=falseがおすすめ
            
            //このコメントを外すと期待通りに動くようになる
            //btn4.mouseChildren = false;
            
            //ボタンSpriteにMouseEventハンドラを登録する
            addAction(btn4, btn4Sprite);
            
            
            //----------------------------------------
            //CASE 5
            //hitAreaプロパティを使わない場合, この方法でボタンを管理している人が多いのでは?
            
            //ボタンSpriteを生成する
            var btn5:Sprite = addContainer(this, "btn5", posX, posY += margin);
            
            //Spriteを, ボタンSpriteの子として生成する
            var btn5Sprite:Sprite = addBox(Sprite, btn5, "btn5.sprite", 0  , 0) as Sprite;
            
            //ヒット領域Spriteを, ボタンSpriteの子として生成する
            var btn5Area:Sprite = addBox(Sprite, btn5, "btn5.area", 120, 0) as Sprite;
            
            //ヒット領域SpriteにMouseEventハンドラを登録する
            addAction(btn5Area, btn5Sprite);
            
             
            //----------------------------------------
            addTitle();
            addCheckBox(btn2, "btn2.area.mouseEnabled", btn2Area, "mouseEnabled");
            addCheckBox(btn4, "btn4.mouseChildren", btn4, "mouseChildren");
        }
       
        private function addAction(area:Sprite, view:* = null):void {
            if (view == null) view = area;
            area.buttonMode = true;
            area.addEventListener(MouseEvent.ROLL_OVER, function(e:MouseEvent):void {
                fillBox(view.graphics, 0x666666);
            });
            area.addEventListener(MouseEvent.ROLL_OUT, function(e:MouseEvent):void {
                fillBox(view.graphics, 0x000000);
            });
            area.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
        }
 
        private function addContainer(parent:Sprite, label:String, x:int, y:int):Sprite {
            var s:Sprite = parent.addChild(new Sprite()) as Sprite;
            s.x = x;
            s.y = y;
            var g:Graphics = s.graphics;
            g.clear();
            g.beginFill(0xcccccc);
            g.drawRect(-60, -10, 290, 60);
            g.endFill();
            addLabel(label, x - 48, y, 0x000000);
            return s;
        }
        
        private function addBox(type:Class, parent:Sprite, label:String, x:int, y:int):* {
            var o:* = parent.addChild(new type());
            o.x = x;
            o.y = y;
            var isArea:Boolean = label.indexOf("area") != -1;
            fillBox(o.graphics, isArea ? 0xffff00 : 0x000000);
            var p:Point = parent.localToGlobal(new Point(x, y));
            var tf:TextField = addLabel(label, p.x, p.y, isArea ? 0x000000 : 0xffffff);
            tf.width = o.width;
            return o;
        }
        
        private function addLabel(text:String, x:int, y:int, color:uint):TextField {
            var fmt:TextFormat = new TextFormat("Arial", 15, color, true);
            var tf:TextField = addChild(new TextField()) as TextField;
            tf.defaultTextFormat = fmt;
            tf.autoSize = TextFieldAutoSize.CENTER;
            tf.text = text;
            tf.x = x;
            tf.y = y + 9;
            tf.mouseEnabled = false;
            return tf;
        }
      
        private function fillBox(g:Graphics, color:uint):void {
            g.clear();
            g.beginFill(color);
            g.drawRect(0, 0, 100, 40);
            g.endFill();
        }
        
        private function addCheckBox(btn:Sprite, label:String, target:Sprite, property:String):void {
            var cb:CheckBox = new CheckBox(this, 15, btn.y + (40 - 10) / 2, label, function(e:Event):void {
                target[property] = CheckBox(e.target).selected;
            });
            cb.selected = target[property];
        }
            
        private function addTitle():void {
            var fmt:TextFormat = new TextFormat("Arial", 14, 0x333333, true);
            var tf:TextField = addChild(new TextField()) as TextField;
            tf.defaultTextFormat = fmt;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.text = "Button HitArea Demo\nevent: tokyopiyo #1\ndate: 2011.3.4\nauthor: alumican.net";
            tf.x = 7;
            tf.y = 5;
            tf.mouseEnabled = false;
            fmt.size = 13;
            fmt.color = 0x999999;
            tf.setTextFormat(fmt, tf.text.indexOf("event:"), tf.text.length);
        }
        
        private var margin:int = 80;
        private var posX:int   = 210;
        private var posY:int   = 60;
    }
}