2009年3月31日星期二

AS3 HTML 文字欄位的型別檢查漏洞   [+/-]

Ticore's Blog

上次介紹了 HTML TextField 神奇之處
這次來介紹它衍伸出來的執行期型別檢查漏洞吧

東西作的太神奇,通常也越容易產生定義衝突與漏洞
像是 TextField 內可以再放 TextField, MovieClip, Sprite, 甚至 Video....
這些類別都屬於 DisplayObject,具有一個型別為 DisplayObjectContainer 的 parent 成員
咦? 這些東西不是放在 TextField 內嗎? TextField 根本不是一個 DisplayObjectContainer
那對 TextField 內的 DisplayObject 取用 parent 會怎樣呢?
實際來測試看看


package {
 import flash.display.DisplayObjectContainer;
 import flash.display.MovieClip;
 import flash.text.TextField;

 [SWF(width="300", height="200", backgroundColor="#FFFFFF")]

 public class main extends MovieClip {

  public function main() {
   var txt:TextField = new TextField();
   txt.border = true;
   txt.x = 100;
   txt.y = 50;
   this.addChild(txt);

   txt.htmlText = "Ticore's Blog<img id='img' src='flash.display.MovieClip' />";
   var mc:MovieClip = txt.getImageReference('img') as MovieClip;
   trace(mc); // [object MovieClip]
   
   if (mc != null) {
    var mcParent:DisplayObjectContainer = mc.parent;
    trace(mcParent); // [object TextField]
    trace(mcParent is DisplayObjectContainer); // false
    trace(mcParent as DisplayObjectContainer); // null
   }
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

由測試程式可以發現,TextField 內的 DisplayObject.parent 居然可以逃過 AS3 的型別檢查
將 TextField 指定到一個 DisplayObjectContainer 變數上
假如再次對該變數作 is 或是 as 運算就破功了~

相關連結:
AS3 SimpleButton 型別檢查漏洞
AS3 HTML 文字欄位技巧與臭蟲

Read more...

2009年3月28日星期六

SWF10 移除物件 3D 屬性   [+/-]

Ticore's Blog

Flash Player 10 新增的 3D 功能很方便
直接對 DisplayObject 指定 rotationX, rotationY, rotationZ 或是 z 等 3D 屬性
平面的 2D 物件馬上躍昇為 3D
可是 Flash Player 10 強迫對 3D 物件作抗鋸齒
不想要也不行~

package {
 import flash.display.MovieClip;
 import flash.geom.Matrix;
 import flash.text.TextField;
 import flash.text.TextFieldAutoSize;
 import flash.text.TextFormat;
 
 [SWF(width="300", height="200", backgroundColor="#FFFFFF")]
 public class main extends MovieClip {
  public function main() {
   var tf:TextFormat = new TextFormat(null, 32);
   var txt:TextField = new TextField();
   txt.defaultTextFormat = tf;
   txt.autoSize = TextFieldAutoSize.CENTER;
   txt.text = "Ticore's Blog";
   txt.x = 40;
   txt.y = 60;
   this.addChild(txt);
   txt.rotationZ = 0;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

既使已經把 rotationX, rotationY, rotationZ 等 3D 屬性歸零
還是無法恢復為 2D 物件,文字也會糊糊的

正確的恢復方式如下,只要將 Transform.maxtrix3D 指定為 null 就好了

package {
 import flash.display.MovieClip;
 import flash.geom.Matrix;
 import flash.text.TextField;
 import flash.text.TextFieldAutoSize;
 import flash.text.TextFormat;
 
 [SWF(width="300", height="200", backgroundColor="#FFFFFF")]
 public class main extends MovieClip {
  public function main() {
   var tf:TextFormat = new TextFormat(null, 32);
   var txt:TextField = new TextField();
   txt.defaultTextFormat = tf;
   txt.autoSize = TextFieldAutoSize.CENTER;
   txt.text = "Ticore's Blog";
   txt.x = 40;
   txt.y = 60;
   this.addChild(txt);
   txt.rotationZ = 0;
   
   var obj:Object = {x: txt.x, y: txt.y, scaleX: txt.scaleX, scaleY: txt.scaleY};
   txt.transform.matrix3D = null;
   txt.x = obj.x;
   txt.y = obj.y;
   txt.scaleX = obj.scaleX;
   txt.scaleY = obj.scaleY;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
Flash Player 10 兩種旋轉文字方式比較
AS3 - BitmapText 程式分享

Read more...

AS3 HTML 文字欄位技巧與臭蟲   [+/-]

Ticore's Blog

Flash 的文字欄位 (TextField) 除了用來顯示與輸入一般文字之外
也有支援簡單的 HTML 標籤
像是 <font>, <b>, <i>, <u>, <a>, <p>, <br>, <li>, <span>, <img>
其中比較特別的是 <img>,除了可以用來表現外部圖片以外
還可以藉由 src 指定 Linkage Identifier 的方式
呈現 Library 內的 MovieClip

Linkage Identifier 已經是 AS2 時代的舊名稱了
轉換為 AS3 的說法就是 Class Name
意思就是可以用指定 htmlText 的方式
直接在 TextField 內產生繼承 DisplayObject 的 Sprite, MovieClip, SimpleButton
甚至是另一個 TextField 實體

以下便是用 AS3 在 TextField 內,再創建另一個TextField

package {
 import flash.display.MovieClip;
 import flash.text.TextField;
 
 [SWF(width="300", height="200", backgroundColor="#FFFFFF")]
 public class main extends MovieClip {
  public function main() {
   var outerTxt:TextField = new TextField();
   outerTxt.border = true;
   outerTxt.x = 100;
   outerTxt.y = 50;
   this.addChild(outerTxt);
   
   outerTxt.htmlText = "Outer TextField<img id='txt' src='flash.text.TextField' width='80' height='50' />";
   var innerTxt:TextField = outerTxt.getImageReference('txt') as TextField;
   innerTxt.border = true;
   innerTxt.text = "Inner TextField";
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

效果截圖

很有趣吧,一般使用情況下 TextField 內是無法再放其它 DisplayObject 的

可是 TextField.htmlText 卻有一個臭蟲
假如 <img> 標籤前後沒有其它文字,img 會建立失敗
如以下 AS3 程式:

package {
 import flash.display.MovieClip;
 import flash.text.TextField;
 import flash.text.TextFormat;
 
 [SWF(width="300", height="200", backgroundColor="#FFFFFF")]
 public class main extends MovieClip {
  public function main() {
   var txt:TextField = new TextField();
   txt.border = true;
   txt.x = 100;
   txt.y = 50;
   this.addChild(txt);
   
   txt.htmlText = "<img id='img' src='flash.display.Sprite' />";
   trace(txt.getImageReference('img')); // null
   
   txt.htmlText = " " + "<img id='img' src='flash.display.Sprite' />";
   trace(txt.getImageReference('img')); // [object Sprite]
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
AS3 HTML 文字欄位的型別檢查漏洞

Read more...

2009年3月25日星期三

Flash CS4 Drawing Tools Bug   [+/-]

Ticore's Blog

最近稍微有開始用 Flash CS4 處理一些東西
天生的好運氣又讓我發現了一些 Bug

Flash CS4 版本:10.0.1.545 Win、10.0.1.545 Mac

在舞台上隨便畫了一些向量色塊之後,選起來
將顏色調為 #000000,Alpha 設為 0
好戲來了,向量色塊全部消失了!
不只如此,在選擇顏色 #000000 Alpha 0 的情況下
什麼東西都畫不出來~

相關連結:
Flash CS4 更新檔下載

Read more...

2009年3月24日星期二

Flash CS4 繁體中文完整線上 HTML 文件下載   [+/-]

Ticore's Blog

好康的又來了!

由於 Flash 開發平台越來越多
Flash、FlashLite、AIR、ActionScript 2.0, 3.0
Flash CS4 剛出的時候,線上文件尚未備齊
所以等到現在才將線上的文件整理下來

這次收集的非常完整,主要有包含以下部分:

下載網址:
http://rapidshare.com/files/212608230/Flash_CS4_LiveDocs_zh_TW_20090323.rar.html

相關連結:
Flash CS3 繁體中文完整線上 HTML 文件下載

Read more...

2009年3月22日星期日

SWF10 時間軸預置物件行為的改變 Part 2   [+/-]

Ticore's Blog

SWF8 以前可以用 AS 隨意跳影格,然後馬上就可以取得新影格下的資料
到了 SWF9 AS3 突然不能這樣做了
跳到新影格之後,還需要等一個 frame 時間
該影格下的物件才會被建立完成
相信這已經搞死很多 Flash RD,哈~~哈~~!

雖然可以理解 SWF9 AS3 這樣作是為了要改善效能
譬如隨意的把影格跳來跳去,中間的畫面最終又不會給使用者看到
那中間的那些物件不是都白建了嗎?
但是坦白說,這行為真的很惱人呢!

好消息是 SWF10 似乎又改回來了喔!
以下用個簡單的實驗來測試看看

用 Flash CS4 建立含有兩個影格的文件
第一影格隨便放一個 MovieClip,第二影格空白
如下圖所示:

然後用以下的 ActionScript 3.0 Document Class:

package {
 import flash.display.*;
 public class main extends MovieClip {
  public function main() {
   stop();
   for (var i:Number = 0 ; i < 10 ; ++i) {
    nextFrame();
    prevFrame();
    trace(this.numChildren, this.getChildAt(0));
   }
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

分別用 SWF9、SWF10 發布測試
從 Log 結果可以發現到 SWF10 不管影格怎樣跳
Flash Player 10 都會馬上把新影格下的物件建立好了
這對一些 Flash RD 來說真是一大福音啊!

相關連結:
SWF10 時間軸預置物件行為的改變
AS3 時間軸預置圖像物件的特性

Read more...

2009年3月21日星期六

Flash Player 10 Vector 使用上的問題   [+/-]

Ticore's Blog

Flash Player 10 的新功能 Vector
使用的時候有一些需要注意的地方

舉例來說,以下 main class 的 member function 內
僅僅只是宣告的一個 Vector.<obj> 變數
會讓 compiler 把 obj class 也一起編譯進來了

package {
 import __AS3__.vec.Vector;
 import flash.display.MovieClip;
 
 public class main extends MovieClip {
  public function main() {
  }
  public function foo():void {
   var vec:Vector.<obj>;
  }
 }
}

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

假如開發的的程式,需要切割模組與 ApplicationDomain 就很不方便
使用 interface, subclass, reflection 等方式或許可以解決這樣的問題
interface, subclass 應該沒問題
可是 Vector 能夠用 reflection 的方式動態建立嗎?

利用 getQualifiedClassName, describeType 可以發現
一個 Vector 類別的完整名稱大概是像這樣 __AS3__.vec::Vector.<Object>

再繼續測試,嘗試使用 getDefinitionByName 動態取得 Vector

package {
 import flash.display.MovieClip;
 import flash.utils.getDefinitionByName;
 
 public class main extends MovieClip {
  public function main() {
   trace(getDefinitionByName("__AS3__.vec::Vector.<Object>"));
   // [class Vector.<Object>]
   
   try {
    trace(getDefinitionByName("__AS3__.vec::Vector.<*>"));
   } catch (e:Error) {
    trace(e);
    // ReferenceError: Error #1065: 變數 * 未定義。
   }
  }
 }
}

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

比較奇怪的地方是 Vector.<*> 型別無法透過反射來取得
假如希望透過反射建立的 Vector 裝載的型別是動態載入的
也必須要等到載入完成之後,才能透過所屬的 ApplicationDomain 取得

這樣看起來,雖然 Reflection 能夠動態建立 Vector
但是有點麻煩~
既然 Vector 與裝載的元素型別綁的那麼緊
那麼何不直接把建立 Vector 的動作寫在 Class Static Function 上呢?

package {
 import __AS3__.vec.Vector;
 
 public class obj {
  public static function getVector(
      length:uint = 0, fixed:Boolean = false):Vector.<obj> {
   return new Vector.<obj>(fixed, length);
  }
 }
}

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

因為直接與元素的類別綁在一起,不用判定是否類別載入完成
所有需要建立該元素型別 Vector 的動作都透過呼叫此 static function 完成
Compiler 也不會多編譯到需要放在外部的類別
看起來會比 interface, reflection 方式好用多了

Read more...

Firefox Addons - CodeBurner   [+/-]

Ticore's Blog

不少人應該都知道 Firefox、FireBug 有多好用了
最近又發現一個基於 FireBug 的擴充 - CodeBurner
可以直接在 FireBug 內快速查詢檢視 HTML、CSS 語法的參考文件
以及在幾個主要瀏覽器上的相容性

假如覺得資料還不夠,CodeBurner 也有提供快速連結
直接連上 sitepoint 網頁查詢詳細的語法參考

缺點是好像少了 Javascript 語法參考~

Read more...

2009年3月20日星期五

Flex Copylocale Commands   [+/-]

Ticore's Blog

Flex Builder 以 Plugin 方式安裝的時候
開發多國語言都會遇到 locale folder 找不到的問題
Flex SDK 下有提供一個 copylocale.exe 的小工具可以解決這個問題
但是多一種語言就要多下一次 command 複製語言資料
假如遇到 27 國,光是找語言代號就很累
更慘的是每次出新的 Flex SDK,整個又再重來一次~

以下將 25 種語言 (27 扣掉 en_US, ja_JP) command 做個速記
方便大家使用~

copylocale en_US zh_TW
copylocale en_US zh_CN
copylocale en_US fr_FR
copylocale en_US de_DE
copylocale en_US ko_KR
copylocale en_US ru_RU
copylocale en_US es_ES
copylocale en_US it_IT
copylocale en_US ar_AE
copylocale en_US nl_NL
copylocale en_US pt_PT
copylocale en_US pt_BR
copylocale en_US sv_SE
copylocale en_US nb_NO
copylocale en_US fi_FI
copylocale en_US da_DK
copylocale en_US pl_PL
copylocale en_US he_IL
copylocale en_US hu_HU
copylocale en_US sl_SI
copylocale en_US el_GR
copylocale en_US cs_CZ
copylocale en_US sk_SK
copylocale en_US tr_TR
copylocale en_US hr_HR

Flex Compiler 找不到語言資料夾的錯誤訊息:

unable to open 'C:\Program Files\Adobe\Flex Builder 3 Plug-in\sdks\3.3.0\frameworks\locale\ar_AE'
unable to open 'C:\Program Files\Adobe\Flex Builder 3 Plug-in\sdks\3.3.0\frameworks\locale\zh_TW'
unable to open 'C:\Program Files\Adobe\Flex Builder 3 Plug-in\sdks\3.3.0\frameworks\locale\zh_CN'
Read more...

2009年3月17日星期二

Flex Transparent Menu Control   [+/-]

Ticore's Blog

在 Flex 大部分的組件中,想要使用半透明背景
通常只要用 CSS 設定 backgroundAlpha 就能做到了
但是這招在 Menu 卻不管用~

譬如這樣設定 Menu CSS Style:

 Menu {
  backgroundColor: #000000;
  backgroundAlpha: 0.1;
 }

出來的 Menu 會變成不透明的灰色

仔細測試之後才發現,Menu 組件會用 borderColor 在背景填色
除非明確指定 borderStyle 為 solid

Flex 半透明 Menu 範例程式:

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF"
    fontSize="12" paddingLeft="5" paddingRight="5" paddingTop="5" paddingBottom="5">
 <mx:Style>
  Alert {
   borderColor: #808080;
   backgroundColor: #808080;
  }
  Menu {
   backgroundColor: #000000;
   backgroundAlpha: 0.1;
   borderColor: #808080;
   borderStyle: solid;
   dropShadowColor: #000000;
   dropShadowEnabled: yes;
  }
 </mx:Style>
 <mx:Script>
  <![CDATA[
   import mx.controls.Menu;
   import mx.events.MenuEvent;
   import mx.controls.Alert;
   import flash.geom.Point;

   private var point1:Point = new Point();
   private var myMenu:Menu;

   private function showMenu():void {
    myMenu = Menu.createMenu(panel, myMenuData, false);
    myMenu.labelField = "@label"
    myMenu.addEventListener("itemClick", menuHandler);
    // Calculate position of Menu in Application's coordinates.
    point1.x = mybutton.x;
    point1.y = mybutton.y;
    point1 = mybutton.localToGlobal(point1);
    myMenu.show(point1.x + 5, point1.y);
   }

   // Event handler for the Menu control's change event.
   private function menuHandler(event:MenuEvent):void {
    Alert.show("Label: " + event.item.@label, "Clicked menu item");
   }
  ]]>
 </mx:Script>

 <mx:XML format="e4x" id="myMenuData">
  <root>
   <menuitem label="MenuItem A" icon="myTopIcon">
    <menuitem label="SubMenuItem A-1" enabled="False"/>
    <menuitem label="SubMenuItem A-2"/>
   </menuitem>
   <menuitem label="MenuItem B" type="check" toggled="true"/>
   <menuitem label="MenuItem C" type="check" toggled="false" icon="myTopIcon"/>
   <menuitem type="separator"/>
   <menuitem label="MenuItem D" icon="myTopIcon">
    <menuitem label="SubMenuItem D-1" type="radio" groupName="one"/>
    <menuitem label="SubMenuItem D-2" type="radio" groupName="one"
        toggled="true"/>
    <menuitem label="SubMenuItem D-3" type="radio" groupName="one"/>
   </menuitem>
  </root>
 </mx:XML>

 <mx:Panel id="panel" title="Transparent Menu Control Example" height="100%"
     width="100%" paddingTop="10" paddingLeft="10" paddingRight="10"
     paddingBottom="10">
  <mx:Button id="mybutton" label="Open Menu" click="showMenu();"/>
  <mx:HBox width="100%" height="100%">
   <mx:Repeater dataProvider="{new Array(3)}">
    <mx:Canvas width="25%" height="100%" backgroundColor="#DDFFDD"/>
    <mx:Canvas width="25%" height="100%" backgroundColor="#FFDDDD"/>
   </mx:Repeater>
  </mx:HBox>
  <mx:ControlBar>
   <mx:Text width="100%" textAlign="right">
    <mx:htmlText>
     <![CDATA[<a target="_blank" href="http://ticore.blogspot.com/">]]>
     <![CDATA[Ticore's Blog - http://ticore.blogspot.com/</a>]]>
    </mx:htmlText>
   </mx:Text>
  </mx:ControlBar>
 </mx:Panel>
</mx:Application>

效果擷圖:

Flex Transparent Menu Control 線上範例:

Read more...

Flex NumericStepper Change Event Bug   [+/-]

Ticore's Blog

又遇到一個 Flex NumericStepper 臭蟲
正常情況下,NumericStepper 數值發生改變都會丟出 change 事件
但是假如手動在文字欄位輸入超過最大值,卻會拿不到 change 事件

Bug 重複步驟:

  1. 先將 NumericStepper 欄位重設為低於 maximum 的數值
  2. 在 NumericStepper 欄位直接輸入超過 maximum 的數值
  3. 滑鼠左鍵點一下增加按鈕
  4. 結果沒有任何 change 事件發生

以下是 Flex NumericStepper Bug 測試程式:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   backgroundColor="#F0F0F0" fontSize="12">
 <!--
  1. Reset to a non-maximum value.
  2. Input some number bigger than numeric stepper maximum.
  3. Mouse left click on increase button.
  4. Result no change event. Expect one change event, because the value changed.
 -->
 <mx:Label text="Flex NumericStepper Change Event Bug" fontSize="14" fontWeight="bold" />
 <mx:NumericStepper id="no" maximum="3"
   change="logTxt.text += event.type + ' : ' + event.value + '\n';">
 </mx:NumericStepper>
 <mx:TextArea id="logTxt" width="100%" height="100%"/>
 <mx:Text width="100%" textAlign="right">
  <mx:htmlText>
   <![CDATA[<a target="_blank" href="http://ticore.blogspot.com/">]]>
   <![CDATA[Ticore's Blog - http://ticore.blogspot.com/</a>]]>
  </mx:htmlText>
 </mx:Text>
</mx:Application>

Flex NumericStepper Change Event Bug 線上範例:

Flex SDK 版本:3.1、3.2、3.3

本來想用繼承複寫的方式修正這 Bug
但是因為 NumericStepper 實在寫的太死了
好多個重要的 Member Function 都宣告為 private
整個打掉重練可能還比較快~

Read more...

2009年3月16日星期一

Flex 怪異的嵌入行為   [+/-]

Ticore's Blog

最近在作 Flex Embed 外部圖片測試時
發現一個很詭異的現象
正常情況下外部資源只能 Embed 到一個 Class 或是 Class Member Variable
可是 Flex SDK 居然可以允許 Embed 圖片到一個 interface 上

AS3 Embed Interface:

package {
 [Embed(source="image.png")] 
 public interface obj {
 }
}

AS3 Document Class:

package {
 public class main {
  public function main() {
   obj;
  }
 }
}

Flex SDK 只是表示性的出現警告訊息,但是還是可以編譯過的

Warning
  Class 'obj' does not extend the 'DefineBits' asset base class 'flash.display.Bitmap'.

Interface 又無法實體化,也無法表現在畫面上
如何判定圖片有被嵌入呢?
就是用 ActionScript Viewer 如下圖所示

很詭異吧,interface 帶了一張點陣圖!

Flex SDK 3.1, 3.2, 3.3 都會發生

Read more...

2009年3月14日星期六

Flash 技巧 - 強迫畫面更新重繪   [+/-]

Ticore's Blog

其實 Flash Player 的 Render Engine 很強
能夠自動偵測需要更新的區域
只針對畫面上有更新的區域進行重繪
所以幾乎很少看到殘影的情況

萬一遇到殘影的情況,該怎樣讓 Flash Player 局部或是全部重繪更新呢?

從 ActionScript 1.0 開始學的人或許會用 updateAfterEvent function
不過之前貼的殘影的問題 - Tween Effect & Scale 9 Grid Redraw Bug
來測試就會發現那一點用處都沒有~

其實強迫畫面重繪很簡單,畫面會需要重繪就是因為圖像有發生變動
只要自己做一個一閃一閃的線框 MovieClip 放在舞台上
線框籠罩的區域就會被強迫重繪更新了

不想要被看到線框的話,那也很簡單,設為透明就好了
只要有兩個影格一閃一閃,既使是透明的也會有效
不過 visible 必須要為 true

那有沒有程式上的作法? 當然也有!
用 Graphics 畫一畫或是清一清,也能達到相同的效果~

AS2 強迫全面更新畫面的方式:

_root.onEnterFrame = function() {
 clear();
}

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

AS3 強迫全面更新畫面的方式:

root.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);

function onEnterFrameHandler(evtObj:Event):void{
 (root as Sprite).graphics.clear();
}

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

相關連結:
Tween Effect & Scale 9 Grid Redraw Bug

Read more...

AIR - 詭異的類別物件比較結果   [+/-]

Ticore's Blog

以下 Flash Base 的 AIR 程式建立 Javascript Runtime 之後
透過 JS Runtime 繞一圈取得 AS3 Object 類別
然後使用 ==, ===, is, instanceof 各種比較方式
來比較直接取得的 AS3 Object Class 與透過 JS Runtime 取得的 AS3 Object Class

AIR AS3 main class:

package {
 import flash.display.MovieClip;
 import flash.events.Event;
 import flash.html.HTMLLoader;
 import flash.system.ApplicationDomain;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  public static var htmlLdr:HTMLLoader = new HTMLLoader();
  
  public var htmlContent:String = "";
  
  public function main() {
   htmlLdr.placeLoadStringContentInApplicationSandbox = true;
   htmlLdr.addEventListener(Event.COMPLETE, onHTMLLoadComplete);
   addChild(htmlLdr);
   htmlLdr.loadString(htmlContent);
  }
  
  public function onHTMLLoadComplete(evtObj:Event):void {
   trace(objClassThuJS == Object); // false
   trace(objClassThuJS === Object); // false
   trace(new objClassThuJS().constructor == new MovieClip().constructor); // false
   
   trace(new objClassThuJS() is Object); // true
   trace(new Object() is objClassThuJS); // true
   trace(new objClassThuJS() instanceof Object); // false
   trace(new Object() instanceof objClassThuJS); // false
   
   trace(describeType(objClassThuJS).@name); // Object
   trace(describeType(Object).@name); // Object
   
   trace(new objClassThuJS().constructor); // [class Object]
   trace(new Object().constructor); // [class Object]
  }
 }
}

測試出來的結果真的是相當詭異啊!
使用 ==, ===, constructor, instanceof 比較出來的都是不同的
可是將物件實體化之後,再用 is 比較卻又顯示出兩種來源的 Object Class 是相同的
而且類別名稱也是相同的
這樣倒底是相同還是不同啊?
為什麼明明是內建的 AS3 Object Class,透過 JS Runtime 繞了一圈取得之後就走樣了?

相關連結:
AIR JavaScript Runtime 的物件型別
Adobe AIR 混搭測試
純程式建立 AIR AS3-JS 混搭的簡單範例
在 AIR Javascript 中使用 Vector
AIR - ActionScript, JavaScript 混搭技巧
AIR - 如何區分 JavaScript 與 ActionScript 物件
Adobe AIR Namespace Bug
注意你的 AIR and Flash Player version
AIR - JavaScript 與 ActionScript 之間物件的傳遞
Adobe AIR 與 Zinc 3.0 兩則比較

Read more...

2009年3月12日星期四

Tween Effect & Scale 9 Grid Redraw Bug   [+/-]

Ticore's Blog

這是一個關於 Scale 9 Grid 重繪的臭蟲
當在九宮格縮放的 MovieClip 中使用影格漸變效果 (Tween Effect)
如下圖所示~

並且將該 MovieClip 實體放在舞台上,放大長寬
然後測試影片就會看到隨著影格前進
Tween 效果後面拖著殘影
Flash Player 沒辦法正確的重繪

Tween Effect & Scale 9 Grid Redraw Bug 實際範例:

Flash CS3 原始檔案下載

以上的 Bug 至少會發生在以下版本的 Flash Player
Flash Player 8.0.34.0
Flash Player 8.0.42.0
Flash Player 9.0.115.0
Flash Player 9.0.124.0
Flash Player 10.0.0.525
Flash Player 10.0.1.218
Flash Player 10.0.12.10
Flash Player 10.0.12.29
Flash Player 10.0.12.36
Flash Player 10.0.22.87

相關連結:
Flash 技巧 - 強迫畫面更新重繪
ActionScript Scale9Grid 使用技巧
在 Flash 作點陣圖九宮格縮放技巧

Read more...

2009年3月10日星期二

Flash Player 10 兩種旋轉文字方式比較   [+/-]

Ticore's Blog

Flash Player 10 已經可以使用系統字體來表現旋轉文字了
方式有兩種,以下做個簡單的比較測試~

分別使用 Flash Player 10 新的 3D 引擎與文字引擎來作旋轉文字
並且將尺寸放大 200%,比較兩者作法的差異

※以下程式需要編譯為 SWF10,使用 Flash Player 10 播放

AS3 Rotate Text by 3D Engine:

package {
 import flash.display.MovieClip;
 import flash.events.Event;
 import flash.geom.Matrix;
 import flash.text.TextField;
 import flash.text.TextFieldAutoSize;

 [SWF(width = 300, height = 200, backgroundColor = "#FFFFFF")]

 public class AS3RotateText01 extends MovieClip {

  public function AS3RotateText01() {
   var txt:TextField = new TextField();
   txt.autoSize = TextFieldAutoSize.LEFT;
   txt.text = "旋轉文字測試 - Ticore's Blog";
   txt.x = 10;
   txt.y = 30;
   txt.scaleX = txt.scaleY = 2;;
   txt.rotationZ = 20;
   this.addChild(txt);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

AS3 Rotate Text by Text Engine:

package {
 import flash.display.MovieClip;
 import flash.text.engine.ElementFormat;
 import flash.text.engine.TextBlock;
 import flash.text.engine.TextElement;
 import flash.text.engine.TextLine;

 [SWF(width = 300, height = 200, backgroundColor = "#FFFFFF")]

 public class AS3RotateText02 extends MovieClip {

  public function AS3RotateText02() {
   var txt:String = "旋轉文字測試 - Ticore's Blog";
   var txtBlock:TextBlock = new TextBlock();
   var elementFormat:ElementFormat = new ElementFormat(null);
   var txtElement:TextElement = new TextElement(txt, elementFormat);
   txtBlock.content = txtElement;
   var txtLine:TextLine = txtBlock.createTextLine(null);
   txtLine.x = 10;
   txtLine.y = 50;
   txtLine.scaleX = txtLine.scaleY = 2;
   txtLine.rotation = 20;
   this.addChild(txtLine);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

實際執行的效果如下

以下是用 3D 引擎旋轉文字的效果圖
可以看得出來,文字沒有 Clear Type 的效果
而且放大之後會失真

接下來再看新文字引擎旋轉文字的效果圖
可以保有 Clear Type 的效果,放大也不會失真
但是新的 Text Engine API 真的挺複雜的 ~

假如想用 3D Engine 旋轉文字,但是又不失真怎麼辦?
其實也不難,只要多包一層 Sprite
在外層作 3D 旋轉就好了~

package {
 import flash.display.MovieClip;
 import flash.display.Sprite;
 import flash.text.TextField;
 import flash.text.TextFieldAutoSize;

 [SWF(width=300, height = 200, backgroundColor = "#FFFFFF")]

 public class AS3RotateText03 extends MovieClip {

  public function AS3RotateText03() {
   var txt:TextField = new TextField();
   txt.autoSize = TextFieldAutoSize.LEFT;
   txt.text = "旋轉文字測試 - Ticore's Blog";
   txt.scaleX = txt.scaleY = 2;
   
   var sp:Sprite = new Sprite();
   sp.x = 10;
   sp.y = 30;
   sp.rotationZ = 20;
   sp.addChild(txt);
   this.addChild(sp);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

執行效果:

看上去,只是少了 Clear Type 而已
這樣總結來看,在不嵌入字體情況下
想要做點陣風? 想要不失真? 想要 Clear Type? 通通都有辦法做得到~
真是富有彈性啊!

相關連結:
SWF10 移除物件 3D 屬性
AS3 - BitmapText 程式分享

Read more...

2009年3月9日星期一

Linux 上 Adobe AIR 成熟度遠高於 Flash Player Plugin ?!   [+/-]

Ticore's Blog

在 Linux 上 Flash Player Plugin 不是比 Adobe AIR 早出很久嘛?
沒想到最新版的 Flash Plugin 10.0.22.87 還無法完整支援 SCIM 多國語言輸入法
但是 Adobe AIR 早就已經可以了喔!

文字欄位輸入應該是 Flash Player 內基本的功能
通常會在 Flash Player 先 Fix,然後才 Porting 到 Adobe AIR 上
可是現在居然反過來了
由此可以看得出來 Adobe 相當偏心喔

Linux Flash Plugin 10.0.22.87 & SCIM

Linux Adobe AIR 1.5.0.7620 & SCIM

Read more...

2009年3月7日星期六

ActionScript Scale9Grid 使用技巧   [+/-]

Ticore's Blog

Flash Player 從 version 8 開始支援九宮格縮放 (Scale 9 Grid) 到現在
限制仍頗多
像是遇到 Mask, Child MovieClip, Bitmap... 會失效
也不太容易用 ActionScript 動態建立完整的九宮格縮放功能
以下分享如何成功應用 Scale 9 Grid 到 AS 動態建立的向量線段

先來看兩段測試程式:

AcrionScript 3.0 Scale9Grid Test Code:

import flash.display.MovieClip;
import flash.display.Graphics;

var mc:MovieClip = new MovieClip();
mc.x = 50;
mc.y = 50;
this.addChild(mc);

var mcGrap:Graphics = mc.graphics;
var i:Number = 0;

// Draw cross lines
mcGrap.lineStyle(2, 0xFF0000, 0.5, true);
mcGrap.moveTo(0, 0);
for (i = 1 ; i <= 100 ; ++i) {
 mcGrap.lineTo(i, i);
}

mcGrap.moveTo(0, 100);
for (i = 1 ; i <= 100 ; ++i) {
 mcGrap.lineTo(i, (100 - i));
}

mcGrap.lineStyle(2, 0x0000FF, 0.5, true);
mcGrap.moveTo(0, 0);
mcGrap.lineTo(100, 100);

mcGrap.moveTo(100, 0);
mcGrap.lineTo(0, 100);


// Draw chessboard lines
mcGrap.lineStyle(2, 0, 0.4, true);

for (i = 0 ; i <= 10 ; ++i) {
 mcGrap.moveTo(i * 10, 0);
 mcGrap.lineTo(i * 10, 100);
 mcGrap.moveTo(0, i * 10);
 mcGrap.lineTo(100, i * 10);
}

mcGrap.moveTo(50, 0);
mcGrap.lineTo(50, 100);

mcGrap.moveTo(0, 50);
mcGrap.lineTo(100, 50);

// Set scale9Grid
mc.scale9Grid = new Rectangle(0.05, 0.05, 30, 99.9);
mc.width = 200;

// Ticore's Blog - http://ticore.blogpsot.com/

AcrionScript 2.0 Scale9Grid Test Code:

import flash.geom.*;

var mc:MovieClip = this.createEmptyMovieClip("mc", 100);

mc._x = 50;
mc._y = 50;
var i:Number = 0;

// Draw cross lines
mc.lineStyle(2, 0xFF0000, 50, true);
mc.moveTo(0, 0);
for (i = 1 ; i <= 100 ; ++i) {
 mc.lineTo(i, i);
}

mc.moveTo(0, 100);
for (i = 1 ; i <= 100 ; ++i) {
 mc.lineTo(i, (100 - i));
}

mc.lineStyle(2, 0x0000FF, 50, true);
mc.moveTo(0, 0);
mc.lineTo(100, 100);

mc.moveTo(100, 0);
mc.lineTo(0, 100);

// Draw chessboard lines
mc.lineStyle(2, 0, 40, true);

for (i = 0 ; i <= 10 ; ++i) {
 mc.moveTo(i * 10, 0);
 mc.lineTo(i * 10, 100);
 mc.moveTo(0, i * 10);
 mc.lineTo(100, i * 10);
}

mc.moveTo(50, 0);
mc.lineTo(50, 100);

mc.moveTo(0, 50);
mc.lineTo(100, 50);

// Set scale9Grid
mc.scale9Grid = new Rectangle(1, 1, 30, 98);
mc._width = 200;

// Ticore's Blog - http://ticore.blogpsot.com/

以上兩個測試程式分別使用 AS2.0, AS3.0 動態繪製向量線段
並且套用 Scale 9 Grid 效果
縮放之前應該會長的像這樣:

寬度放大兩倍之後~

從圖中應該可以很清楚的看到
為什麼紅色交叉線可以成功套用九宮格縮放
藍線卻不行

藍線是很簡單的兩點構成一線段
可是紅線卻是用迴圈,畫出 100 小線段組成的
假如用越多的線段來作,相對的 Scale 9 縮放效果也會越細膩
當然也會越耗資源~

這樣應該可以知道 Scale 9 Grid 計算方式
其實是只有向量線段節點的部分,才能被用來作 Scale 9 縮放運算
Flash Player 根據運算後的節點重新繪製線段

另外還有 scale9Grid 使用限制
指定的 Rectangle 座標範圍,必須比 MovieClip (DisplayObject) 圖像的矩形範圍略小一個精度單位
e.g. AS2 是 1 px, AS3 是 1/20 px
否則九宮格縮放會無效,AS3 也會丟出錯誤訊息

ArgumentError: Error #2004: 有一個參數無效。
 at flash.display::DisplayObject/set scale9Grid()
 at AS3Scale9GridTrick_fla::MainTimeline/frame1()

相關連結:
Tween Effect & Scale 9 Grid Redraw Bug
在 Flash 作點陣圖九宮格縮放技巧

Read more...

2009年3月5日星期四

Qt 4.5 + WebKit + Flash Player   [+/-]

Ticore's Blog

Qt4.5 終於正式發表了
整合了 WebKit,同時也支援 NSAPI Plugin,包含 Adobe Flash Player Plugin
這功能等好久了,之前的 Qt4.5 rc, beta 版從來沒有一次成功跑起來
正式版終於成功了~

除此之外,也能夠直接在 WebKit 頁面上插入 Qt 組件並且與之互動
儼然像是 Adobe AIR 的翻版
並且可以自行擴充 Native Library

雖然是正式版,不過隨便測一下就發現 Bug 了
WebKit 瀏覽器好像少送了 resize 事件給 Flash Plugin
還有更嚴重的 Bug,Qt 4.5 WebKit 內的 Flash Player 居然無法輸入文字!
看樣子 Qt 4.5 也是半調子的支援 Flash Plugin

Read more...

2009年3月3日星期二

AIR JavaScript Runtime 的物件型別   [+/-]

Ticore's Blog

Adobe AIR Mashup Runtime 這麼神奇
那接下來從 ActionScript 3.0 的角度來觀察一下 JavaScript Runtime 的物件型別吧
一方面也是因為 AS3.0 的反射機制比 JavaScript 強多了

AIR ActionScript Document Class:

package {
 import flash.display.MovieClip;
 import flash.events.Event;
 import flash.html.HTMLLoader;
 import flash.system.ApplicationDomain;
 import flash.utils.*;
 
 public class main extends MovieClip {
  
  public static var htmlLdr:HTMLLoader = new HTMLLoader();
  
  public var htmlContent:String = "";
  
  public function main() {
   htmlContent += "<script type='text/javascript'>";
   htmlContent += "function fun() {};";
   htmlContent += "</script>";
   
   htmlLdr.placeLoadStringContentInApplicationSandbox = true;
   htmlLdr.addEventListener(Event.COMPLETE, onHTMLLoadComplete);
   addChild(htmlLdr);
   htmlLdr.loadString(htmlContent);
  }
  
  public function onHTMLLoadComplete(evtObj:Event):void {
   trace(describeType(htmlLdr.window).@name);
   // flash.html::__HTMLScriptObject
   trace(describeType(htmlLdr.window.document).@name);
   // flash.html::__HTMLScriptObject
   trace(describeType(htmlLdr.window.alert).@name);
   // flash.html::__HTMLScriptFunction
   trace(describeType(htmlLdr.window.Date).@name);
   // flash.html::__HTMLScriptFunction
   trace(describeType(htmlLdr.window.runtime).@name);
   // flash.html.script::Package
   
   var app:ApplicationDomain = ApplicationDomain.currentDomain;
   trace(app.hasDefinition("flash.html::__HTMLScriptFunction"));
   // false
   trace(app.hasDefinition("flash.html::__HTMLScriptObject"));
   // false
   trace(app.hasDefinition("flash.html.script::Package"));
   // true
   
   var packageClass:Object = getDefinitionByName("flash.html.script::Package");
   trace(describeType(packageClass));
   
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

從輸出結果可以發現,除了共通的基礎型別之外
在 AIR JS 對應到 AS 的物件主要就是這兩種

flash.html::__HTMLScriptObject
flash.html::__HTMLScriptFunction

AIR JS Mashup 最重要的溝通管道 window.runtime
居然是繼承自 Proxy 的 flash.html.script::Package

<type name="flash.html.script::Package" base="Class"
      isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.html.script::Package">
    <extendsClass type="flash.utils::Proxy"/>
    <extendsClass type="Object"/>
    <constructor>
      <parameter index="1" type="flash.html.script::Package" optional="false"/>
      <parameter index="2" type="String" optional="false"/>
      <parameter index="3" type="flash.system::ApplicationDomain" optional="false"/>
    </constructor>
  </factory>
</type>

然而這些特殊的 Class,都是無法直接建立實體的

Adobe AIR runtime version: 1.5

相關連結:
AIR - 詭異的類別物件比較結果
純程式建立 AIR AS3-JS 混搭的簡單範例
在 AIR Javascript 中使用 Vector
AIR - ActionScript, JavaScript 混搭技巧
AIR - 如何區分 JavaScript 與 ActionScript 物件
Adobe AIR Namespace Bug
AIR - JavaScript 與 ActionScript 之間物件的傳遞

Read more...

2009年3月2日星期一

Flex 技巧 - 緊密無縫的 DividedBox 2   [+/-]

Ticore's Blog

再承上次的 Flex 技巧 - 緊密無縫的 DividedBox
只有用 MXML 就做到了,簡單但是有缺點
比較缺乏彈性與可能會遇到潛在的臭蟲
這次分享比較正式的做法,藉由覆寫 DividedBox、BoxDivider Class 來作到

MyDividedBox.as:

package {
 import mx.containers.DividedBox;

 public class MyDividedBox extends DividedBox {

  public function MyDividedBox() {
   super();
   this.dividerClass = MyBoxDivider;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

MyBoxDivider.as:

package {

 import flash.filters.BlurFilter;
 
 import mx.containers.DividedBox;
 import mx.containers.dividedBoxClasses.BoxDivider;

 public class MyBoxDivider extends BoxDivider {

  protected var blurFilter:BlurFilter = new BlurFilter(0, 0);
  public function MyBoxDivider() {
   super();
   this.filters = [blurFilter];
  }

  override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
   if (isNaN(width) || isNaN(height))
    return ;
   if (!parent)
    return ;
    
   var gap:Number = DividedBox(owner).direction == "vertical" ? DividedBox(owner).getStyle("verticalGap")
    : DividedBox(owner).getStyle("horizontalGap");
    
   if (gap >= 6) {
    super.updateDisplayList(unscaledWidth, unscaledHeight);
   }
   
   graphics.clear();
   graphics.beginFill(0x000000, 0);
   graphics.drawRect(0, 0, width, height);
   graphics.endFill();

   var color:Number;
   var alpha:Number = 1.0;
   var thickness:Number = getStyle("dividerThickness");

   color = getStyle("dividerColor");
   alpha = getStyle("dividerAlpha");

   graphics.beginFill(color, alpha);
   if (DividedBox(owner).direction == "vertical") {
    var visibleHeight:Number = thickness;
    var y:Number = (height - visibleHeight) / 2;
    graphics.drawRect(0, y, width, visibleHeight);
    blurFilter.blurX = 0;
    blurFilter.blurY = gap + 1;
   } else {
    var visibleWidth:Number = thickness;
    var x:Number = (width - visibleWidth) / 2;
    graphics.drawRect(x, 0, visibleWidth, height);
    blurFilter.blurX = gap + 1;
    blurFilter.blurY = 0;
   }
   this.filters = [blurFilter];
   graphics.endFill();
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

TinyGapDividedBoxByDivider.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF"
    fontSize="12" paddingTop="5" paddingBottom="5" paddingLeft="5"
    paddingRight="5">

 <mx:Panel width="100%" height="100%" layout="absolute" title="Tiny Gap DividedBox by Override BoxDivider">

  <local:MyDividedBox xmlns:local="*" direction="horizontal" width="100%"
       height="100%" dividerAffordance="7"
       dividerThickness="7" dividerAlpha="0.3" horizontalGap="1">
   <mx:Tree id="myTree" width="30%" height="100%" borderThickness="0"
      labelField="@label" showRoot="false" dataProvider="{treeData}"/>

   <mx:DataGrid id="dg" width="70%" height="100%" borderThickness="0"
       rowCount="5" dataProvider="{employees}">
    <mx:columns>
     <mx:DataGridColumn dataField="name" headerText="Name"/>
     <mx:DataGridColumn dataField="phone" headerText="Phone"/>
     <mx:DataGridColumn dataField="email" headerText="Email"/>
    </mx:columns>
   </mx:DataGrid>

  </local:MyDividedBox>
  <mx:Canvas x="{myTree.width}" width="1" height="100%" backgroundColor="#505050"
       mouseEnabled="false"/>

  <mx:ControlBar>
   <mx:Text width="100%" textAlign="right">
    <mx:htmlText>
     <![CDATA[<a target="_blank" href="http://ticore.blogspot.com/">]]>
     <![CDATA[Ticore's Blog - http://ticore.blogspot.com/</a>]]>
    </mx:htmlText>
   </mx:Text>
  </mx:ControlBar>

 </mx:Panel>

 <mx:XMLList id="treeData">
  <node label="Mail Box">
   <node label="Inbox">
    <node label="Marketing"/>
    <node label="Product Management"/>
    <node label="Personal"/>
   </node>
   <node label="Outbox">
    <node label="Professional"/>
    <node label="Personal"/>
   </node>
   <node label="Spam"/>
   <node label="Sent"/>
  </node>
 </mx:XMLList>

 <mx:XMLList id="employees">
  <employee>
   <name>Christina Coenraets</name>
   <phone>555-219-2270</phone>
   <email>ccoenraets@fictitious.com</email>
  </employee>
  <employee>
   <name>Joanne Wall</name>
   <phone>555-219-2012</phone>
   <email>jwall@fictitious.com</email>
  </employee>
  <employee>
   <name>Maurice Smith</name>
   <phone>555-219-2012</phone>
   <email>maurice@fictitious.com</email>
  </employee>
  <employee>
   <name>Mary Jones</name>
   <phone>555-219-2000</phone>
   <email>mjones@fictitious.com</email>
  </employee>
 </mx:XMLList>

</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

Tiny Gap DividedBox 線上範例:

相關連結:
Flex 技巧 - 緊密無縫的 DividedBox
Flex DividedBox Skin 小技巧

Read more...