2007-12-14

AIR beta3, Flex 3 beta 3, BlazeDS beta

Adobe labs 昨天發佈的 beta

Flex 3 beta 3 應該是正式版前最後的公開測試版

BlazeDS 是新釋出的開源專案, 功能只包含部份的 LCDS(LiveCycleR Data Services) ES 功能。 AMF3 spec 也一併釋出了。
LCDS ES 應該還是商業版, 又是開源版輔助商業版的策略。

2007-12-09

Free CSS templates and pictures

資料來源: Lynch Consulting Blog

free CSS templates
Free Public Domain Photo Database

AUG 2007 年底研討AS3 投影片

投影片和相關檔案在這裡
index.swf 為投影片檔, 左右鍵為上一張下一張, 向上鍵為目錄頁

2007-12-04

我終於明白

看到這一篇「黑暗界拍賣王:失森購物台
我終於明白, 為什麼我以前的書都不賣 ..... 原來沒有夜光封面 :P
黑暗界拍賣王 blog 吃飯的時候最好別看

2007-12-03

將 JPG 檔案資料加入 SWF, 並讓 SWF 載入自己

Appending binary data of a JPG file to a swf file.
我們可以將 SWF 檔後接一個圖檔資料 (別的格式當然也行),然後再利用 SWF 讀取自己, 把圖秀出來。這樣做的優點是, 可以動態組合不同內容的 SWF, 而且包成一個檔, 攜帶方便。
找了 JPG 、 PNG 圖檔格式和 SWF 檔案格式, 如下:

Jpeg 檔案格式:
JPEG Header Information
JPG File Header Format

PNG 檔案格式:
怎樣才是好的 File Format Header
Designing File Formats

SWF 檔案格式:
Alexis' SWF Reference
SWF File Format Specification (內容有點舊)
Adobe 官方資料

然而由於無法直接從 SWF 檔頭得知壓縮後的 SWF 大小, 所以放棄使用原有檔案格式的標記,改用自己增加設定。以下是合併檔案的 PHP 語法:
<?php
$fw = fopen("merged.swf", "wb");
$fn0 = "read_self.swf";
$fn1 = "hippocampus.jpg";
$fr0 = fopen($fn0, "rb");
$fr1 = fopen($fn1, "rb");
$content0 = fread($fr0, filesize($fn0));
$content1 = fread($fr1, filesize($fn1));

fwrite($fw, $content0);
fwrite($fw, '-----'); // add a specific mark
fwrite($fw, $content1);

fclose($fr0);
fclose($fr1);
fclose($fw);
?>

載入自己的那個 FLA frame actions:
var MyUrl:String = new LoaderInfo().url;
var lastSlash:int = MyUrl.lastIndexOf("/");
var selfName:String = MyUrl.slice(lastSlash+1);

var urlr:URLRequest = new URLRequest(selfName);
var urll:URLLoader = new URLLoader;
urll.dataFormat = URLLoaderDataFormat.BINARY;
urll.load(urlr);
urll.addEventListener(Event.COMPLETE, loadFinished);

function loadFinished(e:Event):void {
var ba:ByteArray = urll.data;
while (true) {
if (ba.readByte() == 45) {
if (ba.readByte() == 45) {
if (ba.readByte() == 45) {
if (ba.readByte() == 45) {
if (ba.readByte() == 45) {
break;
}
}
}
}
}
}

var ldr:Loader = new Loader;
var img_ba:ByteArray = new ByteArray;
ba.readBytes(img_ba);
this.addChild(ldr);
ldr.loadBytes(img_ba);
}

相關檔案下載

2007-11-30

AS3 AMF 基礎教學

The ABC's of AMF 簡單明瞭的說明範例。
下個月可能會有 AMF 的大新聞。

2007-11-29

Google 的 My Location 技術

有文有影片的報導
Never lost with Google Maps Mobile and My Location technology

看樣子將會有一堆 Google 的手機服務能把 G-phone 拱上天。

「Flash CS3 ActionScript 3.0 應用程式設計」圖片對照

收到「Flash CS3 ActionScript 3.0 應用程式設計」版權書了, 不過發現裡面的圖都比較深色, 問企編得到的答案是「油墨加重, 而且紙張是象牙白, 所以視覺上會變得更黑」。

其實有部份的圖應該印成彩色才適當, 不過因為售價及成本的關係, 又是偏程式書, 所以印成黑白書 (嘖! 定價520, 天瓏才賣406, 不知道有沒有算錯)。

為了讀者方便, 用昨天介紹的 BulkLoader 和書中的範例, 兜一個小相本用以查看書中的範例圖 (不包含圖說)。由於使用國外便宜的空間所以速度較慢, 敬請見諒。

「Flash CS3 ActionScript 3.0 應用程式設計」圖片對照

2007-11-28

AS3 BulkLoader 好用的載入工具

專案 BulkLoader @ Google Code
drawlogic 介紹 BulkLoader
已具備的功能特色:
1) Connection pooling.
2) Unified interface for different loading types.
3) Cache managing.
4) Statistics about loading (latency, speed, average speed).

2007-11-27

Adobe User Group TW (MMUG) 網聚


活動公告
報名處
qop 負責介紹 AS2 -> AS3 所應注意的地方 (入門討論) :D

2007-11-26

簡單保護SWF (AS3)

Protect your SWF files
由上一篇可知, 我們可以把 SWF 切成幾個檔案, 弄亂檔案名稱編號, 再依序載入。除了切割檔案外, 也可以對分割後的檔案添油加醋, 做些處理, 載入後再去除。
這種做法的主要前提是, AS3 反譯器還未出來之前可以用這樣的方式。
以下是載入的語法參考:
var files:Array = [4,5,6,7,0,1,2,3];
var filename_head = "weather_info";
var filename_tail = ".jpg";
var urlr:Array = [];
var urll:Array = [];
for (var i:int=0; i < files.length; i++) {
urlr[i] = new URLRequest(filename_head+ files[i] +filename_tail);
urll[i] = new URLLoader;
urll[i].dataFormat = URLLoaderDataFormat.BINARY;
urll[i].load(urlr[i]);
urll[i].addEventListener(Event.COMPLETE, loadFinished);
}

var loadCount:int = 0;
function loadFinished(e:Event):void {
loadCount++;
if (loadCount == files.length) {
var ba:ByteArray = new ByteArray;
for(var i:int =0; i < files.length; i++){
ba.writeBytes(urll[i].data);
}
var loader:Loader = new Loader;
this.addChild(loader);
loader.loadBytes(ba);
}
}


Demo

相關檔案下載

載入部份SWF取得資料 (AS3)

Loading a fragment including header of the SWF file
SWF 檔案結構是依照影格順序, 在被載入的 SWF 的第 1 影格定義一個陣列 ar, 然後使用璃樹無(http://luna.fc2.com/)將 SWF 分割成小檔案, 取第一個載入。
利用下列程式就可以取得 ar 陣列的內容。
var urlr0:URLRequest = new URLRequest("file_000.jpg");
var urll0:URLLoader = new URLLoader;
urll0.dataFormat = URLLoaderDataFormat.BINARY;
urll0.load(urlr0);
urll0.addEventListener(Event.COMPLETE, loadFinished);

var ldr:Loader = new Loader();
function loadFinished(e:Event):void{
ldr.loadBytes(urll0.data);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,
function(e:Event){
trace( ldr.content['ar']);
});
}

相關檔案下載

2007-11-23

Aptana Studio 1.0 設定 UTF-8 編碼



1) 點選指令選單上 Window > Preferences...
2) 在面板左側點選 General > Workspace
3) 在右下方的 Text file encoding 點選 other, 設定為「UTF-8」即可。

2007-11-22

載入外部類別庫

承上篇, CNS2UCS4.as 對編輯器而言檔案實在太大, 不論使用 Flash IDE 或 Flex 去編輯都是不智的選擇。用 Flex 開啟 CNS2UCS4.as 會整個當在那兒, 除非再去調整啟動時 JVM 的設定。相對的, 可以使用 Notepad++ 之類的小巧文字編輯器。
若每次使用都要用 Flash 或 Flex 編譯, 也是件痛苦的事情。可以用 command line 來編譯 (參考) :
C:\Program Files\Adobe\Flex Builder 2\Flex SDK 2\bin>compc -source-path C:\AS3_classes -include-classes CNS2UCS4 -directory=true -debug=false -output C:\AS3_classes\CNS2UCS4
-directory=true的設定可以不包成 swc, 在C:\AS3_classes\CNS2UCS4裡會有 library.swf 那正是我們要的。
FLA 第一格:
stop();
var my_this = this;
var CNS2UCS4:Class;
var ldr:Loader = new Loader();
var ldrContext:LoaderContext = new LoaderContext();
ldrContext.applicationDomain = ApplicationDomain.currentDomain;
ldr.load(new URLRequest("CNS2UCS4/library.swf"), ldrContext);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);

function onComplete(e:Event):void{
CNS2UCS4 = getDefinitionByName('CNS2UCS4') as Class;
gotoAndStop(2);
}
相關檔案下載

2007-11-21

使用 CNS 11643 編碼排序

利用上一篇 CNS11643 和 UCS4 的對照表, 做成類別檔, 用以排序中文字。
由於字碼很多, 只取三萬八千多對編碼, 發佈出來的檔案還是很大 =.=
圖為範例檔執行情形

相關檔案下載

2007-11-20

正體中文 CNS 11643 中文碼

關於 CNS11643 國家標準中文交換碼
CNS11643 與 UCS4 對照表

CNS11643目前除了公家單位之外,很少人使用。
對我來說,其主要的優點是「先筆畫後部首排列順序編碼」和「依字之使用頻率編排於各字面」。

2007-11-14

Quercus: Java 平台上實作 PHP5

Quercus 是 Caucho 公司(就是做 Resin 那家)推出的開源專案
PHP5 的程式當然最好在 PHP5 原生解譯器中執行。然而在千奇百怪的需求下, 或許會用到Quercus。

2007-11-13

「Flash CS3 ActionScript 3.0 應用程式設計」已經出版


前一陣子花了許多時間在編寫此書, blog 就很少更新了 :p

原則上這本書是「ActionScript 2.0 入門與應用」的改版, 不過後半部幾乎是重新寫過, 把一些比較少用的部份拿掉, 加入常用的基本範例。

當然一本書無法滿足所有讀者的需求, 讀者群定位在有點 ActionScript 編寫經驗, 想跨入 ActionScript 3.0 的讀者。對 Developers 是本入門書, 對 Designers 來說可能歸類進階書, 最好翻翻實體書, 再考慮購買吧。

2007,11,29 ---------------
圖片對照發文 圖片對照小相本

2007-11-08

線上點陣圖轉向量圖

史丹佛大學的 VectorMagic 可將點陣圖轉向量圖, 效果看起來比用 Flash 轉要好得多, 其 UI 使用 Flex 建構。

2007-09-12

Flash/AS3 z-index 處理 part 2

承上一篇
3)欲以物件的某個參考值當作 Depth
將 Display Object 和 Depth (參考值) 做成 Object
所有 Object 做成 Object Array, 就可以用 sortOn 幫你排
FLA 原始檔
var numObj:int = 12;
var dang:Number = Math.PI*2/numObj;
var xr:int = 200;
var yr:int = 20;
var shift:Number = 0;
var arObj:Array = [];
for (var i:int = 0; i < numObj; i++) {
arObj[i] = new mc_star;
this.addChild( arObj[i] );
}
this.addEventListener(Event.ENTER_FRAME, mEnterFrame);
function mEnterFrame(e:Event):void {
var _mc:MovieClip;
var ang:Number;
var depth:int;
var depthsRela:Array = [];
for (var i:int = 0; i < numObj; i++) {
ang = i*dang +shift;
_mc = arObj[i] as MovieClip;
_mc.x = xr*Math.cos(ang);
_mc.y = yr*Math.sin(ang);
_mc.scaleX = 0.8 + 0.2*Math.sin(ang);
_mc.scaleY = _mc.scaleX;
var blurN:Number = 4*(1- Math.sin(ang) );
_mc.filters = [new BlurFilter(blurN, blurN, BitmapFilterQuality.HIGH)];
// z-index 的參考值
depth = Math.sin(ang)*1000;
depthsRela.push({d:depth, mc:_mc});

}
// 排序
depthsRela.sortOn("d", Array.NUMERIC);
for (i=0; i < numObj; i++) {
this.setChildIndex(depthsRela[i].mc, i);
}
shift += 0.01;
}

2007-09-11

Flash/AS3 z-index 處理 part 1

z-index 的處理經常遇到的有三種情況, 先提兩種:

1) 將 display object 由原來的 z-index 提到最高值
可以先 removeChild, 再使用 addChild

2) display object 在某些時候要提到最高值, 某些時候要回到原來的 z-index
做個空的 Sprite 物件去佔原來位置, 之後再對調回來
FLA 原始檔
this.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
this.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
function onMouseOver(e:MouseEvent):void{
var _mc:MovieClip = e.target as MovieClip;
var _p:DisplayObjectContainer =
_mc.parent as DisplayObjectContainer;
// 建立佔茅坑者
_mc.occu = new Sprite;
_p.addChild(_mc.occu);
// 交換位置
_p.swapChildren(_mc, _mc.occu);
}
function onMouseOut(e:MouseEvent):void{
var _mc:MovieClip = e.target as MovieClip;
var _p:DisplayObjectContainer =
_mc.parent as DisplayObjectContainer;
// 換回原來的位置
_p.swapChildren(_mc, _mc.occu);
delete _mc.occu;
}

2007-09-06

Adobe 公開預覽 Flash Media Server 3

FMS3 大概 2008 第一季會開賣
官方消息
支援 H.264 和 AAC
支援 Flash Lite 3
伺服端依然使用 AS1, 客戶端不限 AS1 ~ AS3
詳情請看 fms3 faq

2007-09-03

fl.controls.Button 的 click 事件

看樣子 fl 包又出包了 ...
主時間軸上放個 AS3 組件 Button b
以下的兩個事件偵聽器居然有不同的結果
b.addEventListener(MouseEvent.CLICK, lisa);
b.toggle = true;
b.addEventListener(MouseEvent.CLICK, lisb);
function lisa(e:Event) {
trace("lisa:", b.selected);
}
function lisb(e:Event) {
trace("lisb:", b.selected);
}

按一下 b 的結果:
lisa: false
lisb: true

2007-08-24

AlivePDF 0.1 Alpha Release

AlivePDF 用 AS3 動態建立 PDF 文件, 後台使用 PHP。
以後的官網應該會是 http://www.alivepdf.org/

AsWing AS3 version 1.1 released

福樂包 (fl package) 難用嗎? 麥香包 (mx package) 佔太大體積嗎 ?
試試 AsWing
有用過 Java Swing 的人應該會覺得它很好用 ;)

2007-08-16

實現 ActionScript 3 的全域物件 global

把 global.as 放在類別路徑上即可, 其內容為:
package {
public function get global():Object{
return this;
}
}

2007-08-14

22 組 AS3 API

資料來源: List of 22 ActionScript 3.0 API’s
內容:
Adobe APIs
corelib, mappr, flickr, youtube and more.
http://labs.adobe.com/wiki/index.php/ActionScript_3:resources:apis:libraries

APE (Actionscript Physics Engine)
http://www.cove.org/ape/

as3awss3lib
ActionScript 3.0 library for interacting with Amazon S3
http://code.google.com/p/as3awss3lib/

as3soundeditorlib
Actionscript 3.0 library for sound editing
http://code.google.com/p/as3soundeditorlib/

as3ds
AS3 Data Structures For Game Developers
http://code.google.com/p/as3ds/

ASCOLLADA
http://code.google.com/p/ascollada/

As3Crypto
ActionScript 3 Cryptography Library
http://crypto.hurlant.com/

asinmotion
Animation Library for AS3
http://code.google.com/p/asinmotion/

Away3d
http://code.google.com/p/away3d/

ebay API
http://code.google.com/p/as3ebaylib/

facebook-as3
AS3 API to access Facebook's Platform API
http://code.google.com/p/facebook-as3/

flest
Flest Framework for Adobe Flex and ActionScript3 Applications
http://code.google.com/p/flest/

FZip
Actionscript 3 class library to load standard ZIP archives and extract/decompress contained files.
http://codeazur.com.br/lab/fzip/

lastfm-as3
Actionscript 3.0 library to access the Last.fm web services
http://code.google.com/p/lastfm-as3/

MapQuest
http://company.mapquest.com/mqbs/4a.html

mecheye-as3-libraries
A set of ActionScript 3 Libraries, primarily for Flash game development.
http://code.google.com/p/mecheye-as3-libraries/

Papervision3D
http://code.google.com/p/papervision3d/

Salesforce Flex Toolkit
http://wiki.apexdevnet.com/index.php/Flex_Toolkit

Tweener
Full featured animation library
http://code.google.com/p/tweener/

Twitter AS3 API
http://twitter.com/blog/2006/10/twitter-api-for-flash-developers.html

uicomponents-as3
Lightweight AS3 UI component library
http://code.google.com/p/uicomponents-as3/

XIFF
XMPP client library
http://svn.igniterealtime.org/svn/repos/xiff/branches/xiff_as3_flexlib_beta1/

Yahoo AS3 APIs
http://developer.yahoo.com/flash/as3_api_libraries.html

2007-08-13

AS3 計算效能

來源: Optimizations for AS3 calculations
Math 裡的方法, 計算效能似乎都不是最佳的 =.=

2007-08-11

AS3 陣列的 forEach 方法測試

Flash frame AS3:
var ar:Array = ['a','b','c'];

ar.forEach(
function(...args){
trace(args[0], this);
}
, this);

2007-08-02

lighttpd Web Server

號稱跟 apache httpd 相比, 可處理更多的連線的 web server
官網: lighttpd fly light
在 windows 上跑的專案: WLMP Project
支援 flv streaming

2007-07-31

blogger-ext2

給 Blogger 使用的 JS lib: blogger-ext2
Project owner: Racklin's 阿土伯程式大觀園

2007-07-28

Real-Time Messaging with LiveCycle Data Services ES

Real-Time Messaging with LiveCycle Data Services ES

SWFfix: 將 SWF 放入 HTML 的另一種方式

SWFObject 已經很好用了, 但是為了減少對 JavaScript 的依賴, 以及支援更多的平台, 於是有 SWFfix 的出頭。現在有公開測試版了, 相關網址:
SWFfix project
SWFfix.org

2007-07-25

Flexlib

Flexlib 顧名思義提供 Flex 組件, 藉由社群力量, 提供質量皆佳的組件。
相關資料: FlexLib in the wild

2007-07-15

混搭 spry 和 jQuery 時的載入順序

來源網址: SPRY and jQuery load sequence
先載入 SpryData.js, 再載入 jquery.js。

2007-07-12

2007-07-10

2007-07-09

AS3 不支援八進位表示法

Flash CS3 Help 裡的說明: In ActionScript 3.0, the Number() function no longer supports octal, or base 8, numbers.
其實八進位幾乎用不到。

2007-07-06

辛普森 Avatar


Simpsons 電影活動網站提供一個 Avatar 系統, 蠻好玩的。
不過圖生成的速度很慢, 不知道是不是用 Flash 8 做的。

2007-07-05

Flex 的翻頁效果

FlexBook: Flex 翻頁效果的組件, 包含範例和原始檔。

2007-07-04

Mapping Flash video to 3D objects

Adobe 官方的教學, 將影片貼在 3D 的物件上, 使用 Papervision 3D library。

影像變形類別

Ruben Swieringa 提供了影像變形類別, 其 blog 上除了 Demo 還有原始檔文件

2007-07-03

2007-06-29

Export Motion XML 相關訊息

Flash CS3 Export Motion XML Kevin Hoyt
Motion XML || XML Motion scripts for Flash CS3

Flash CS3 的程式碼提示

Flash CS3 的 Code hint 看起來不會比 Flash 8 好 =.=
另外, 在預設的情況下 stage 裡的 instances 會被自動宣告, 所以不能為了要有 code hint 而再宣告一次。
慶幸的是, CS3 和 8 一樣, 可以用多行註解 /* */ 來避開重複宣告, 又可保有 code hint 的功能。

2007-06-28

免費的 Adobe AIR 電子書

書名: Adobe Integrated Runtime (AIR) for JavaScript Developers Pocket Guide (Amazon)
相關訊息: Adobe AIR Free Book Download
下載位址

取得 FLV 內的 header 資料

依據 osFlash 裡 FLV 檔案資料格式的說明, 利用 Flash 開發「取得 FLV 檔頭資料及串流資料」的 AIR app。
要注意的是 meta 裡包含兩個 AMF packets, 所以需使用 ByteArray.readObject() 兩次。
Flash frame AS3:
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;

var file:File;
var fs:FileStream;
var flvFilter:FileFilter = new FileFilter("Flash Video", "*.flv");
var header_ba:ByteArray;
var stream_ba:ByteArray;

function bClick(e:MouseEvent):void {
var targetName:String = e.target.name;
switch (targetName) {
case "open_btn" :
file = new File();
file.browseForOpen("Open", [flvFilter]);
file.addEventListener(Event.SELECT, readFLVHeader);
break;
case "show_btn" :
readStreamHeader();
break;
case "close_btn" :
fs.close();
break;
}
}
open_btn.addEventListener(MouseEvent.CLICK, bClick);
show_btn.addEventListener(MouseEvent.CLICK, bClick);
close_btn.addEventListener(MouseEvent.CLICK, bClick);


function readFLVHeader(e:Event) {
filename_txt.text = file.nativePath;
fs = new FileStream();
fs.open(file, FileMode.READ);

// read FLV Header
header_ba = new ByteArray();
fs.readBytes(header_ba, 0, 9);
main_txt.text = "Signature: "+ header_ba.readMultiByte(3, "") +"\n";
main_txt.appendText("Version: "+ header_ba.readUnsignedByte()+"\n");
main_txt.appendText("Flags: "+ header_ba.readUnsignedByte()+"\n");
main_txt.appendText("Offset: "+ header_ba.readUnsignedInt()+"\n");
main_txt.appendText("---\n");
}
function readStreamHeader() {
stream_ba = new ByteArray();
fs.readBytes(stream_ba, 0, 15);

main_txt.appendText("PreviousTagSize: "+ stream_ba.readInt()+" ----\n");
var type:uint = stream_ba.readUnsignedByte();
main_txt.appendText("Type: "+ type +"\n");
// 取 3 bytes
var bodyLength:uint = stream_ba.readUnsignedShort()<<8 | stream_ba.readUnsignedByte();
main_txt.appendText("BodyLength: "+ bodyLength +"\n");
var timestamp:uint = stream_ba.readUnsignedShort()<<8 | stream_ba.readUnsignedByte();
main_txt.appendText("Timestamp: "+ timestamp +"\n");
main_txt.appendText("Padding: "+ stream_ba.readUnsignedInt()+"\n");
if (type == 0x12) {
var t_ba:ByteArray = new ByteArray();
fs.readBytes(t_ba, 0, bodyLength);
// 設定 AMF 的格式, 即使是 on2 VP6 應該還是舊的
t_ba.objectEncoding = ObjectEncoding.AMF0;
// 第一個 AMF 物件是事件處理器的資料
var obj:Object = t_ba.readObject();
var str:String = QopDump.go( obj );
main_txt.appendText("***\nEvent handler:"+str+"\n***\n");
obj = t_ba.readObject();
str = QopDump.go( obj );
main_txt.appendText(str+"\n");
} else {
// skip the body
fs.position += bodyLength;
}
main_txt.verticalScrollPosition = main_txt.maxVerticalScrollPosition;
}

FLV 的第一個 stream unit 應該都是 meta。較舊 FLV 的 meta 大多有問題, 沒有提供仔細而實用的資料。

較新格式的 FLV 其 Flags 通常是 13 而不是 5。


原始檔: parseFLV.fla
安裝檔: parseFLV.air

AS3 TextArea 組件的文件說明有誤

屬性沒有: scrollV, scrollH, maxScrollV, maxScrollH.
分別對應的應為:
verticalScrollPosition
horizontalScrollPosition
maxVerticalScrollPosition
maxHorizontalScrollPosition

2007-06-27

Aptana IDE: AJAX 整合開發環境

Aptana IDE 以 Eclipse 為基礎的 AJAX 整合開發環境
可以和 Flex Builder 併在一起使用
另外也支持 Adobe AIR 的開發

利用 NativeDragEvent, 以拖拉放的方式開啟檔案

參考網頁: Simple Drag and Drop AIR
依據上一篇: Adobe AIR Simple Text Editor 再加上拖曳開檔的功能
Flash frame actions:
import flash.events.NativeDragEvent;
import flash.desktop.DragManager;
import flash.desktop.DragActions;
import flash.desktop.TransferableFormats;
import flash.desktop.TransferableData;

this.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER,onDragIn);
this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP,onDrop);
this.addEventListener(NativeDragEvent.NATIVE_DRAG_EXIT,onDragExit);

function onDragIn(event:NativeDragEvent):void {
// acceptDragDrop() 只能在 nativeDragEnter 或 nativeDragOver 事件處理器上使用
DragManager.acceptDragDrop(this);
}

function onDrop(event:NativeDragEvent):void {

// 下行若沒設定, 順序會是 copy, move, link
DragManager.dropAction = DragActions.COPY;
var tfd:TransferableData = event.transferable as TransferableData;
var dropfiles:Array = tfd.dataForFormat(TransferableFormats.FILE_LIST_FORMAT) as Array;
// 只取一個檔案
var sourceFile:File = dropfiles[0];
file = new File();
file.nativePath = sourceFile.nativePath;
filename_txt.text = file.nativePath;

fs = new FileStream();
fs.open(file, FileMode.READ);
var str:String = fs.readMultiByte(fs.bytesAvailable, "utf-8");
main_txt.text = str.replace( new RegExp(File.lineEnding, "g"), "\n");
fs.close();
}
function onDragExit(event:NativeDragEvent):void {
trace("Drag exit event.");
}

原始檔: test_dragAndDrop.fla

2007-06-26

Adobe AIR Simple Text Editor


這個例子主要是用來測試 File.browseForOpen 的功能
缺點還很多, 包含只能讀寫 utf-8 編碼的檔案

Flash frame actions:
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;

var file:File;
var fs:FileStream;
var textFilter:FileFilter = new FileFilter("Text", "*.txt");
file = new File("app-resource:/temp.txt");
filename_txt.text = file.nativePath;

function bClick(e:MouseEvent):void {
var targetName:String = e.target.name;
switch (targetName) {
case "new_btn" :
file = new File("app-resource:/temp.txt");
filename_txt.text = file.nativePath;
main_txt.text = "";
break;
case "load_btn" :
file = new File();
file.browseForOpen("Open", [textFilter]);
file.addEventListener(Event.SELECT, onSelectOpenFile);
break;
case "save_btn" :
fs = new FileStream();
fs.open(file, FileMode.WRITE);
fs.writeMultiByte(main_txt.text, "utf-8");
fs.close();
break;
case "saveas_btn" :
file = new File();
file.browseForSave("Save as");
file.addEventListener(Event.SELECT, onSelectWriteFile);
break;
}
}
new_btn.addEventListener(MouseEvent.CLICK, bClick);
load_btn.addEventListener(MouseEvent.CLICK, bClick);
save_btn.addEventListener(MouseEvent.CLICK, bClick);
saveas_btn.addEventListener(MouseEvent.CLICK, bClick);

function onSelectOpenFile(e:Event) {
filename_txt.text = file.nativePath;
fs = new FileStream();
fs.open(file, FileMode.READ);
var str:String = fs.readMultiByte(fs.bytesAvailable, "utf-8");
// 替換 換行符號
main_txt.text = str.replace( new RegExp(File.lineEnding, "g"), "\n");
fs.close();
file.removeEventListener(Event.SELECT, onSelectOpenFile);
}
function onSelectWriteFile(e:Event) {
filename_txt.text = file.nativePath;
fs = new FileStream();
fs.open(file, FileMode.WRITE);
fs.writeMultiByte(main_txt.text, "utf-8");
fs.close();
file.removeEventListener(Event.SELECT, onSelectWriteFile);
}


原始檔: test_browseForOpen.fla

2007-06-23

AIR local database 測試

Flash frame AS3:
import flash.data.SQLResult;
import flash.filesystem.File;
import flash.data.SQLStatement;
import flash.data.SQLConnection;
import flash.events.SQLEvent;
import flash.events.SQLErrorEvent;
import flash.errors.SQLError;
import fl.data.DataProvider;

var dbFile:File = new File("app-resource:/test01.db");
var dbConn:SQLConnection = new SQLConnection();
var dbStatement:SQLStatement;
var insertCount:uint = 0;
dbConn.addEventListener(SQLEvent.OPEN, onDBOpened);
dbConn.addEventListener(SQLErrorEvent.ERROR, onDBError);
// 若檔案不存在, 會自動建立
dbConn.open(dbFile);

function onDBOpened(e:SQLEvent) {
trace("onDBOpened:", e);
if (e.type == SQLEvent.OPEN) {
dbStatement = new SQLStatement();
dbStatement.sqlConnection = dbConn;
dbStatement.text = "select * from Users";
dbStatement.addEventListener(SQLEvent.RESULT, onSQLResult);
dbStatement.addEventListener(SQLErrorEvent.ERROR, onSQLError);
dbStatement.execute();
}
}

function onDBError(e:SQLErrorEvent) {
trace("onDBError:", e);
}

function onSQLResult(e:SQLEvent) {
trace("onSQLResult:", e);
var d:Array = dbStatement.getResult().data;
QopDump.echo(d);
dataGrid.dataProvider = new DataProvider(d);
dbConn.close();
}

function onSQLError(e:SQLErrorEvent) {
trace("onSQLError:", e);

var err:SQLError = e.error;
trace("Error Code:", err.code);
trace("Operation:", err.operation);
trace("Error Message:", err.message, "\n");
if (err.message.indexOf("no such table") != -1) {
dbStatement = new SQLStatement();
dbStatement.sqlConnection = dbConn;
dbStatement.text = "CREATE TABLE Users "+
"(id INTEGER PRIMARY KEY, username TEXT, password TEXT);";
dbStatement.addEventListener(SQLEvent.RESULT, doInsert);
dbStatement.addEventListener(SQLErrorEvent.ERROR, onSQLError);
dbStatement.execute();
}
}

function doInsert(e:SQLEvent) {
insertCount++;
if(insertCount>3) return;
dbStatement = new SQLStatement();
dbStatement.sqlConnection = dbConn;
var sql:String;
switch (insertCount) {
case 1 :
sql = "INSERT INTO Users VALUES(null,'MyName','MyPassword');";
break;
case 2 :
sql = "INSERT INTO Users VALUES(null,'qop','qop543');";
break;
case 3 :
sql = "INSERT INTO Users VALUES(null,'小黑','出運了');";
break;
}
dbStatement.text = sql;
dbStatement.addEventListener(SQLEvent.RESULT, doInsert);
dbStatement.execute();
}

執行第一次的結果 (由無到有建立DB):

執行第二次的結果 (取得資料秀在 DataGrid 上):

AIR local database

AIR 內含 SQLite SQL database engine
每個資料庫都以一個檔案實體存在
官網: SQLite home page
工具: SQLite Database Browser, SQLite Control Center

2007-06-22

AirWaves: 使用 Adobe AIR 開發的 IM

相關訊息:
AirWaves
AirWaves will use XMPP / Jabber for it’s messaging

AIR 存圖測試

Flash Frame Actions:
import com.adobe.images.JPGEncoder;
import com.adobe.images.PNGEncoder;
import flash.filesystem.*;

jpg_btn.addEventListener(MouseEvent.CLICK, saveImg);
png_btn.addEventListener(MouseEvent.CLICK, saveImg);

function saveImg(e:MouseEvent):void {
var tname = e.target.name;
var file:File = File.applicationResourceDirectory;

var bpd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
var ba:ByteArray;
bpd.draw(root);

if(tname == "jpg_btn"){
var jpg:JPGEncoder = new JPGEncoder(80);
ba = jpg.encode(bpd);
file = file.resolve("test.jpg");
}else if(tname == "png_btn"){
ba = PNGEncoder.encode(bpd);
file = file.resolve("test.png");
}

var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(ba);
fileStream.close();
}

原始檔: saveImgFile.fla (as3corelib 已經包含在原始檔內)

2007-06-21

as3corelib

as3corelib: ActionScript 3.0 library for several basic utilities.
裡面的工具都很有用, 包含常用的 JPGEncoder, JSON, MD5, PNGEncoder, SHA1.

在 Flash IDE 使用, 大多使用類別原始碼, 也可以使用 SWC. 以下是使用 SWC 的方式
1. 把 corelib.swc 放在 Flash CS3 安裝目錄的 en\Configuration\Components.
2. 開啟 Flash CS3.
3. 在 components 面板裡可以看到「standard components」>「DateFormatter」.
4. 把「DateFormatter」放在文件的元件庫即可.

2007-06-20

標籤雲的作法

中文標籤雲
Label Cloud
phydeaux3 上面有太多恐怖的東西 ...

Adobe AIR Developer Derby

AIR 開發大賽
Adobe AIR Developer Derby

package a flash app as an AIR file (for windows)

請參考 Create AIR Apps in Flash CS3 在 Flash CS3 中安裝 Test in Apollo
下載並解開 package_app_as_an_AIR_file.zip
然後將修改後的檔案蓋過
在 Flash CS3 開啟文件, 再點選「Commands」>「package app as an AIR file」即可
查看一下是否有 .air 生成
當然也可以用手動的方式, 參考 adt 的使用

AIR 存檔測試

Flash Frame Actions:
import flash.filesystem.*;
// var file:File = File.documentsDirectory; // 我的文件
var file:File = File.applicationResourceDirectory; // 應用程式所在的目錄
file = file.resolve("test.txt");
trace(file.nativePath); // 於 DOS 視窗輸出

function doSave(e:MouseEvent):void {
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.UPDATE);
// File.systemCharset 為系統編碼
//fileStream.writeMultiByte(_txt.text, File.systemCharset);
fileStream.writeMultiByte(_txt.text, "utf-8");
fileStream.close();
}
function doLoad(e:MouseEvent):void {
var fileStream:FileStream = new FileStream();
try{
fileStream.open(file, FileMode.READ);
//_txt.text = fileStream.readMultiByte(file.size, File.systemCharset);
_txt.text = fileStream.readMultiByte(file.size, "utf-8");
}catch(err:IOError){
_txt.text = "No data!";
}
fileStream.close();
sbar.update();
}
function doClear(e:MouseEvent):void {
_txt.text = "";
sbar.update();
}
save_btn.addEventListener(MouseEvent.CLICK, doSave);
load_btn.addEventListener(MouseEvent.CLICK, doLoad);
clear_btn.addEventListener(MouseEvent.CLICK, doClear);

原始檔: saveTextFile.fla

2007-06-19

Create AIR Apps in Flash CS3

AIR SDK 請安裝新的 beta
參考 Create Apollo Apps in Flash CS3 安裝「Test in Apollo.mxp」

如果之前已經安裝 apollo alpha1 sdk
1. 直接將「C:\Documents and Settings\USERID\Local Settings\Application Data\Adobe\Flash CS3\en\Configuration\Test in Apollo\config.dat」的內容改成新 SDK 的路徑, 例如:
file:///C|/air_b1_win_sdk_061107

2. 將「C:\Documents and Settings\USERID\Local Settings\Application Data\Adobe\Flash CS3\en\Configuration\Test in Apollo\apollo-app-template.xml」的內容改成:
<application xmlns="http://ns.adobe.com/air/application/1.0.M4" appId="$appId" version="$version">
<name>$name</name>
<title>$name</title>
<publisher>$publisher</publisher>
<description>$description</description>
<copyright>$copyright</copyright>
<rootContent systemChrome="standard" visible="true">[the name of your main file will be put here]</rootContent>
</application>

如果從未安裝「Test in Apollo.mxp」, 安裝之後, 如上述第2點修改 apollo-app-template.xml 即可。

漏掉了一件事, playerglobal.swc 也要更新。

  1. Download Flex 3 SDK 3 beta 1 and unzip it

  2. Copy the airglobal.swc from the frameworks\libs\air folder of the Flex 3 SDK 3 beta 1

  3. Paste it into the \en\Configuration\ActionScript 3.0\Classes folder of your Adobe Flash CS3 installation

  4. Delete the playerglobal.swc file that is inside of that same folder

  5. Rename the airglobal.swc file to playerglobal.swc

Adobe Extension mxi 於 Windows 存放的路徑

路徑在:
C:\Documents and Settings\USERID\Application Data\Adobe\Extension Manager\Configuration\Extensions
以 Flash CS3 為例, mxi 中指的 $flash 為:
C:\Documents and Settings\USERID\Local Settings\Application Data\Adobe\Flash CS3\en\Configuration

2007-06-18

元件會自動轉換為類別

沒有設定連結的元件, 和設定連結的元件類似, 可能會被轉換為類別
如果元件內沒有 frame actions, 元件實體會屬於 MovieClip 類型
如果元件內包含 frame actions, 則轉換為「元件名_X」的類別, 其中 X 為 z-order index
參考原始檔: symbol_to_class.fla
既然為類別, 元件內定義的 functions (不論在哪一影格定義), 在實體出現時即可被呼叫
當然也可以由類別建立物件
參考原始檔: symbol_to_class_2.fla

DisplayObjects 的 frame actions 執行順序

Flash AS3 中, frame actions 執行順序和 AS1/AS2 一樣
父物件的 frame actions 先執行, 再執行子物件的 frame actions

Z-order Index (part 2)

移除 DisplayObject 時, 其原本所佔用的 index, 會被後面的物件所遞補
參考 設定連結的元件會變成類別 原始檔
Frame actions :
var ar:Array = new Array();
var s:Symbol1;
for (var i:int=0; i<6; i++) {
s = new Symbol1();
s.x = s.width*i;
s.y = 100;
s._txt.text = String(i+1);
s.name = 's'+(i+1);
s.addEventListener(MouseEvent.CLICK, cOnClick);
this.addChild(s);
ar.push(s);
}

function cOnClick(e:MouseEvent):void {
var t_mc:MovieClip = e.currentTarget as MovieClip;
t_mc.parent.removeChild(t_mc);
trace('子物件數目:', this.numChildren);
for (var i:int=0; i < ar.length; i++) {
if (this.contains(ar[i])) {
trace(ar[i].name, ':', this.getChildIndex(ar[i]) );
}
}
}

點按1號物件後的輸出結果:
子物件數目: 5
s2 : 0
s3 : 1
s4 : 2
s5 : 3
s6 : 4

若欲取得某 DisplayObject 的所有子物件, 可以搭配使用:
for(var k:int=0; k < this.numChildren; k++){
var d:DisplayObject = this.getChildAt(k);
trace(d.name);
}

Z-order Index (part 1)

在 AS2, 稱為 depth; 在 AS3, 稱 z-order index
有兩個方法可以改變 z-order index:
swapChildren(child1:DisplayObject, child2:DisplayObject):void
swapChildrenAt(index1:int, index2:int):void

兩者的參數必須是合法的 DisplayObject (已存在的子物件)
或者合法的 index (已存在子物件的索引)

因此, 所有已被使用的 indexes 必定是連號的
(例如: 0,1,2,3,4,5,6)
不會有中間空號沒被使用的情形
(不會發生: 0,1,2, 4,5,6,7)

2007-06-16

Loading External module-SWF

參考 ActionScript 3 Tip of the Day: Loading External Classes with ApplicationDomain

載入模組測試
load_module_loadee01.fla 包含 linkaged symbol: Symbol1
load_module_loader01.fla
var my_this = this;
var ldr:Loader = new Loader();
var ldrContext:LoaderContext = new LoaderContext();
// 使用 loader 的類別域
ldrContext.applicationDomain = ApplicationDomain.currentDomain;
ldr.load(new URLRequest("load_module_loadee01.swf"), ldrContext);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);

function onComplete(e:Event):void{
/*
var Symbol1:Class =
ApplicationDomain.currentDomain.getDefinition('Symbol1')
as Class;
*/
var Symbol1:Class = getDefinitionByName('Symbol1')
as Class;

var s:MovieClip = new Symbol1();
this.addChild(s);
}

原始檔: load_module_01.zip

2007-06-15

載入 SWF 後的物件關係 (AS3)

loadee.fla :
a_mc.alpha = 0.5;
trace('a_mc.parent:',
a_mc.parent, "::",
a_mc.parent.name);
trace('a_mc.parent.parent:',
a_mc.parent.parent, "::",
a_mc.parent.parent.name);
trace('a_mc.parent.parent.parent:',
a_mc.parent.parent.parent, "::",
a_mc.parent.parent.parent.name);
trace('a_mc.parent==root :', a_mc.parent==root);
trace('------------');

loader.fla :
var my_this = this;
var ldr:Loader = new Loader();
ldr.load(new URLRequest("loadee.swf"));
addChild(ldr);

b_mc.addEventListener(MouseEvent.CLICK, function():void{
trace(ldr.content.name);
ldr.content['a_mc'].rotation = 30;
});

loadee.fla 裡內有一個 MovieClip「a_mc」
loader.fla 裡內有一個 MovieClip「b_mc」
執行 loader.swf 後, 再按 b_mc 後的結果:
a_mc.parent: [object MainTimeline] :: instance4
a_mc.parent.parent: [object Loader] :: instance3
a_mc.parent.parent.parent: [object MainTimeline] :: root1
a_mc.parent==root : true
------------
instance4

由結果可知 :
1. loader root -> ldr -> loadee root -> a_mc
(上式 -> 表示包含子物件)
2. 每個 swf 裡的 root 參照是固定的, 不因被載入而改變

使用匿名偵聽函式該注意

1. 若有 frames loop, 會註冊多個偵聽器
2. 匿名函式內的 this 指向一 Global 物件
a_btn.addEventListener(
MouseEvent.CLICK,
function(e:MouseEvent):void{
trace(this, ':', e.target.name);
}

);

Output:
[object global] : a_btn

由物件取得類別名

由物件取得類別名, 使用 getQualifiedClassName()
由物件取得類別資料, 使用 describeType()
由類別名取得類別物件, 使用 getDefinitionByName()
例:
var sprite:Sprite = new Sprite();
// 取得物件的類別資訊
trace(getQualifiedClassName(sprite));
// 取得物件所屬類別的父類別資訊
trace(getQualifiedSuperclassName(sprite));
// 由字串取得類別
var c:Class = getDefinitionByName("flash.display::Sprite") as Class;
var s:Sprite = new c();
trace(getQualifiedClassName(s));
trace(getQualifiedSuperclassName(s));

AS3 FlashVars

Flash AS3 用
root.loaderInfo.parameters // 或 stage.loaderInfo.parameters

Flex 2 用
Application.application.parameters

在 HTML/JavaScript 中修改
if (AC_FL_RunContent == 0) {
alert("This page requires AC_RunActiveContent.js.");
} else {
AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '550',
'height', '400',
'src', 'flashvars_test',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'flashvars_test',
'bgcolor', '#ffffff',
'name', 'flashvars_test',
'menu', 'false',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'flashvars_test',
'flashvars', 'a=777', // shinder added
'salign', ''
); //end AC code
}

順帶一提, Flash 檔名請符合變數命名規則, 也應避免使用 _ (underscore)

設定連結的元件會變成類別

設定元件的連結

若無定義類別, Flash 會自動幫你產生一個
在這個例子裡, Symbol1 裡有一個動態文字物件 _txt
AS3 已經沒有 attachMovie() 可用
複製 MovieClip 時,使用 new 和 addChild
var s:Symbol1;
for (var i:int=0; i<6; i++) {
s = new Symbol1();
s.x = s.width*i;
s.y = s.height/2*i;
s._txt.text = String(i+1);
addChild(s);
}

結果:

原始檔

Flash CS3 的 AS3 components 無 bindings

暈 ... 福樂包比不上麥香包 ( fl 套件比不上 mx 套件 )

2007-06-14

AS3 Event Phases

ActionScript 3 的事件物件傳遞方式
Adobe ActionScript Article: Introduction to event handling in ActionScript 3.0

Event Object 由外傳至內(capture phase), 達到標的物件(target phase)後, 再往外傳(bubbling phase)
addEventListener() 的第三個參數 (useCapture) 就是用來決定,
偵聽器是否在 capture phase 時偵聽事件並觸發
useCapture 預設值為 false, 因此事件在 target phase 或 bubbling phase 可以被偵聽。
以下是個說明的例子:
var m1:MovieClip = new MovieClip();
m1.graphics.beginFill(0xFF9900);
m1.graphics.drawRect(100, 100, 200, 200);
m1.graphics.endFill();
m1.name = 'm1';
var m2:MovieClip = new MovieClip();
m2.graphics.beginFill(0x99FF00);
m2.graphics.drawRect(140, 140, 120, 120);
m2.graphics.endFill();
m2.name = 'm2';

addChild(m1);
m1.addChild(m2);

function mHandler(e:MouseEvent) {
switch (e.eventPhase) {
case EventPhase.CAPTURING_PHASE :
trace('capture');
break;
case EventPhase.AT_TARGET :
trace('at target');
break;
case EventPhase.BUBBLING_PHASE :
trace('bubbling');
}
trace('currentTarget: ' +e.currentTarget.name + e.currentTarget);
trace('target: ' + e.target.name + '\n');
}
stage.addEventListener(MouseEvent.CLICK, mHandler);
root.addEventListener(MouseEvent.CLICK, mHandler);
m1.addEventListener(MouseEvent.CLICK, mHandler);
m1.addEventListener(MouseEvent.CLICK, mHandler); // 重複註冊偵聽器
m2.addEventListener(MouseEvent.CLICK, mHandler);
stage.addEventListener(MouseEvent.CLICK, mHandler, true);
root.addEventListener(MouseEvent.CLICK, mHandler, true);
m1.addEventListener(MouseEvent.CLICK, mHandler, true);
m2.addEventListener(MouseEvent.CLICK, mHandler, true); // 這一行沒有作用

用滑鼠擊點 m2 後的結果:
capture
currentTarget: null[object Stage]
target: m2

capture
currentTarget: root1[object MainTimeline]
target: m2

capture
currentTarget: m1[object MovieClip]
target: m2

at target
currentTarget: m2[object MovieClip]
target: m2

bubbling
currentTarget: m1[object MovieClip]
target: m2

bubbling
currentTarget: root1[object MainTimeline]
target: m2

bubbling
currentTarget: null[object Stage]
target: m2

2007-06-13

由 URL 取得 Domain Name (AS2 版)

在測試和發佈 Flash Remoting 專案時還滿有用的
原始檔 MyDomain.as
/**
* author: shinder lin
* email: shinder.lin@gmail.com
*/
class MyDomain {
static var defaultDomain = "http://localhost";
static function getDomain() {
var url_str = _root._url;
if (url_str.indexOf("http://") == 0) {
var s_index = url_str.indexOf("/", 10);
return url_str.substring(0, s_index);
} else {
return defaultDomain;
}
}
}

SDDump - Dump 的 AS2 版

原始檔 SDDump.as
/**
* author: shinder lin
* email: shinder.lin@gmail.com
*/
class SDDump {
static var n:Number = 0;
static var str:String = '';
static function echo(a) {
trace(go(a));
}
static function go(a) {
str = '';
dumpIt(a);
str = str.slice(0, str.length-1);
return str;
}
static function dumpIt(a) {
if (a instanceof Array) {
dumpArray(a);
} else if (a instanceof Object) {
dumpObject(a);
} else {
appendStr(a);
}
}
static function dumpArray(ar:Array):Void {
n++;
for (var o in ar) {
if (ar[o] instanceof Object) {
appendStr("["+o+"]:");
dumpIt(ar[o]);
} else {
appendStr("["+o+"]:"+ar[o]);
}
}
n--;
}
static function dumpObject(obj:Object):Void {
n++;
for (var o in obj) {
if (obj[o] instanceof Object) {
appendStr(o+":");
dumpIt(obj[o]);
} else {
appendStr(o+":"+obj[o]);
}
}
n--;
}
static function appendStr(s):Void {
str += getSpaces()+s+'\n';
}
static function getSpaces():String {
var s:String = '';
for (var i = 1; i < n; i++) {
s += " ";
}
return s;
}
}

2007-06-12

Adobe AIR beta

之前代號為 Apollo, 現在正式稱為 Adobe AIR
釋出 public beta Adobe Integrated Runtime (AIR)
相關新聞: Adobe推Apollo平台測試版 正名AIR
Flex 3 也 beta 了, 請看 Adobe Labs

AS3 frame actions 可以定義 setter/getter functions

Flash CS3 AS3 的 frame actions 可以用 setter/getter 囉
雖然不能使用 private 宣告變數
但是可以定義 setter/getter functions 就很方便了
var t:Number = 10;
function set test(n:Number):void {
t=n;
}
function get test():Number {
return t;
}
trace('t='+t);
test = 99;
trace('t='+t);

2007-06-11

The rules of frame actions converting to a class definition ?

承上一篇: Frame Action 的 Function literal 裡的 Scope
個人「純猜測」可能轉換成類別定義:
package {
import flash.display.MovieClip;

public class TestMC8 extends MovieClip {
public var me:Object = this;
public var o:Object = {};
public var i:Number = 6;

public function TestMC8() {
addFrameScript(0, frame1);
}

internal function frame1():void {
o.a = function():void{
this.c = function():void{
};
};
o.b = function():void{
trace(i);
trace(this.i);
trace(me.i);
};
o.a();
o.b();
}
}
}

然而 frame1 應該不是 class member, 所以應該比較像這樣:
package {
import flash.display.MovieClip;

public class TestMC8a extends MovieClip {
public var me:Object = this;
public var o:Object = {};
public var i:Number = 6;

public function TestMC8a() {
function frame1():void{
o.a = function():void{
this.c = function():void{
};
};
o.b = function():void{
trace(i);
trace(this.i);
trace(me.i);
};
o.a();
o.b();
trace(this);
}

addFrameScript(0, function(){
frame1.apply(me);
}
);
}
}
}

紅色字的部份應該是在 addFrameScript() 裡面運作

Frame Action 的 Function literal 裡的 Scope

之前在 mmug 的討論: Flash CS3 - AS3 又一影格程式問題
老方式用 describeType() 去檢查. 以 literal 方式定義的 function objects, 其內部的變數若不是以 this 為開頭, 皆會被轉換為 影格所在MovieClip 物件的屬性。
Frame Actions:
var me:Object = this;
var o:Object = {};
o.a = function():void{
var i:Number = 6;
this.c = function():void{
var k;
};
};
o.b = function():void{
trace(i);
trace(this.i);
trace(me.i);
};
o.a();
o.b();
trace(describeType(this));

結果:
6
undefined
6
...
<variable name="k" type="*"/>
<variable name="i" type="Number"/>
<variable name="me" type="Object"/>
<variable name="o" type="Object"/>
...

MainTimeline Frame Functions -> Class Methods

Flash CS3 裡 MainTimeline frame actions 定義的 functions (not literal)
如何轉換成 class methods 的定義呢 ?
測試了一下, 無論在哪一格定義, 全都變成 public class methods

Frame 1:
b();
a();
function a():void {
trace('a');
}

Frame 6:
stop();
function b():void {
trace('b');
}
trace(describeType(this));

輸出結果:
b
a
<type name="Untitled_fla::MainTimeline" base="flash.display::MovieClip" isDynamic="true" isFinal="false" isStatic="false">
...
<method name="a" declaredBy="Untitled_fla::MainTimeline" returnType="void"/>
<method name="b" declaredBy="Untitled_fla::MainTimeline" returnType="void"/>
...

2007-06-10

AS3 未公開的類別和方法

網路上的資源:
Ticore's Blog: ActionScript 3.0 未公開的函式 AVM1Movie.call、addCallback, ActionScript 3.0 未公開的函式 MovieClip.addFrameScript
Experimenting with AS3 ,Apollo and HaXe: ActionScript3中未公开的一些方法和类

在 Flash CS3 開個 AS3 新文件, 輸入 Frame Actions
trace(describeType(this));

得到的結果, 可以找到
<method name="addFrameScript" declaredBy="flash.display::MovieClip" returnType="void">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</method>

依照 metadata 標籤又可以找到
<accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</accessor>

addFrameScript 和 AccessibilityImplementation 都是 undocumented.

Colin Moock - actionscript 3.0 and flash cs3

Colin Moock - 演講大綱
actionscript 3.0 and flash cs3
explains how to integrate ActionScript 3.0 code with content created in the flash cs3 authoring tool.

AS3 與 AMFPHP 1.2 part 3 - Credentials

AS3 沒有 setCredentials() 了
而是利用 NetConnection.addHeader(), 下兩行是 Help 裡說明
Adds a context header to the AMF packet structure.
This header is sent with every future AMF packet.

Flash AS3:
var nc:NetConnection = new NetConnection();
nc.objectEncoding = ObjectEncoding.AMF0;
nc.connect('http://localhost/amfphp/gateway.php');
nc.addHeader("Credentials", false,
{userid:'kitty', password:'kitty'});

var responder:Responder = new Responder(onResult, onError);
nc.call('myremoting.DataOp_6.isLogin', responder);

function onResult(re:Object):void {
QopDump.echo(re);
}
function onError(er:Object):void {
QopDump.echo(er);
}

AS3 與 AMFPHP 1.2 part 2

後台傳送資料表至前端的「格式」
DataOp_2.php 原始碼
< ?php
class DataOp_2
{
var $dbhost = "localhost";
var $db = "test";
var $table = "tbl_address_book";
var $user = "root";
var $password = "admin";

function DataOp_2(){
mysql_connect($this->dbhost, $this->user, $this->password);
mysql_query("SET NAMES 'utf8'");
mysql_select_db($this->db);

$this->methodTable = array(
"getAllData"=>array(
"access"=>"remote"
)
);
}

function getAllData(){
$sql = sprintf("select * from `%s`", $this->table);
return mysql_query($sql);
}
}
?>

Flash AS3
import QopDump; // just prompt

var nc:NetConnection = new NetConnection();
nc.connect('http://localhost/amfphp/gateway.php');
var responder:Responder = new Responder(onResult, onError);
nc.call('myremoting.DataOp_2.getAllData', responder);

function onResult(re:Object):void {
QopDump.echo(re);
}
function onError(er:Object):void {
QopDump.echo(er);
}

正常執行的結果:
serverInfo:
version:1
id:
serviceName:PageAbleResult
initialData:
[0]:
[0]:3
[1]:哈利
[2]:0987654321
[3]:台北市大安區
[1]:
[0]:4
[1]:凱蒂貓
[2]:0987654322
[3]:宜蘭縣礁溪鄉
[2]:
[0]:6
[1]:小叮噹
[2]:0987654323
[3]:台東縣知本溫泉旁
columnNames:
[0]:id
[1]:name
[2]:phone
[3]:address
cursor:1
totalCount:3

方法名稱錯誤的結果:
line:171
description:The method {getAll} was not declared in the meta data for class {DataOp_2}.
level:User Error
details:C:\wamp163\www\amfphp\amf-core\app\Actions.php
code:AMFPHP_UNDECLARED_METHOD

AS3 與 AMFPHP 1.2 part 1

AS3 object serialization 預設為 AMF3, 後台若使用 AMFPHP 1.2
且要由 AS3 送資料紿後台時, 記得要設定成 AMF0 的格式溝通
var nc:NetConnection = new NetConnection();
// 設定為 AMF0, 預設值為 AMF3
nc.objectEncoding = ObjectEncoding.AMF0;
nc.connect('http://localhost/amfphp/gateway.php');

2007-06-09

QopDump - Dump 的 AS3 版

改寫以前 AS2 的 Dump
使用方式
var a:Object = ["sd","tg","rt",{a:"1", b:"23", c:"11"}];
// 取得字串資料用 QopDump.go(a)
// 直接 trace
QopDump.echo(a);

執行結果:
[0]:sd
[1]:tg
[2]:rt
[3]:
c:11
a:1
b:23

原始檔 QopDump.as
/**
* author: shinder lin
* email: shinder.lin@gmail.com
*/
package {
import flash.utils.describeType;
public class QopDump {
static var n:int = 0;
static var str:String;
// trace
public static function echo(o:Object):void {
trace( go(o) );
}
// return the result string
public static function go(o:Object):String {
str = "";
dump(o);
// remove the lastest \n
str = str.slice(0, str.length-1);
return str;
}
static function dump(o:Object) {
var type:String = describeType(o).@name;
if(type == 'Array') {
dumpArray(o);
} else if (type == 'Object') {
dumpObject(o);
} else {
appendStr(o);
}
}
static function appendStr(s:Object) {
str += s + '\n';
}
static function dumpArray(a:Object):void {
n++;
var type:String;
for (var i:String in a) {
type = describeType(a[i]).@name;
if (type == 'Array' || type == 'Object') {
appendStr(getSpaces() + "[" + i + "]:");
dump(a[i]);
} else {
appendStr(getSpaces() + "[" + i + "]:" + a[i]);
}
}
n--;
}
static function dumpObject(o:Object):void {
n++;
var type:String;
for (var i:String in o) {
type = describeType(o[i]).@name;
if (type == 'Array' || type == 'Object') {
appendStr(getSpaces() + i + ":");
dump(o[i]);
} else {
appendStr(getSpaces() + i + ":" + o[i]);
}
}
n--;
}
static function getSpaces():String {
var s:String ="";
for(var i:int = 1; i < n; i++){
s += " ";
}
return s;
}
}
}

2007-06-08

describeType() 是判斷型別的好工具

flash.utils.describeType() 是判斷型別的好工具
Flash AS3:
var a:Object = 123;
var b:Object = 1e-1;
var c:Object = {a:1,b:2};
var d:Object = [5,4,3];
var e:Object = 'sss';
trace(describeType(a).@name);
trace(describeType(b).@name);
trace(describeType(c).@name);
trace(describeType(d).@name);
trace(describeType(e).@name);

Output:
int
Number
Object
Array
String

AS3 堆疊溢位

AS2 的遞迴限制是 255 次
AS3 顯然好多了, 我測試的結果是 6898 次
不知道是否跟系統資源相關
function sum(n:int):int{
trace(n);
if(n < 2)
return 1;
else
return n+sum(n-1);
}
trace(sum(6900));

Error #1023: 發生堆疊溢位

Adobe CS3 中文版於 7/12 發表

Adobe CS3中文版將於七月發表
CS3 中文版上市日程
於7月12日
假 THCC 台大醫院國際會議中心舉辦

把 JavaScript 當作 temporary data pool (AS3 和 AS2 溝通)

將 SWF9(from Flex2)收到的 Flashvars 變數, 傳給 JS
SWF8 需要時或被載入後再由 JS 取出
SWF9: AS3
private var paramObj:Object;
private function init():void{
paramObj = Application.application.parameters;
ExternalInterface.call('setMyVars', paramObj);
}

JavaScript:
var myVars;
function setMyVars(v){
myVars = v;
/*
var s='';
for(var i in v){
s+= i+' : '+v[i]+'\n';
}
alert(s);
*/
}
function getMyVars(){
return myVars;
}

SWF8: AS2
import flash.external.ExternalInterface;
var myVars = ExternalInterface.call('getMyVars');

JavaScript 的 alert() 有時也是個很好的除錯工具

AS3 和 AS2 溝通

Adobe CS3 才上市不久, 大部份的人對 Flash CS3 不是頂熟稔
若要使用 ActionScript 3 的新功能, 卻又想以熟悉的 Flash 8 開發
遇到的最大問題就是 ActionScrip 3 和 ActionScript 2 的溝通
目前常用的作法有兩種: LocalConnection 和 ExternalInterface

在使用 SWF 9 (from Flex 2) 載入 SWF 8 (from Flash 8) 的情況下, 使用文字資料做測試
LocalConnection 每次只能傳送低於 40K 的資料
透過 ExternalInterface 則可以傳遞超過 1M 的資料給 JavaScript

LocalConnection 明顯只適用於傳遞少量資料
缺點: 接收的 SWF 實體只能有一個 (第二個實體之後是收不到資料的)
優點: 不限實體的執行形式 (EXE, flash player, flash plugin)
ExternalInterface 的缺點是必須要有 plugin container 當中介的角色

之前遇到的一個情況是 SWF9 載入兩支 SWF8 (a 和 b)
● SWF8a 負責和使用者互動, 讓使用者編輯
● SWF8b 負責產生上傳的圖片
● SWF9 負責將 SWF8b 的內容上傳
SWF8a 透過 EI 傳遞 XML 給 SWF8b 產生圖片
SWF8b 完成圖片後, 透過 EI 叫 SWF9 上傳圖片

SWF8a: AS2
import flash.external.ExternalInterface;
ExternalInterface.call("toRender", _xml.toString());

JavaScript:
function toRender(str){
if(navigator.appName.indexOf("Microsoft") != -1){
window.room_planner.renderPic(str);
}else{
window.document.room_planner.renderPic(str);
}
return true;
}
function uploadImage(){
if(navigator.appName.indexOf("Microsoft") != -1){
window.room_planner.uploadImage();
}else{
window.document.room_planner.uploadImage();
}
return true;
}

SWF8b: AS2
import flash.external.ExternalInterface;
var successRegist = ExternalInterface.addCallback("renderPic", null, render);
//
function render(d_str) {
// loading objects ...
onEnterFrame = sdEnterFrame;
}
function sdEnterFrame() {
var all_loaded = true;
for (var i = 0; i < loadee_ar.length; i++) {
if (loadee_ar[i].c_mc.getBytesLoaded() < 10) {
all_loaded = false;
break;
}
}
if (all_loaded) {
resizeToUpload();
ExternalInterface.call('uploadImage');
delete this.onEnterFrame;
}
}

SWF9: AS3
private function init():void{
// ...
ExternalInterface.addCallback('uploadImage', uploadImage);
}
private function uploadImage():void{
pop = PopUpManager.createPopUp(this, MyMsgWin, true);
pop.x = 440;
pop.y = 296;

var timer:Timer = new Timer(500, 1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, doUploadImage);
timer.start();
}

換用免錢的暴露閣

Shinder's List 已經停擺許久了
最近又想寫點東西, 但懶得處理垃圾廣告, 所以轉到 Blogger
Shinder's List 可能會無預警倒站
部份文章會在這改寫再重貼

FB 留言