frames.frame オプションでプリローディング

http://d.hatena.ne.jp/flashrod/20070317#1174093786 ここ見てわかった。getDefinitionByName() を使うのか。ただ [Frame(...)] 使うよりは、frames.frame オプション使った方がきめこまかくやれる気がする。以下サンプル。
http://park.geocities.jp/mxmlc/misc/FramesExample.html

メインクラス(プリローダ含む)

// FramesExample.as
package
{
  import flash.display.*;
  import flash.text.*;
  import flash.events.*;
  import flash.utils.*;
  import lw.*;

  public class FramesExample extends MovieClip
  {
    private var placeHold:Sprite = new Sprite();
    private var progressBar:Sprite = new Sprite();
    private var textField:TextField = new TextField();

    public function FramesExample()
    {
      stage.align = StageAlign.TOP_LEFT;
      stage.scaleMode = StageScaleMode.NO_SCALE;

      stop();

      textField.autoSize = TextFieldAutoSize.LEFT;
      textField.defaultTextFormat = new TextFormat("_sans", 12);
      textField.background = true;

      progressBar.graphics.lineStyle(0, 0x000000);
      progressBar.graphics.beginFill(0xFFFFFF, 0.5);
      progressBar.graphics.drawRect(0, 0, 100, 4);
      progressBar.graphics.endFill();

      addChild(placeHold);
      addChild(textField);
      addChild(progressBar);

      onEnterFrame(new Event(Event.ENTER_FRAME));
      addEventListener(Event.ENTER_FRAME, onEnterFrame);

      onResize(new Event(Event.RESIZE));
      stage.addEventListener(Event.RESIZE, onResize);
    }
    private var index:int = 0;
    private var images:Array = new Array();
    private function onEnterFrame(ev:Event):void {
      textField.text = "bytes:" + root.loaderInfo.bytesLoaded + "/" + root.loaderInfo.bytesTotal
                     + " - frames:" + framesLoaded + "/" + totalFrames;
      progressBar.width = stage.stageWidth * loaderInfo.bytesLoaded / loaderInfo.bytesTotal;

      if (index + 1 < framesLoaded) {
        index++;
        nextFrame();
        var Image:Class = Class(getDefinitionByName("Image" + index));
        if (Image) {
          var bm:Bitmap = new Image();
          images.push(bm);
          removeChildAt(0);
          addChildAt(bm, 0);
        }
        onResize(new Event(Event.RESIZE));
      }
      if (index == totalFrames - 1) {
        index--;
        removeEventListener(Event.ENTER_FRAME, onEnterFrame);
        onFullLoaded();
      }
    }
    private function onResize(ev:Event):void {
      var bm:DisplayObject = getChildAt(0);
      bm.width = stage.stageWidth;
      bm.height = stage.stageHeight;
    }
    private function onFullLoaded():void {
      textField.htmlText = "<a href='event:prev'>&lt; </a><a href='event:next'> &gt;</a>"
      textField.addEventListener(TextEvent.LINK, function(ev:TextEvent):void {
        if (ev.text == "prev") {
          index = Math.max(0, index-1);
        } else {
          index = Math.min(totalFrames-2, index+1);
        }
        var bm:Bitmap = images[index];
        removeChildAt(0);
        addChildAt(bm, 0);
        onResize(new Event(Event.RESIZE));
      });
      removeChild(progressBar);
    }
  }
}

2、3、4フレームにそれぞれ画像を入れる。
FramesExample-config.xml

<flex-config>
  <default-size>
    <width>650</width>
    <height>400</height>
  </default-size>
  <default-frame-rate>30</default-frame-rate>
  <default-background-color>0xFFFFFF</default-background-color>
  <frames>
    <frame><label></label><classname>Image1</classname></frame>
    <frame><label></label><classname>Image2</classname></frame>
    <frame><label></label><classname>Image3</classname></frame>
  </frames>
</flex-config>

画像用クラス Image2,Image3 も同様に。

// Image1.as
package 
{
  import flash.display.*;
  [Embed(source="image1.jpg")]
  public class Image1 extends Bitmap { }
}
  • nextFrame() 重要。そのフレームに行かないとオブジェクト作られない。
  • firefox で url#abc とかするとうまくいかない??

TextField 上でのマウスカーソルの形

マウスカーソルの形は、ボタン上のポインタ型、テキストフィールド上のセレクション型、通常のポインタ型の3種類。
ステージ上でマウス押下そのままテキストフィールドまでドラッグしても形はポインタ型のまま。
スプライト上などでマウス押してそのままテキストフィールドに入るとセレクション型に変わる。
いったん別のスプライトを経由するとポインタ型のまま。
プレーヤのバージョンで違うのだろけど、なんだか気持ち悪い。

ドラッグの雛形

DraggableButtonTest


startDrag() は、マウスが stage から外れるとうまくいかない。
ドラッグの制限も矩形のみということで、自前でやるときの雛形。
こんな感じ。
http://park.geocities.jp/mxmlc/misc/DraggableButtonTest.html

// DraggableButton.as

package {
  import flash.display.*;
  import flash.events.*;
  import flash.geom.*;

  public class DraggableButton extends Sprite {

    private var delta:Point = new Point();
    private var a:Point = new Point();
    public var limit:Function = function(pt:Point):void {};

    public function DraggableButton(c:uint, r:Number):void {
      graphics.beginFill(c);
      graphics.drawCircle(0, 0, r);
      graphics.endFill();

      addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
    }
    private function onMouseDown(ev:MouseEvent):void {
      delta.x = x - parent.mouseX;
      delta.y = y - parent.mouseY;
      stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMove);
      stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
    }
    private function stageMouseMove(ev:MouseEvent):void {
      a.x = parent.mouseX + delta.x;
      a.y = parent.mouseY + delta.y;
      limit(a);
      x = a.x;
      y = a.y;
      dispatchEvent(new Event(Event.CHANGE));
      ev.updateAfterEvent();
    }
    private function stageMouseUp(ev:MouseEvent):void {
      stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMove);
      stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
    }
  }
}

PushButton の雛形

次のような感じだと思う。
PushButton の状態には、up, over, down ともうひとつ、ボタン押したままでボタンの枠外にマウスが外れたときの状態 (downout?) が必要。なんというかボタンごときでなんでこんなに複雑なんだろ。
http://park.geocities.jp/mxmlc/misc/PushButtonTest.html

// PushButton.as

package {
  import flash.display.*;
  import flash.text.*;
  import flash.events.*;

  public class PushButton extends Sprite {

    private var _state:int;
    private static const UP:int = 0;
    private static const OVER:int = 1;
    private static const DOWN:int = 2;
    private static const DOWNOUT:int = 3;

    public function PushButton():void {
      graphics.beginFill(0xFF8888, 1.0);
      graphics.drawRoundRect(0, 0, 100, 20, 4,4);
      graphics.endFill();

      state = UP;
      addEventListener(MouseEvent.ROLL_OVER, onRollOver);
      addEventListener(MouseEvent.ROLL_OUT, onRollOut);
      addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
    }
    private function onMouseDown(ev:MouseEvent):void {
      state = DOWN;
    }
    private function stageMouseUp(ev:MouseEvent):void {
      if (state == DOWNOUT) {
        stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
      }
      state = UP;
    }
    private function onMouseUp(ev:MouseEvent):void {
      state = OVER;
    }
    private function onRollOver(ev:MouseEvent):void {
      if (ev.buttonDown) {
        if (state == DOWNOUT) {
          state = DOWN;
          stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
        } else {
          state = UP;
        }
      } else {
        state = OVER;
      }
    }
    private function onRollOut(ev:MouseEvent):void {
      if (state == DOWN) {
        state = DOWNOUT;
        stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp);
      } else {
        state = UP;
      }
    }

    private function set state(val:int):void {

      import flash.filters.*;
      var gf_up:Array = [new GlowFilter(0x888888, 0.3, 1,1, 3)];
      var gf_over:Array = [new GlowFilter(0x888888, 0.3, 4,4, 6)];
      var gf_down:Array = [new GlowFilter(0xFF0000, 0.5, 8,8, 2)];
      var gf_downout:Array = [new GlowFilter(0xFF0000, 0.5, 4,4, 2)];
      _state = val;
      switch (val) {
        case UP:
          filters = gf_up;
          break;
        case OVER:
            filters = gf_over;
          break;
        case DOWN:
            filters = gf_down;
          break;
        case DOWNOUT:
            filters = gf_downout;
          break;
      }
    }
    private function get state():int { return _state; }
  }
}

mouseover と rollover の違い

MouseEventTest

を理解しようとテストswfを作ってみた。
http://park.geocities.jp/mxmlc/misc/MouseEventTest.html

// MouseEventTest.as

package {
  import flash.display.*;
  import flash.events.*;
  import flash.text.*;


  public class MouseEventTest extends Sprite {
    private var tf:TextField;
    private var sp1:Sprite;
    private var sp2:Sprite;

    function MouseEventTest():void {
      stage.align = StageAlign.TOP_LEFT;
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.addEventListener(Event.RESIZE, function (ev:Event):void {
        tf.height = stage.stageHeight;
        tf.width = stage.stageWidth;
        tf.scrollV = tf.maxScrollV;
      });

      tf = new TextField();
      tf.defaultTextFormat = new TextFormat("_sans", 12, 0);
      tf.mouseEnabled = false;
      tf.multiline = true;
      tf.width = stage.stageWidth;
      tf.height = stage.stageHeight;
      addChild(tf);

      sp1 = new Sprite();
      sp1.graphics.lineStyle(5, 0);
      sp1.graphics.beginFill(0x008800, 1.0);
      sp1.graphics.drawRoundRect(360, 30, 200, 200, 10,10);
      sp1.graphics.endFill();
      sp1.name = "Parent";
      addChild(sp1);

      sp2 = new Sprite();
      sp2.graphics.lineStyle(5, 0);
      sp2.graphics.beginFill(0x004400, 1.0);
      sp2.graphics.drawRoundRect(420, 80, 150, 100, 5,5);
      sp2.graphics.endFill();
      sp2.name = "Child";
      sp1.addChild(sp2);

      sp1.addEventListener(MouseEvent.MOUSE_OVER, onSpriteEvent);
      sp1.addEventListener(MouseEvent.MOUSE_OUT, onSpriteEvent);
      sp1.addEventListener(MouseEvent.ROLL_OVER, onSpriteEvent);
      sp1.addEventListener(MouseEvent.ROLL_OUT, onSpriteEvent);
      sp1.addEventListener(MouseEvent.MOUSE_UP, onSpriteEvent);
      sp1.addEventListener(MouseEvent.MOUSE_DOWN, onSpriteEvent);
      sp1.addEventListener(MouseEvent.CLICK, onSpriteEvent);
      // sp1.addEventListener(MouseEvent.DOUBLE_CLICK, onSpriteEvent);
      // sp1.addEventListener(MouseEvent.MOUSE_WHEEL, onSpriteEvent);
      // sp1.addEventListener(MouseEvent.MOUSE_MOVE, onSpriteEvent);

      sp2.addEventListener(MouseEvent.MOUSE_OVER, onSpriteEvent);
      sp2.addEventListener(MouseEvent.MOUSE_OUT, onSpriteEvent);
      sp2.addEventListener(MouseEvent.ROLL_OVER, onSpriteEvent);
      sp2.addEventListener(MouseEvent.ROLL_OUT, onSpriteEvent);
      sp2.addEventListener(MouseEvent.MOUSE_UP, onSpriteEvent);
      sp2.addEventListener(MouseEvent.MOUSE_DOWN, onSpriteEvent);
      sp2.addEventListener(MouseEvent.CLICK, onSpriteEvent);
      // sp2.addEventListener(MouseEvent.DOUBLE_CLICK, onSpriteEvent);
      // sp2.addEventListener(MouseEvent.MOUSE_WHEEL, onSpriteEvent);
      // sp2.addEventListener(MouseEvent.MOUSE_MOVE, onSpriteEvent);

      stage.addEventListener(Event.MOUSE_LEAVE, onLeaveEvent);
      stage.addEventListener(MouseEvent.MOUSE_OVER, onStageEvent);
      stage.addEventListener(MouseEvent.MOUSE_OUT, onStageEvent);
      stage.addEventListener(MouseEvent.ROLL_OVER, onStageEvent);
      stage.addEventListener(MouseEvent.ROLL_OUT, onStageEvent);
      stage.addEventListener(MouseEvent.MOUSE_UP, onStageEvent);
      stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageEvent);
      stage.addEventListener(MouseEvent.CLICK, onStageEvent);
      // stage.addEventListener(MouseEvent.DOUBLE_CLICK, onStageEvent);
      // stage.addEventListener(MouseEvent.MOUSE_WHEEL, onStageEvent);
      // stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageEvent);
    }

    private function onSpriteEvent(ev:MouseEvent):void {
      tf.appendText("\n[SPRITE] " + getName(ev.target)
        + " - " + getName(ev.currentTarget)
        + " - " + ev.type);
      tf.scrollV = tf.maxScrollV;
    }
    private function onStageEvent(ev:MouseEvent):void {
      tf.appendText("\n[STAGE] " + getName(ev.target)
        + " - " + getName(ev.currentTarget)
        + " - " + ev.type);
      tf.scrollV = tf.maxScrollV;
    }
    private function onLeaveEvent(ev:Event):void {
      tf.appendText("\n[LEAVE] " + getName(ev.target)
        + " - " + getName(ev.currentTarget)
        + " - " + ev.type);
      tf.scrollV = tf.maxScrollV;
    }
    private function getName(target:Object):String {
      if (target == stage) return "stage";
      else return target.name;
    }
  }
}

よくわからん。
極力 mouseEnabled = false; mouseChildren = false; にしたほうが楽なのか。