2007年8月27日 星期一

利用 SharedEvents 作部分 Cross-Domain Scripting   [+/-]

Ticore's Blog

ActionScript 可以利用 allowDomain 解除 Cross-Domain Scripting 限制
但是這樣全開全關的方式在很多情況下不太合適
在 AS3 LoaderInfo.sharedEvents 可以在不開放 Cross-Domain Scripting 限制下
互相發送事件,以下是簡單的測試程式

http://www.dom1.com/SharedEvents/main.swf class:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  public var ldr:Loader = new Loader();
  public var req:URLRequest = new URLRequest("http://www.dom2.com/SharedEvents/module.swf");
   
  public function main ():*{
   ldr.contentLoaderInfo.sharedEvents.addEventListener("MODULE_EVENT", onEvent);
   ldr.contentLoaderInfo.addEventListener(Event.INIT, onInit);
   ldr.load(req);
  }
  
  public function onInit(evtObj:Event):*{
   ldr.contentLoaderInfo.sharedEvents.dispatchEvent(new evt("MAIN_EVENT", true, true, new Obj()));
  }
  
  public function onEvent(evtObj:*):*{
   trace(evtObj.data.type); // Module Obj
   trace(evtObj.data == Obj); // false
   trace(describeType(evtObj.data.constructor) == describeType(Obj)); // true
  }
  
 }
}

class Obj {
 public var type:String = "Main Obj";
}
// Ticore's Blog - http://ticore.blogspot.com/

http://www.dom2.com/SharedEvents/module.swf class:

package {
 import flash.display.*;
 import flash.events.*;
 
 public class module extends MovieClip {
  
  public function module ():*{
   this.loaderInfo.sharedEvents.addEventListener("MAIN_EVENT", onEvent);
   this.loaderInfo.sharedEvents.dispatchEvent(new evt("MODULE_EVENT", true, true, new Obj()));
  }
  
  public function onEvent(evtObj:*):*{
   trace(evtObj.data.type); // Main Obj
  }
  
 }
}

class Obj {
 public var type:String = "Module Obj";
}

evt class:

package {
 import flash.events.*;
 public class evt extends Event {
  
  public var data:*;
  
  public function evt (type:String, bubble:Boolean = true, cancelable:Boolean = true, data:* = null):*{
   super(type, bubble, cancelable);
   this.data = data;
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

由測試結果可以發現透過 SharedEvents 不但可以自由傳送事件
還可以偷渡物件,並且呼叫物件成員
再進一步測試,除了 Stage、Document Class 會出現安全性警告之外
其它的物件都可以透過 SharedEvents 傳遞
看起來 Flash Player Cross-Scripting 限制主要是建立在 Stage、Document Class 之上
畢竟這是直接存取必經門戶~

Read more...

2007年8月26日 星期日

利用 static 區塊建立額外 Document Class 實體   [+/-]

Ticore's Blog

ActionScript 3.0 的 Document Class 在正常情況下是無法建立額外的實體
意思就是除了 SWF 載入時自動建立的實體
完全不能對 Document Class 呼叫 "new"
否則會出現 Error 訊息

TypeError: Error #1007: 嘗試個體化非建構函式。

假如該 Document Class 是由 Loader 從外部載入
甚至還會造成 Flash Player Crash

不過可以在 static 初始階段產生額外 Document Class 實體
以下是測試程式:

package {
 import flash.display.*;
 
 public class main extends MovieClip {
  
  public static var mainInsAry:Array =
   [new main(), new main(), new main()];
   
  public function main ():*{
   new main();
   if (mainInsAry != null) {
    init();
   }
  }
  
  public function init ():*{
   
   trace(mainInsAry[0].loaderInfo);  // null
   trace(mainInsAry[0].stage);       // null
   trace(mainInsAry[0].root);        // null
   trace(mainInsAry[0].parent);      // null
   
   trace(mainInsAry[0].totalFrames); // always 1
   trace(this.totalFrames);          // 8
   
   mainInsAry[0].fun();  // [object main]
   this.fun();           // [object main]
  }
  
  public function fun ():*{
   trace(this);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

由測試結果可以發現,額外產生的實體不具有真正 Document Class 特性
甚至連 Timeline 都不見了
只剩下一般 Class 特性與方法
好像是漩渦鳴人變出來的影分身喔~~

相關連結:
RSL Document Class 實體化造成 Player Crash Bug
AS3 Document Class 實體化怪異現象
Flex Embed 外部資源技巧

Read more...

AS3 DisplayObject 四大變動屬性   [+/-]

Ticore's Blog

DisplayObject 四大變動屬性指的是 stage、parent、root、loaderInfo
這些物件本身的屬性會隨著相對物件變動而變
常常會令人難以捉摸~

依據這些屬性變動行為,DisplayObject 又可以分為三類:

  • Stage
  • Document Class
  • Other DisplayObject

以下則是相關屬性與行為對照表:

  Stage Document Class Other DisplayObject Class
stage 總是得到 stage 只要該物件有被加入 stage dom tree 之下,便可經由 stage 屬性取得 Stage,否則為 null 只要該物件有被加入 Stage dom tree 之下,便可經由 stage 屬性取得 stage,否則為 null
parent 總是得到 null 只要該物件有被加入 DisplayObjectContainer 之下,便可經由 prent 屬性取得 DisplayObjectContainer,否則為 null 只要該物件有被加入 DisplayObjectContainer 之下,便可經由 prent 屬性取得 DisplayObjectContainer,否則為 null
root 總是得到 stage 總是得到自己本身 會得到最接近 parent document class or stage,否則為 null
loaderInfo 總是得到不完整功能的實體 可以得到實體,但是不會隨著相對物件變動 會得到最接近 parent document class or stage loaderInfo,否則為 null

以上的特性可以很容易被驗證
由於相當繁瑣,僅對 Document Class 與非 Document Class 的 root 變動性作一個示範

main class:

package {
 import flash.display.*;
 import flash.net.*;

 public class main extends MovieClip {
  var modURL:String = "module.swf";
  var ldr:Loader = new Loader();
  var req:URLRequest = new URLRequest(modURL);

  public function main():* {
   ldr.load(req);
   this.addChild(ldr);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

module class:

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

 public class module extends MovieClip {
  public function module():* {
   this.addEventListener(Event.ADDED_TO_STAGE, onAddStage);
  }
  public function onAddStage(evtObj:Event):* {

   this.removeEventListener(Event.ADDED_TO_STAGE, onAddStage);
   
   var mc:MovieClip = new MovieClip();
   mc.name = "mc";

   trace(mc.root);  // null
   this.addChild(mc);
   trace(mc.root);  // [object module]
   parent.parent.addChild(mc);
   trace(mc.root);  // [object main]

   trace(this.root);  // [object module]
   parent.parent.addChild(this);
   trace(this.root);  // [object module]
   
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
AS3 時間軸預置圖像物件的特性

Read more...

AS3 Cross-Domain Event Flow   [+/-]

Ticore's Blog

ActionScript 3.0 的 Event Flow 都是由 stage -> document class -> ... 下來
假如遇到 Loader 與 Corss-Domain Flash Movie 會怎樣呢?
以下測試看看~~

以下建立兩個 document class,放在不同的 domain 下測試
儘可能在所有位置監聽 MouseDown 事件
分別觀察允許與不允許 Corss-Domain 情況下的 Event Flow

http://www.dom1.com/main.swf class:

package {
 import flash.display.*;
 import flash.events.*;
 import flash.net.*;
 import flash.system.*;

 public class main extends MovieClip {

  var modURL:String = "http://www.dom2.com/module.swf";
  var ldr:Loader = new Loader();
  var req:URLRequest = new URLRequest(modURL);

  public function main():* {

   Security.allowDomain("www.dom2.com");
   
   initEvent(stage);
   initEvent(this);
   initEvent(ldr);
   
   this.addChild(ldr);
   ldr.load(req);
   
  }
  public function initEvent(obj:*):* {
   
   obj.addEventListener(MouseEvent.MOUSE_DOWN, onHandler, false);
   obj.addEventListener(MouseEvent.MOUSE_DOWN, onHandler, true);
   
  }
  public function onHandler(evtObj:MouseEvent):* {

   trace("eventPhase : " + evtObj.eventPhase + ", type : " + evtObj.type +
     ", currentTarget : " + evtObj.currentTarget + ", target : " + evtObj.target);

  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

http://www.dom2.com/module.swf class:

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

 public class module extends MovieClip {

  public function module():* {

   Security.allowDomain("www.dom1.com");
   this.addEventListener(Event.ADDED_TO_STAGE, onAddStage);

  }
  public function onAddStage(evtObj:Event):* {

   var mc:MovieClip = new MovieClip();
   mc.x = 100;
   mc.y = 50;
   drawRect(mc.graphics);
   this.addChild(mc);
   
   initEvent(this);
   initEvent(mc);

  }
  public function initEvent(obj:*):* {
   
   obj.addEventListener(MouseEvent.MOUSE_DOWN, onHandler, false);
   obj.addEventListener(MouseEvent.MOUSE_DOWN, onHandler, true);
   
  }
  public function onHandler(evtObj:MouseEvent):* {

   trace("eventPhase : " + evtObj.eventPhase + ", type : " + evtObj.type +
     ", currentTarget : " + evtObj.currentTarget + ", target : " + evtObj.target);

  }
  static public function drawRect(g:Graphics,x=0,y=0,w=100,h=100,c=0x0):* {

   g.lineStyle(1,0x0,1,true);
   g.beginFill(c,0.6);
   g.drawRect(x,y,w,h);
   g.endFill();

  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

根據輸出結果將 Event Flow 畫成圖片

允許 Cross-Domain 情況下,與一般的 Event Flow 無異
不允許 Cross-Domain 情況下,module 內的 Event 不會通過 stage、main、loader

相關連結:
AS3 - MouseOver 與 RollOver 差異性 (1)
AS3 - MouseOver 與 RollOver 差異性 (2)
AS3 - MouseOver 與 RollOver 差異性 (3)

Read more...

2007年8月25日 星期六

Loader.loadBytes 與 loaderInfo.url   [+/-]

Ticore's Blog

ActionScript 3.0 的 Loader 可以直接從 ByteArray 載入 Flash Movie
不知道這樣載入的 Flash Movie 的 URL 會是什麼
以下做個測試~

Main Class:

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

 public class main extends MovieClip {

  var swfAry:Array = [0x46, 0x57, 0x53, 0x1, 0x19, 0x0, 0x0,
     0x0, 0x30, 0xa, 0x0, 0xa0, 0x0, 0xc,
     0x1, 0x0, 0x43, 0x2, 0xff, 0xff, 0xff,
     0x40, 0x0, 0x0, 0x0];
  var swfByteAry:ByteArray = new ByteArray();
  var ldr1:Loader = new Loader();
  
  public function main():* {
   
   for (var i:Number = 0 ; i < swfAry.length ; ++i) {
    swfByteAry.writeByte(swfAry[i]);
   }
   
   ldr1.contentLoaderInfo.addEventListener(Event.INIT, onSwfLoad);
   ldr1.loadBytes(swfByteAry);
   
  }
  
  public function onSwfLoad(evtObj:Event):* {
   trace(evtObj.target.loader.contentLoaderInfo.url);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

輸出結果:

file:///C|/main.swf/[[DYNAMIC]]/1
Read more...

2007年8月22日 星期三

AS3 - MouseOver 與 RollOver 差異性 (3)   [+/-]

Ticore's Blog

之前關於 MouseOver 與 RollOver 測試程式也許不是容易理解
盡可能在所有位置監聽事件
依據輸出結果以圖片方式表達

以下程式會建立兩個 MovieClip,於 stage、root、mc1、mc2 都加入監聽

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

 public class main extends MovieClip {

  public function main():* {

   var mc1:MovieClip = new MovieClip();
   var mc2:MovieClip = new MovieClip();

   mc1.name="MC1";
   mc2.name="MC2";

   mc1.x = 70;
   mc1.y = 40;
   mc2.x = 60;
   mc2.y = 20;

   drawRect(mc1.graphics, 0, 0, 100, 100, 0xFF0000);
   drawRect(mc2.graphics, 0, 0, 100, 100, 0x0000FF);

   mc1.addChild(mc2);

   initEvents(stage);
   initEvents(this);
   initEvents(mc1);
   initEvents(mc2);

   this.addChild(mc1);
   
  }
  
  public function initEvents(obj:InteractiveObject):* {

   obj.addEventListener(MouseEvent.MOUSE_OVER, handler, false);
   obj.addEventListener(MouseEvent.MOUSE_OVER, handler, true);
   
   obj.addEventListener(MouseEvent.MOUSE_OUT, handler, false);
   obj.addEventListener(MouseEvent.MOUSE_OUT, handler, true);

   obj.addEventListener(MouseEvent.ROLL_OUT, handler, false);
   obj.addEventListener(MouseEvent.ROLL_OUT, handler, true);

   obj.addEventListener(MouseEvent.ROLL_OVER, handler, true);
   obj.addEventListener(MouseEvent.ROLL_OVER, handler, false);

  }
  
  public function handler(evtObj:MouseEvent):* {
   
   trace("eventPhase : " + evtObj.eventPhase +
      ", currentTarget : " + evtObj.currentTarget.name +
      ", target : " + evtObj.target.name + ", type : " + evtObj.type);
   
  }
  
  static public function drawRect(g:Graphics,x=0,y=0,w=100,h=100,c=0x0):* {
   
   g.lineStyle(1,0x0,1,true);
   g.beginFill(c,0.6);
   g.drawRect(x,y,w,h);
   g.endFill();
   
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

以上的程式會在畫面上產生兩個正方形
用滑鼠滑過正方形
會得到以下輸出結果:

eventPhase : 1, currentTarget : null, target : MC1, type : rollOver
eventPhase : 1, currentTarget : root1, target : MC1, type : rollOver
eventPhase : 2, currentTarget : MC1, target : MC1, type : rollOver
eventPhase : 1, currentTarget : null, target : root1, type : rollOver
eventPhase : 2, currentTarget : root1, target : root1, type : rollOver
eventPhase : 1, currentTarget : null, target : MC1, type : mouseOver
eventPhase : 1, currentTarget : root1, target : MC1, type : mouseOver
eventPhase : 2, currentTarget : MC1, target : MC1, type : mouseOver
eventPhase : 3, currentTarget : root1, target : MC1, type : mouseOver
eventPhase : 3, currentTarget : null, target : MC1, type : mouseOver
eventPhase : 1, currentTarget : null, target : MC1, type : mouseOut
eventPhase : 1, currentTarget : root1, target : MC1, type : mouseOut
eventPhase : 2, currentTarget : MC1, target : MC1, type : mouseOut
eventPhase : 3, currentTarget : root1, target : MC1, type : mouseOut
eventPhase : 3, currentTarget : null, target : MC1, type : mouseOut
eventPhase : 1, currentTarget : null, target : MC2, type : rollOver
eventPhase : 1, currentTarget : root1, target : MC2, type : rollOver
eventPhase : 1, currentTarget : MC1, target : MC2, type : rollOver
eventPhase : 2, currentTarget : MC2, target : MC2, type : rollOver
eventPhase : 1, currentTarget : null, target : MC2, type : mouseOver
eventPhase : 1, currentTarget : root1, target : MC2, type : mouseOver
eventPhase : 1, currentTarget : MC1, target : MC2, type : mouseOver
eventPhase : 2, currentTarget : MC2, target : MC2, type : mouseOver
eventPhase : 3, currentTarget : MC1, target : MC2, type : mouseOver
eventPhase : 3, currentTarget : root1, target : MC2, type : mouseOver
eventPhase : 3, currentTarget : null, target : MC2, type : mouseOver
eventPhase : 1, currentTarget : null, target : MC2, type : mouseOut
eventPhase : 1, currentTarget : root1, target : MC2, type : mouseOut
eventPhase : 1, currentTarget : MC1, target : MC2, type : mouseOut
eventPhase : 2, currentTarget : MC2, target : MC2, type : mouseOut
eventPhase : 3, currentTarget : MC1, target : MC2, type : mouseOut
eventPhase : 3, currentTarget : root1, target : MC2, type : mouseOut
eventPhase : 3, currentTarget : null, target : MC2, type : mouseOut
eventPhase : 1, currentTarget : null, target : root1, type : rollOut
eventPhase : 2, currentTarget : root1, target : root1, type : rollOut
eventPhase : 1, currentTarget : null, target : MC1, type : rollOut
eventPhase : 1, currentTarget : root1, target : MC1, type : rollOut
eventPhase : 2, currentTarget : MC1, target : MC1, type : rollOut
eventPhase : 1, currentTarget : null, target : MC2, type : rollOut
eventPhase : 1, currentTarget : root1, target : MC2, type : rollOut
eventPhase : 1, currentTarget : MC1, target : MC2, type : rollOut
eventPhase : 2, currentTarget : MC2, target : MC2, type : rollOut

根據以上資料,分別將 RollOver、RollOut 與 MouseOver、MouseOut 事件流畫成圖片

MouseOver、MouseOut Event Flow:

RollOver、RollOut Event Flow:

AS3 Dispatch Bubble、Non-Bubble Event Flow:

相關連結:
AS3 - MouseOver 與 RollOver 差異性 (1)
AS3 - MouseOver 與 RollOver 差異性 (2)
AS3 MouseEvent.relatedObject
AS3 Cross-Domain Event Flow
AS 3.0 - Mouse Event & mouseEnabled

Read more...

Flash Player 9 Update 支援 H.264   [+/-]

Ticore's Blog

Flash Player 開始支援 H.264 Codec 了~
在 Demo 頁面,Flash Player 是直接讀取外部 *.mp4 進行撥放

Adobe Labs - Flash Player 9 Update
Adobe Labs - Downloads Flash Player 9 Update
Adobe Labs - Flash Player 9 Update Full-Screen Mode Demo

相關連結:
ActionScript 3.0 - NetStream 未公開的 Codec 函式
Flash Player MovieStar 與 NetStream.VideoCodec 代碼

Read more...

2007年8月10日 星期五

AS3 Fix SharedObject Flush Timeout Bug   [+/-]

Ticore's Blog

承上一篇,後來繼續測試,發現一直 Load 外部 swf 內的 SharedObject
就不會發生問題,搞不好又是 Garbage Collection 的問題~~

以下將不斷 Load SWF 的動作寫成單獨的 Class
迫使 SharedObject 進行某些未知的回收動作
這樣就可以在 Main Movie 直接使用 SharedObject 了~~

AS3 SOClassUpdater Class:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.utils.*;
 
 public class SOClassUpdater {
  
  protected static var timer:Timer;
  protected static var loader:Loader;
  
  protected static var swfAry:Array =
   [0x46, 0x57, 0x53, 0x1, 0x1d, 0x0, 0x0, 0x0,
    0x70, 0x0, 0xb, 0xb8, 0x0, 0x0, 0x7d, 0x0,
    0x0, 0x18, 0x1, 0x0, 0x43, 0x2, 0xff, 0xff,
    0xff, 0x40, 0x0, 0x0, 0x0];
  protected static var swfByteAry:ByteArray;
  
  {
   init();
  }
  
  public function SOClassUpdater():*{
   throw new Error("You cannot new a SOClassUpdater instance !");
  }
  
  protected static function init():*{
   
   swfByteAry = new ByteArray();
   for (var i:Number = 0 ; i < swfAry.length ; ++i) {
    swfByteAry.writeByte(swfAry[i]);
   }
   
   timer = new Timer(1000);
   timer.addEventListener(TimerEvent.TIMER, doUpdate);
   
   loader = new Loader();
   
   doUpdate();
   startUpdate();
   
  }
  
  public static function startUpdate ():*{
   timer.start();
  }
  
  public static function stopUpdate ():*{
   timer.stop();
  }
  
  public static function doUpdate (evtObj:TimerEvent = null):*{
   //trace("SOClassUpdater.doUpdate();");
   loader.loadBytes(swfByteAry);
  }
  
  public static function get delay():Number{
   return timer.delay;
  }
  
  public static function set delay(time:Number):*{
   return timer.delay = time;
  }
  
 }
 
}

AS3 Main Class:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  protected var timer:Timer;
  
  public function main ():*{
   
   trace(SOClassUpdater);
   timer = new Timer(10);
   timer.addEventListener(TimerEvent.TIMER, run);
   timer.start();
   
  }
  
  public function run(evtObj:TimerEvent):*{
   
   var so:SharedObject = SharedObject.getLocal("so", "/");
   trace(so.data.t);
   so.data.t = new Date();
   so.flush(1);
   so.close();
   
  }
  
 }
}

更新,後來在家裡進行測試發現還是會出現 Timeout
看起來 Loader 只能改善問題~~

相關連結:
AS3 SharedObject Flush Timeout Bug

Read more...

AS3 SharedObject Flush Timeout Bug   [+/-]

Ticore's Blog

這次是公司同事 Luc 發現的問題
在 ActionScript 3.0 不斷的對 SharedObject 執行寫入動作
預設情況下,約十幾秒之後會出現程式執行 Timeout 警告

影片中有一個 Script 會讓 Flash Player 的速度便慢,如果繼續執行它,
電腦可能會停止回應,你要停止這個 Script 嗎?

除了寫入動作以外,不斷建立新的 SharedObject 動作也會發生 Timeout
以下是示範程式

AS3 SharedObject Bug 示範 1:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  public function main ():*{
   
   var timer:Timer = new Timer(100);
   timer.addEventListener(TimerEvent.TIMER, run);
   timer.start();
   
  }
  
  public function run(evtObj:TimerEvent):*{
   
   trace("run();");
   var so:SharedObject = SharedObject.getLocal("so", "/");
   so.flush(1);
   so.close();
   
  }
  
 }
}

AS3 SharedObject Bug 示範 2:

package {
 import flash.display.*;
 import flash.net.*;
 import flash.events.*;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  protected var index:Number = 0;
  
  public function main ():*{
   
   var timer:Timer = new Timer(100);
   timer.addEventListener(TimerEvent.TIMER, run);
   timer.start();
   
  }
  
  public function run(evtObj:TimerEvent):*{
   
   trace("run();");
   var so:SharedObject = SharedObject.getLocal("so" + index++, "/");
   so.close();
   
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

這個 Bug 實在非常詭異,明明沒有什麼需要花時間的執行動作
居然會出現 Timeout 警告

既然是 Timeout,那麼可想而知
最簡單的修補方式,就是到發布設定修改 Timeout 時間
最大可以設到 65535 秒,相當於 18 小時多
應該不會有人連續跑那麼久吧! 除非是當作應用程式~~

這個 Bug 在以下 Flash Player 版本會發生:
Flash Player 9.0.15.0
Flash Player 9.0.16.0
Flash Player 9.0.28.0
Flash Player 9.0.45.0
Flash Player 9.0.47.0
Flash Player 9.0.60.120
Flash Player 9.0.60.235
Flash Player 9.0.64.0

Flash Player 9.0.115.0 版本似乎已經對此作了修正

相關連結:
AS3 Fix SharedObject Flush Timeout Bug

Read more...

2007年8月5日 星期日

AS2 - try...catch 與 with 程式碼區塊   [+/-]

Ticore's Blog

之前測試 with bock 與 proxy object 時
突然想到還有一個 try...catch 異常捕捉語法
拿來與 with block 進行測試,發現有趣的現象~

AS2 測試程式:

var proxyObj:Object = {};
proxyObj.__resolve = function(name) {
 trace("proxyObj.__resolve : " + name);
};
try {
 with (proxyObj) {
  throw new Error("Error in with block.");
 }
} catch (e:Object) {
 trace("e : " + e);
} catch (e:Error) {
 trace("e : " + e);
} catch (e) {
 trace("e : " + e);
}
// Ticore's Blog - http://ticore.blogspot.com/

輸出結果:

proxyObj.__resolve : Error
proxyObj.__resolve : Object
proxyObj.__resolve : Error
proxyObj.__resolve : e
e : undefined

沒想到在 ActionScript 2.0,with block 的範圍與優先權居然比 catch block 還要高
也許是因為 AS2 不夠嚴謹的緣故
假如改用 AS3 進行類似的測試,便不會有這樣的情況了

相關連結:
ActionScript "with" Block Scope 遮蔽效應
AS2 利用 with, Object.__resolve 選擇性替換 Scope Variables

Read more...

2007年8月4日 星期六

AS3 - MouseOver 與 RollOver 差異性 (2)   [+/-]

Ticore's Blog

承前一篇~
MouseOver (MouseOut) 與 RollOver (RollOut) 之中的差異性不是光靠 Bubble 屬性就可以消除的
RollOver (RollOut) 事件有些機制,是 MouseOver (MouseOut) 做不到的

以下程式會建立三個 MovieClip,依序加入前一個子物件下
三個 MovieClip 具有相同的 HitArea
分別用兩個 Dictionary 收集三個 MovieClip 發出的 MouseOver、RollOver 事件
利用 Dictionary Key 值不重複的特性,觀察 Event Object 數量

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

 public class main extends MovieClip {

  var rollOverEvtObjs:Dictionary = new Dictionary();
  var mouseOverEvtObjs:Dictionary = new Dictionary();
  
  public function main():* {

   var subMc1:MovieClip = new MovieClip();
   var subMc2:MovieClip = new MovieClip();
   var subMc3:MovieClip = new MovieClip();

   subMc1.name="SubMc1";
   subMc2.name="SubMc2";
   subMc3.name="SubMc3";

   subMc1.x = 100;
   subMc1.y = 50;

   initEvents(subMc1);
   initEvents(subMc2);
   initEvents(subMc3);

   drawRect(subMc3.graphics);

   subMc2.addChild(subMc3);
   subMc1.addChild(subMc2);
   this.addChild(subMc1);
   
  }
  
  public function initEvents(obj:InteractiveObject):* {
   
   obj.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
   obj.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
   
   obj.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
   obj.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
   
  }
  
  public function rollOverHandler(evtObj:MouseEvent):* {
   
   trace("currentTarget : " + evtObj.currentTarget.name);
   trace("target : " + evtObj.target.name);
   trace("type : " + evtObj.type);
   
   rollOverEvtObjs[evtObj] = null;
   var counter:Number = 0;
   for (var i in rollOverEvtObjs) {
    counter++;
   }
   trace("No: " + counter);
   
  }
  
  public function rollOutHandler(evtObj:MouseEvent):* {
   rollOverEvtObjs = new Dictionary();
  }
  
  public function mouseOverHandler(evtObj:MouseEvent):* {
   
   trace("currentTarget : " + evtObj.currentTarget.name);
   trace("target : " + evtObj.target.name);
   trace("type : " + evtObj.type);
   
   mouseOverEvtObjs[evtObj] = null;
   var counter:Number = 0;
   for (var i in mouseOverEvtObjs) {
    counter++;
   }
   trace("No: " + counter);
   
  }
  
  public function mouseOutHandler(evtObj:MouseEvent):* {
   mouseOverEvtObjs = new Dictionary();
  }
  
  static public function drawRect(g:Graphics,x=0,y=0,w=100,h=100):* {
   
   g.lineStyle(1,0x0,1,true);
   g.beginFill(0x0,0.1);
   g.drawRect(x,y,w,h);
   g.endFill();
   
  }
  
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

以上的程式會在畫面上產生一個正方形
用滑鼠滑過正方形
會得到以下輸出結果:

currentTarget : SubMc3
target : SubMc3
type : rollOver
No: 1
currentTarget : SubMc2
target : SubMc2
type : rollOver
No: 2
currentTarget : SubMc1
target : SubMc1
type : rollOver
No: 3
currentTarget : SubMc3
target : SubMc3
type : mouseOver
No: 1
currentTarget : SubMc2
target : SubMc3
type : mouseOver
No: 1
currentTarget : SubMc1
target : SubMc3
type : mouseOver
No: 1

發現到 MouseOver 事件在整個 Event Flow 中只會產生一個
可是 RollOver 事件卻會產生三個
而且三個 RollOver 事件的對象 (target) 都不一樣
就像是針對不同的對象專屬的事件一樣
也是因為專屬的特性,Bubble 變的沒有意義

相關連結:
AS3 - MouseOver 與 RollOver 差異性 (1)
AS3 - MouseOver 與 RollOver 差異性 (3)
AS3 MouseEvent.relatedObject
AS3 Cross-Domain Event Flow
AS 3.0 - Mouse Event & mouseEnabled

Read more...

AS3 - MouseOver 與 RollOver 差異性 (1)   [+/-]

Ticore's Blog

ActionScript 3.0 DisplayObject 的事件機制變的相當複雜
其中 MouseEvent.MOUSE_OVER 與 MouseEvent.ROLL_OVER 又非常容易混淆
一般情況下,使用起來不會感覺到很大的差異
文件上只是 Bubble 屬性不同而已
不過實際上差異不僅是如此
舉例子來說明~

以下程式會建立三個 MovieClip,依序加入前一個子物件下
但是只有在最上層的 MovieClip 註冊滑鼠事件

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

 public class main extends MovieClip {

  public function main():* {
   var mc1:MovieClip = new MovieClip();
   var mc2:MovieClip = new MovieClip();
   var mc3:MovieClip = new MovieClip();

   mc1.name="MC1";
   mc2.name="MC2";
   mc3.name="MC3";

   mc1.x = 70;
   mc1.y = 40;
   mc2.x = 30;
   mc2.y = 10;
   mc3.x = 30;
   mc3.y = 10;

   drawRect(mc1.graphics);
   drawRect(mc2.graphics);
   drawRect(mc3.graphics);

   mc1.addChild(mc2);
   mc2.addChild(mc3);

   initEvents(mc1);
   this.addChild(mc1);
  }
  
  public function initEvents(obj:InteractiveObject):* {
   obj.addEventListener(MouseEvent.MOUSE_OVER, handler);
   obj.addEventListener(MouseEvent.MOUSE_OUT, handler);
   obj.addEventListener(MouseEvent.ROLL_OUT, handler);
   obj.addEventListener(MouseEvent.ROLL_OVER, handler);
  }

  public function handler(evtObj:MouseEvent):* {
   trace(evtObj.currentTarget.name + "\t" +
       evtObj.target.name + "\t" + evtObj.type);
  }

  static public function drawRect(g:Graphics,x=0,y=0,w=100,h=100):* {
   g.lineStyle(1,0x0,1,true);
   g.beginFill(0x0,0.1);
   g.drawRect(x,y,w,h);
   g.endFill();
  }

 }
}
// Ticore's Blog - http://ticore.blogspot.com/

以上的程式會在畫面上產生部份重疊的三個正方形
用滑鼠由左到右,橫劃過三個正方形
會得到以下輸出結果:

MC1 MC1 rollOver
MC1 MC1 mouseOver
MC1 MC1 mouseOut
MC1 MC2 mouseOver
MC1 MC2 mouseOut
MC1 MC3 mouseOver
MC1 MC3 mouseOut
MC1 MC1 rollOut

看出其中的差異了吧!

當 DisplayObjectContainer 含有多個子物件具有 mouseEnabled = true 屬性時
父物件的 MouseOver、MouseOut 事件會被觸發好幾次
就像是 hitArea 被切成好幾塊似的

假如改用 RollOver、RollOut 事件就不會有這個問題
當然也可以直接把子物件 mouseEnabled 通通設為 false
不過子物件就會失去接受滑鼠事件的能力

相關連結:
AS3 Cross-Domain Event Flow
AS3 - MouseOver 與 RollOver 差異性 (2)
AS3 - MouseOver 與 RollOver 差異性 (3)
AS 3.0 - Mouse Event & mouseEnabled

Read more...

2007年8月1日 星期三

hxASM - ActionScript 3.0 組語編譯類別庫   [+/-]

Ticore's Blog

SWF9 可以用 ActionScript 3.0 動態編譯了
編譯完成的 ByteArray 可以用其它方式存下來
更有趣的是,還可以直接用 Loader 載入執行~

缺點是該類別庫是用 HaXe 語言寫成的
無法用 Flash CS3 or Flex 2 編譯
需要安裝 HaXe 才能編譯使用

hxASM
hxASM Google Code
Read more...