2008年5月31日 星期六

Flash 技巧 - 利用 ExternalInterface 完全暂停 Flash Movie 程序   [+/-]

Ticore's Blog

最近在 review 一年半以前发现的技巧时
『利用 window.prompt 解决 Flash 透明模式下无法输入中文的问题』
又有了新的发现

透过 ExternalInterface 调用 window.prompt 时
完全是同步的
在浏览器对话框关闭以前
Flash Movie 就像是被暂停了一样

忽然想到 Flash ActionScript 到现在没有直接提供过全面暂停的功能
(PS. Flash Player 9 debug 版可以使用 flash.system.System.pause(); 暂停)
不光是只调用 _root.stop(); 那样
要连 _root 下面所有子 MovieClip 也一并暂停啊

于是更进一步测试
发现透过 ExternalInterface 调用 JavaScript alert, prompt, confirm 时
能够将 Flash Player 几乎全面暂停

能够暂停的项目:

  1. MovieClip Timeline
  2. Video play head
  3. Timer, setInterval, setTimeout
  4. for, while 回圈
  5. 影格上的 Stream Sound

无法暂停的项目:

  1. Event Sound, 串流下载播放的 Sound
  2. Network Activity

这样一来就很方便了
除了声音对象要自行暂停以外
几乎大部分 Flash Player 内的活动都能够用 ExternalInterface 加以暂停

而且会比自行实作的更省效能
因为它连回圈, Timer 都停住了
其实已经很接近运行绪 (Threading) 的睡眠 (sleep) 功能

声音播放、网络活动等之所以无法暂停
原因可能与 Flash Player 内部运行绪配置方式有关
声音播放、网络活动都是非同步的
很可能是在主运行绪之外配置了副运行绪来处理的

未来 Flash Player 可能会支持运行绪的功能
在那之前,就先用这个小技巧
暂停 Flash Player 主运行绪吧!

ActionScript 测试程序:

import flash.external.*;

function doPause() {
 trace("Before call alert.");
 ExternalInterface.call("alert", "Flash Movie 已暂停, 按下确定继续");
 trace("After call alert.");
}

setInterval(function(){trace("onTimer: " + getTimer());}, 1000);

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

线上测试页面

测试程序下载

相关连结:
利用 window.prompt 解决 Flash 透明模式下无法输入中文的问题

PS. 上述功能主要是以 AS2.0 测试的
后来邦邦告知可能会引发 Script Timeout 问题
测试之后发现 AS3.0 上运行类似的动作
只要 JS Alert, Prompt 对话框超过默认 15 秒没有关闭
便会引发 Script Timeout 问题

Read more...

2008年5月28日 星期三

Flex - RemoteObject 与 ApplicationDomain 问题   [+/-]

Ticore's Blog

问题出处:SWFLoader装入问题,当要装入的swf有使用DataServices...
在 Flex App 内,以新的 ApplicationDomain 装入另一个 Flex App 之后
被读入的 Flex App 使用 RemoteObject 调用会出现问题

重新把问题程序码简化如下
因为这问题发生于 HTTP 请求之前,不必配置后端

LoadeeApp.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
 <mx:Button label="Submit" click="remoteObj.test(123);"/>
 <mx:RemoteObject id="remoteObj" destination="xxx" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

LoaderApp.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 <mx:SWFLoader id="swfLdr" width="100%" height="100%">
  <mx:creationComplete>
   <![CDATA[
    swfLdr.loaderContext = new LoaderContext();
    swfLdr.loaderContext.applicationDomain = new ApplicationDomain();
    swfLdr.source = "LoadeeApp.swf";
   ]]>
  </mx:creationComplete>
 </mx:SWFLoader>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

编译之后,运行 LoaderApp,按下按钮就会得到错误消息

ArgumentError: Error #1063:
 Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
 上的引数个数不相符。需要 0 个,当前为 2 个。
 at LoadeeApp/___LoadeeApp_Button1_click()

假如改成 remoteObj.test(); 还会得到堆栈溢位错误呢

Error: Error #1023: 发生堆栈溢位。
 at Object$/_hasOwnProperty()
 at Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
 at Object$/_hasOwnProperty()
 at Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
 ...

从错误消息看起来,其实与 Flex 无关
问题很可能是出在 Flash ActionScript 3.0 内建 Class 上
由于 RemoteObject 是继承 Proxy
再将问题简化,剔除 Flex 相关的因素
仅使用 Flash ActionScript 3.0 以 new ApplicationDomain(); 装入另一个 Flash App
于被装入的 Flash App 调用自订的 MyProxy 方法

LoaderFlash Class:

package {
 import flash.display.Loader;
 import flash.display.Sprite;
 import flash.net.URLRequest;
 import flash.system.ApplicationDomain;
 import flash.system.LoaderContext;

 public class LoaderFlash extends Sprite {
  
  protected var ldr:Loader;
  protected var ldrCxt:LoaderContext;
  protected var req:URLRequest;
  
  public function LoaderFlash() {
   ldr = new Loader();
   ldrCxt = new LoaderContext(false, new ApplicationDomain());
   req = new URLRequest("LoadeeFlash.swf");
   
   ldr.load(req, ldrCxt);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

LoadeeFlash Class:

package {
 import flash.display.Sprite;

 public class LoadeeFlash extends Sprite {
  public function LoadeeFlash() {
   var proxy:MyProxy = new MyProxy();
   proxy.test(123);
   //proxy.prop++;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

MyProxy Class:

package {
 import flash.utils.Proxy;
 import flash.utils.flash_proxy;

 public dynamic class MyProxy extends Proxy {
  public function MyProxy() {
   super();
  }
  override flash_proxy function callProperty(methodName:*, ... args):* {
   trace("callProperty :", methodName, args);
   return;
  }
  override flash_proxy function getProperty(name:*):* {
   trace("getProperty :", name);
   return;
  }
  override flash_proxy function hasProperty(name:*):Boolean{
   trace("hasProperty :", name);
   return true;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

下载测试程序码

运行 LoaderFlash.swf,结果还是会得到一样的错误消息
所以 flash.utils.Proxy 无法在 new ApplicationDomain(); 方式装入的 SWF 内使用

变通方式,大概只能避免使用到 Proxy 的功能了
改以 NetConnection 等比较低阶的方式使用 Remoting 功能

以上的 Bug 至少会发生在以下版本的 Flash Player
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

Read more...

2008年5月23日 星期五

Flash Player 10 beta - 新的影格事件   [+/-]

Ticore's Blog

Flash Player 10 beta 文档出来了
要观察新的 API 更方便一些

新的 AS3 API 多了两个影格事件
分别是 Event.FRAME_CONSTRUCTED, Event.EXIT_FRAME
看起来有点像 Director 的影格事件
以往 Flash 从来没有离开影格的相关事件

Event.FRAME_CONSTRUCTED 事件按照文档上所述
是发生在影格上的 DisplayObject 创建之后
运行影格程序之前

看起来像是用来补足 Flash Player 9 影格事件的不足
之前听到不少人抱怨 AS3 作影格跳跃之后
无法直接取用该影格的时间轴预置对象 (Timeline-Placed Object)
必须要等一个影格左右的时间...
非常不方便!

不过新的 frameConstructed 事件也只是将等待一个影格的时间缩短而已
好像没有方便到哪去
至于正式版情况怎样,就拭目以待了!

以下为 Flash Player 10 beta 新影格事件测试程序:
(需要自行准备一个具有三个影格的空白 fla 文档)

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

    public class Main extends MovieClip {

        public function Main() {
            this.addEventListener(Event.ENTER_FRAME, onEvent);
            this.addEventListener(Event.EXIT_FRAME, onEvent);
            this.addEventListener(Event.FRAME_CONSTRUCTED, onEvent);
            this.addFrameScript(0, onFrame, 1, onFrame, 2, onFrame);
        }

        private function onFrame():void {
            trace(currentFrame, "FrameAction");
        }

        private function onEvent(evtObj:Event):void {
            trace(currentFrame, evtObj.type);
        }

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

以下是输出结果:

1 frameConstructed
1 FrameAction
1 exitFrame
2 enterFrame
2 frameConstructed
2 FrameAction
2 exitFrame
3 enterFrame
3 frameConstructed
3 FrameAction
3 exitFrame
1 enterFrame
1 frameConstructed
1 FrameAction
1 exitFrame
..
.

除了第一影格之外,大致上可以看得出来运行顺序是
enterFrame, frameConstructed, FrameAction, exitFrame

相关连结:
Flash Player 10 beta - MouseCursor 功能
Flash Player 10 beta - JPEGLoaderContext 介绍
Flash 9 AS3 时间性事件混合测试
Flash Player 8 AS2 影格程序运行顺序

Read more...

2008年5月18日 星期日

Flash Player 10 beta - MouseCursor 功能   [+/-]

Ticore's Blog

以下介绍 Flash Player 10 beta 新的 Class - MouseCursor

先利用 describeType 观察 MouseCursor 与 Mouse

import flash.ui.*;
import flash.utils.*;

trace(describeType(MouseCursor));
trace(describeType(Mouse));

可以得到以下输出结果:

<type name="flash.ui::MouseCursor" base="Class"
   isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <constant name="IBEAM" type="String"/>
  <constant name="HAND" type="String"/>
  <constant name="BUTTON" type="String"/>
  <constant name="AUTO" type="String"/>
  <constant name="ARROW" type="String"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.ui::MouseCursor">
    <extendsClass type="Object"/>
  </factory>
</type>


<type name="flash.ui::Mouse" base="Class"
   isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="cursor" access="readwrite" type="String" declaredBy="flash.ui::Mouse"/>
  <method name="hide" declaredBy="flash.ui::Mouse" returnType="void"/>
  <method name="show" declaredBy="flash.ui::Mouse" returnType="void"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.ui::Mouse">
    <extendsClass type="Object"/>
  </factory>
</type>

MouseCursor 内共有五个常量 IBEAM, HAND, BUTTON, AUTO, ARROW
而刚好 Mouse 多出一个 cursor 属性
看起来就像是可以自由决定使用系统鼠标功能

实际测试之后,果然如此
可以自由设置要使用哪一个系统鼠标游标
这样就省事多了,不需要像以前那样
要先隐藏系统鼠标,还要再用一个 MovieClip 跟随鼠标~~

假如要恢复默认状态
只要重新指定为 MouseCursor.AUTO 即可

Flex MouseCursor 测试程序:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   layout="horizontal" backgroundColor="#FFFFFF">
 <mx:Script>
  <![CDATA[
   import flash.ui.Mouse;
  ]]>
 </mx:Script>
 <mx:Button label="Auto" buttonMode="true" click="Mouse.cursor = MouseCursor.AUTO;" />
 <mx:Button label="Arrow" buttonMode="true" click="Mouse.cursor = MouseCursor.ARROW;" />
 <mx:Button label="Hand" buttonMode="true" click="Mouse.cursor = MouseCursor.HAND;" />
 <mx:Button label="Button" buttonMode="true" click="Mouse.cursor = MouseCursor.BUTTON;" />
 <mx:Button label="IBEAM" buttonMode="true" click="Mouse.cursor = MouseCursor.IBEAM;" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

相关连结:
Flash Player 10 beta - 新的影格事件
Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x
Flash Player 10 beta - JPEGLoaderContext 介绍

Read more...

Flash Player 10 beta - JPEGLoaderContext 介绍   [+/-]

Ticore's Blog

最近 Flash Player 10 beta 出了
各大网站、Blog 已经有太多相关文章了
在此不再赘述

除了那些官方列出来的新功能之外
还有一些是没有被发现的
像是 flash.system::JPEGLoaderContext 类别

先来利用 describeType 观察一下 JPEGLoaderContext

import flash.system.*;
import flash.utils.*;
trace(describeType(JPEGLoaderContext));

可以得到以下输出结果:

<type name="flash.system::JPEGLoaderContext"
  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.system::JPEGLoaderContext">
    <extendsClass type="flash.system::LoaderContext"/>
    <extendsClass type="Object"/>
    <constructor>
      <parameter index="1" type="Number" optional="true"/>
      <parameter index="2" type="Boolean" optional="true"/>
      <parameter index="3" type="flash.system::ApplicationDomain" optional="true"/>
      <parameter index="4" type="flash.system::SecurityDomain" optional="true"/>
    </constructor>
    <variable name="deblockingFilter" type="Number"/>
    <variable name="applicationDomain" type="flash.system::ApplicationDomain"/>
    <variable name="securityDomain" type="flash.system::SecurityDomain"/>
    <variable name="checkPolicyFile" type="Boolean"/>
  </factory>
</type>

从名称上看起来,用途应该是与 LoaderContext 类似的
然后是用来处理外部 JPEG 图档
只是多了一个 deblockingFilter 变量
看起来也很像是去马赛克用的

以下便是实际使用示范:(需要自行准备一个外部图档 img.jpg)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
  initialize="init();" layout="horizontal" backgroundColor="#FFFFFF">
 <mx:Script>
  <![CDATA[
   import flash.system.*;
   import flash.utils.*;
   
   [Bindable]
   public var jpgLdrCxt1:JPEGLoaderContext = new JPEGLoaderContext(0);
   public var jpgLdrCxt2:JPEGLoaderContext = new JPEGLoaderContext(1);
   
   public function init():void{
    
    trace(describeType(JPEGLoaderContext));
    
    img1.loaderContext = jpgLdrCxt1;
    img1.source = "img.jpg";
    img2.loaderContext = jpgLdrCxt2;
    img2.source = "img.jpg";
   }
  ]]>
 </mx:Script>
 <mx:Image id="img1" scaleX="1.5" scaleY="1.5" />
 <mx:Image id="img2" scaleX="1.5" scaleY="1.5" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

以下是实际用 Flash Player 10.0.1.218 运行的效果

可以明显看得出来其中的差异
deblockingFilter 值大约是在 0-1 之间
超过 1 以上就没有太大的差异了
假如再加上 Bitmap.smoothing 会得到更好的效果

相关连结:
Flash Player 10 beta - 新的影格事件
Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x
Flash Player 10 beta - MouseCursor 功能

Read more...

AIR - ActionScript, JavaScript 混搭技巧   [+/-]

Ticore's Blog

拜 Adobe AIR ActionScript, JavaScript 混搭功能所赐
ActionScript 3.0 runtime 可以使用 JavaScript 创建的 Function
也能互相应用 Scope

由于 ActionScript 是编译语言,无法动态创建 Statement, Function
但是 JavaScript 可以

于是想到结合 AIR, JavaScript 动态的功能
让 ActionScript 3.0 也能具有直译程序的能力

以下创建 AS3 对象,动态赋予两个 JS Function 成员:

// Ticore's Blog - http://ticore.blogspot.com/
import flash.utils.*;
import flash.system.*;

var htmlLdr:HTMLLoader = new HTMLLoader();

var jsRuntime:Object = htmlLdr.window;

var obj:Object = {};
obj.name = "Object 1";
obj.getName = new jsRuntime.Function(null, "return this.name;");
obj.setName = new jsRuntime.Function("value", "this.name = value;");

trace(obj.getName()); // Object 1
obj.setName("Object 2");
trace(obj.getName()); // Object 2

相关连结:
AIR - 如何区分 JavaScript 与 ActionScript 对象
Adobe AIR Namespace Bug
AIR - JavaScript 与 ActionScript 之间对象的传递

Read more...

2008年5月17日 星期六

AIR - 如何区分 JavaScript 与 ActionScript 对象   [+/-]

Ticore's Blog

Adobe AIR 虽然可以让 ActionScript 与 JavaScript 对象互相传递调用
但是除了基础对象以外,复杂对象是不会被转换的
某些情况下,仍需要注意所持有的对象到底是 AS Object 还是 JS Object
以下介绍如何区分 JavaScript 与 ActionScript 对象

于 AIR ActionScript runtime 中辨别对象是否为 AS Object

import flash.html.*;
import flash.events.*;
import flash.utils.*;
import flash.system.*;

var htmlLdr:HTMLLoader = new HTMLLoader();
var jsRuntime:Object = htmlLdr.window;

var asObj:Object = new Object();
var asAry:* = new Array();
var asDate:* = new Date();
var asSprite:* = new flash.display.Sprite();
var asXML:* = new XML();
var asXMLList:* = new XMLList();
var asRegExp:* = new RegExp();
var asNS:* = new Namespace();
var asFun:* = function():void{};
var asNo:* = new Number();
var asStr:* = new String();
var asBol:* = new Boolean();

var jsObj:Object = new jsRuntime.Object();
var jsAry:Object = new jsRuntime.Array();
var jsDate:Object = new jsRuntime.Date();
var jsFun:Object = new jsRuntime.Function("", "");
var jsNo:Object = new jsRuntime.Number();
var jsStr:Object = new jsRuntime.String();
var jsBol:Object = new jsRuntime.Boolean();

function isASObject(o:*):Boolean{
 //return o.constructor is Class;
 return getQualifiedClassName(o).indexOf("flash.html::__HTMLScript") < 0;
}

trace(isASObject(asObj)); // true
trace(isASObject(asAry)); // true
trace(isASObject(asDate)); // true
trace(isASObject(asSprite)); // true
trace(isASObject(asXML)); // true
trace(isASObject(asXMLList)); // true
trace(isASObject(asRegExp)); // true
trace(isASObject(asNS)); // true
trace(isASObject(asFun)); // true
trace(isASObject(asNo)); // true
trace(isASObject(asStr)); // true
trace(isASObject(asBol)); // true

trace(isASObject(jsObj)); // false
trace(isASObject(jsAry)); // false
trace(isASObject(jsDate)); // false
trace(isASObject(jsFun)); // false
trace(isASObject(jsNo)); // true
trace(isASObject(jsStr)); // true
trace(isASObject(jsBol)); // true

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

于 AIR JavaScript runtime 中辨别对象是否为 JS Object


var asObj = new runtime.Object();
var asAry = new runtime.Array();
var asDate = new runtime.Date();
var asSprite = new runtime.flash.display.Sprite();
var asXML = new runtime.XML();
var asXMLList = new runtime.XMLList();
var asRegExp = new runtime.RegExp();
var asFun = runtime.trace;
var asNo = new runtime.Number();
var asStr = new runtime.String();
var asBol = new runtime.Boolean();

var jsObj = new Object();
var jsAry = new Array();
var jsDate = new Date();
var jsFun = function(){};
var jsNo = 10;
var jsStr = "str";
var jsBol = true;

function isJSObject(o) {
 return o.constructor instanceof Function;
}

runtime.trace(isJSObject(asObj)); // false
runtime.trace(isJSObject(asAry)); // false
runtime.trace(isJSObject(asDate)); // false
runtime.trace(isJSObject(asSprite)); // false
runtime.trace(isJSObject(asXML)); // false
runtime.trace(isJSObject(asXMLList)); // false
runtime.trace(isJSObject(asRegExp)); // false
runtime.trace(isJSObject(asFun)); // false
runtime.trace(isJSObject(asStr)); // true
runtime.trace(isJSObject(asNo)); // true
runtime.trace(isJSObject(asBol)); // true

runtime.trace(isJSObject(jsObj)); // true
runtime.trace(isJSObject(jsAry)); // true
runtime.trace(isJSObject(jsDate)); // true
runtime.trace(isJSObject(jsFun)); // true
runtime.trace(isJSObject(jsStr)); // true
runtime.trace(isJSObject(jsNo)); // true
runtime.trace(isJSObject(jsBol)); // true

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

以上的方式,除了 Number, String, Boolean 会自动转换的对象以外
应该都可以辨别大部分的 AS or JS Object

其实之前尝试过各种不同的方式
像是 __proto__, constructor is Class 等等
但是都无法用在所有的对象判别上

相关连结:
AIR - ActionScript, JavaScript 混搭技巧
Adobe AIR Namespace Bug
AIR - JavaScript 与 ActionScript 之间对象的传递

Read more...

2008年5月13日 星期二

Adobe AIR Namespace Bug   [+/-]

Ticore's Blog

继续之前的 Adobe AIR AS-JS runtime 混合测试
发现无法从 JavaScript runtime 创建 AS3 Namespace 实体

AIR JavaScript 测试程序如下:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script type="text/javascript">

new runtime.Namespace();
// Error: Internal Error
new runtime.Namespace("ns", "http://ticore.blogspot.com");
// Error: Internal Error

</script>
</head>
<body>
</body>
</html>

只要尝试创建 Namespace 就会出现 Error
于是转个弯,从 AS3 runtime 创建 Namespace 丢给 JavaScript runtime

AIR ActionScript 3.0 测试程序如下:

package {
 import flash.display.*;
 import flash.html.*;
 import flash.system.*;
 import flash.desktop.*;
 
 public class Main extends MovieClip {
  
  public var htmlLdr:HTMLLoader = new HTMLLoader();
  
  public function Main() {
   
   var nativeApp:NativeApplication = NativeApplication.nativeApplication;
   trace("AIR version :", nativeApp.runtimeVersion, nativeApp.runtimePatchLevel);
   // AIR version : 1.0.1 4990
   trace("Flash Player version :", Capabilities.version);
   // Flash Player version : WIN 9,0,124,0
   trace("Flash Player type :", Capabilities.playerType);
   // Flash Player type : Desktop
   
   // Create javascript function
   var jsFun:* = new htmlLdr.window.Function(["obj"], "return obj;");
   
   try {
    trace(jsFun(new htmlLdr.window.Object()));
    // [object Object]
    trace(jsFun(new Object()));
    // [object Object]
    trace(jsFun(new Namespace("ns", "http://ticore.blogspot.com")));
    // AIR runtime crash !
   } catch (e:Error) {
    trace(e);
   }
  }
 }
}

结果更糟糕,Adobe AIR 直接 Crash!

OS:Windows VISTA SP1

以上 Bug 至少会发生在以下版本的 Adobe AIR
Adobe AIR 1.0 4880
Adobe AIR 1.0.1 4990

相关连结:
AIR - ActionScript, JavaScript 混搭技巧
AIR - 如何区分 JavaScript 与 ActionScript 对象
AIR - JavaScript 与 ActionScript 之间对象的传递

Read more...

注意你的 AIR and Flash Player version   [+/-]

Ticore's Blog

自从 Flash Player 进入到 9 版之后,功能越来越复杂
每一次的 release 都有相当程度变动
遇到版本更新有关的问题时,只知道自己装的 Flash Player 是 9 版
却不知道是哪一个 build or release
问题就很难解决了~

Adobe AIR 也是一样的
以下便是取得 AIR runtime 与 Flash Player 完整版本的方式

// AS3 Get Adobe AIR runtime version
import flash.desktop.*;
var nativeApp:NativeApplication = NativeApplication.nativeApplication;
trace(nativeApp.runtimeVersion); // 1.0
trace(nativeApp.runtimePatchLevel); // 4880

// AS3 Get Flash Player version
trace(flash.system.Capabilities.version); // WIN 9,0,115,0

// AS2 Get Flash Player version
trace(System.capabilities.version); // WIN 9,0,115,0

// AS1 Get Flash Player version
trace($version); // WIN 9,0,115,0

// AS3 Get Operating System
trace(flash.system.Capabilities.os); // Windows XP

// AS2 Get Operating System
trace(System.capabilities.os); // Windows XP

// AS3 Get Flash Player type
trace(flash.system.Capabilities.playerType); // External

// AS2 Get Flash Player type
trace(System.capabilities.playerType); // External
Read more...

2008年5月11日 星期日

诡异的 JavaScript typeof 函式   [+/-]

Ticore's Blog

在进行 AIR AS-JS 测试时,发现 JavaScript typeof 诡异的行为
对于相同的 Number,使用 new 生成的实体与直接宣告的实体
使用 typeof 判断,居然会得到不一样的型别
真是太糟糕了

JavaScript typeof 测试程序:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<pre>
<script type="text/javascript">

document.writeln(typeof(1)); // number
document.writeln(typeof("str")); // string
document.writeln(typeof(true)); // boolean
document.writeln(typeof({})); // object
document.writeln(typeof([])); // object
document.writeln(typeof(function(){})); // function

document.writeln(typeof(new Number(1))); // object
document.writeln(typeof(new String("str"))); // object
document.writeln(typeof(new Boolean(true))); // object
document.writeln(typeof(new Object())); // object
document.writeln(typeof(new Array())); // object
document.writeln(typeof(new Function())); // function

document.writeln(1 == new Number(1)); // true
document.writeln("str" == new String("str")); // true
document.writeln(true == new Boolean(true)); // true

document.writeln(typeof(new Number(1) + 0)); // number
document.writeln(typeof(new Number(1).valueOf())); // number
document.writeln(typeof(new String("str").valueOf())); // string
document.writeln(typeof(new Boolean(true).valueOf())); // boolean

</script>
</pre>
</body>
</html>

假如再多测试一些其它型别,不同的浏览器还会得到更多不同的结果呢!

Read more...

AIR - JavaScript 与 ActionScript 之间对象的传递   [+/-]

Ticore's Blog

Adobe AIR 运行环境下,集成了 ActionScript 3.0 与 JavaScript
可以在 ActionScript runtime 下,调用 JavaScript function;反之亦然
在 AIR HTML App 下,许多延伸功能,像是 SQLite, File System....
JavaScript 也都是透过调用 ActionScript 达到的
而 JavaScript 甚至可以直接透过 Script 标签引用外部 AS Library

但是,AIR AS-JS 真的集成那么好吗?
以下先就对象在 AS 与 JS runtime 之间传递与转型测试
分别在 AIR AS, JS 运行环境下生成 AS, JS 常用对象实体
测试对象的型别

AIR ActionScript 3.0 测试程序:

import flash.html.*;

var htmlLdr:HTMLLoader = new HTMLLoader();
var jsRuntime:Object = htmlLdr.window;

function traceType(obj) {
 trace(flash.utils.getQualifiedClassName(obj));
}

traceType(new jsRuntime.Object()); // flash.html::__HTMLScriptObject
traceType(new jsRuntime.Array()); // flash.html::__HTMLScriptArray
traceType(new jsRuntime.Date()); // flash.html::__HTMLScriptObject
traceType(new jsRuntime.Function()); // flash.html::__HTMLScriptFunction
traceType(new jsRuntime.RegExp()); // flash.html::__HTMLScriptObject
traceType(new jsRuntime.String()); // String
traceType(new jsRuntime.Number()); // int
traceType(new jsRuntime.Boolean()); // Boolean

traceType(new Object()); // Object
traceType(new Array()); // Array
traceType(new Date()); // Date
traceType(new Function()); // Function-35
traceType(new RegExp()); // RegExp
traceType(new String()); // String
traceType(new Number()); // int
traceType(new int()); // int
traceType(new uint()); // int
traceType(new Boolean()); // Boolean

traceType(1.1); // Number
traceType(true); // Boolean
traceType("str"); // String

AIR JavaScript 测试程序:

function traceType(obj) {
 runtime.trace(runtime.flash.utils.getQualifiedClassName(obj));
}

traceType(new Object()); // flash.html::__HTMLScriptObject
traceType(new Array()); // flash.html::__HTMLScriptArray
traceType(new Date()); // flash.html::__HTMLScriptObject
traceType(new Function()); // flash.html::__HTMLScriptFunction
traceType(new RegExp()); // flash.html::__HTMLScriptObject
traceType(new String()); // String
traceType(new Number()); // int
traceType(new Boolean()); // Boolean

traceType(new runtime.Object()); // Array
traceType(new runtime.Array()); // Array
traceType(new runtime.Date()); // Date
traceType(new runtime.Function()); // Function-35
traceType(new runtime.RegExp()); // RegExp
traceType(new runtime.String()); // Boolean
traceType(new runtime.Number()); // int
traceType(new runtime.int()); // int
traceType(new runtime.uint()); // int
traceType(new runtime.Boolean()); // Boolean

traceType(1.1); // Number
traceType(true); // Boolean
traceType("str"); // String

从测试结果看起来,似乎只有 Number, Boolean, String 可能是共用的型别
或者是在 AS-JS 传递时,被自动转换了
至于其它复杂型别的对象,可能是被包覆为 Proxy 对象
假如真的是如此,复杂对象在 AS-JS 传递时必须要额外注意了

可能会发现到以上的测试都只有使用 AS3 getQualifiedClassName 观察型别
没有用到 JS typeof 测试
原因是 typeof 功能实在太阳春而且诡异,无法用来测试
参考 诡异的 JavaScript typeof 函式

相关连结:
AIR - ActionScript, JavaScript 混搭技巧
AIR - 如何区分 JavaScript 与 ActionScript 对象
Adobe AIR Namespace Bug

Read more...

2008年5月4日 星期日

一行 AS3 程序让 Flash Player 9 死机 Part 4   [+/-]

Ticore's Blog

Bug 又来了,以下任一行 AS3 程序都会造成 Flash Player Crash

Object['isPrototypeOf']();
Object['hasOwnProperty']();
Object['propertyIsEnumerable']();
Object['setPropertyIsEnumerable']();

实在是太诡异了,这么平常的 Class - Object
居然可以轻易让 Flash Player 挂掉
其实该 Bug 是在测试 Adobe AIR JavaScript 时发现的
连带的导致 AIR 也 Crash
因为 JavaScript 没有型别检查功能
不小心就会调用到不属于该对象的方法
平常 Flash 多亏了 AS3 型别检查
才会让该问题这么久没有浮上台面

正常情况下,对 Class 调用 non-static member 虽然是错误的动作
但是也不至于会造成 Flash Player Crash
只要捕捉例外就好
但是对于以上这四行 AS3 程序
try...catch 例外捕捉完全没用,Flash Player 照样 Crash

以上 Bug 至少会在以下的 Flash Player 版本发生
Flash Player 9.0.47.0
Flash Player 9.0.115.0
Flash Player 9.0.124.0

相关连结:
一行 AS3 程序让 Flash Player 9 死机 Part 3
一行 AS3 程序让 Flash Player 9 死机 Part 2
一行 AS3 程序让 Flash Player 9 死机
用 @* 指定 Attributes 造成 Flash Player 9 Crash

Read more...

2008年5月1日 星期四

AS3 - 利用 flash.sampler.getSize 观察对象大小   [+/-]

Ticore's Blog

Flash Player 9 update 3 (9.0.115.0) 添加了 flash.sampler package
里面的类别与方法主要都是与内存使用有关的
可以在 Flash Player 9 update 3 debug version 与 Adobe AIR 环境中使用
以下简单利用 flash.sampler.getSize 函式观察常用对象所占内存的大小

ActionScript 3.0 Code:

import flash.sampler.*;
import flash.display.*;

trace("new Number() : ", getSize(new Number()));
trace("new int() : ", getSize(new int()));
trace("new uint() : ", getSize(new uint()));
trace("new Boolean() : ", getSize(new Boolean()));
trace("new Object() : ", getSize(new Object()));
trace("new Array() : ", getSize(new Array()));
trace("new String() : ", getSize(new String()));
trace("new Date() : ", getSize(new Date()));
trace("new XML() : ", getSize(new XML()));
trace("new XMLList() : ", getSize(new XMLList()));
trace("new RegExp() : ", getSize(new RegExp()));
trace("new Function() : ", getSize(new Function()));
trace("new Sprite() : ", getSize(new Sprite()));
trace("new MovieClip() : ", getSize(new MovieClip()));


trace("Number : ", getSize(Number));
trace("int : ", getSize(int));
trace("uint : ", getSize(uint));
trace("Boolean : ", getSize(Boolean));
trace("Object : ", getSize(Object));
trace("Array : ", getSize(Array));
trace("String : ", getSize(String));
trace("Date : ", getSize(Date));
trace("XML : ", getSize(XML));
trace("XMLList : ", getSize(XMLList));
trace("RegExp : ", getSize(RegExp));
trace("Function : ", getSize(Function));
trace("Sprite : ", getSize(Sprite));
trace("MovieClip : ", getSize(MovieClip));


trace("[] : ", getSize([]));
trace("[0] : ", getSize([0]));
trace("[0, 1] : ", getSize([0, 1]));
trace("[null, null] : ", getSize([null, null]));
trace("new Array(0) : ", getSize(new Array(0)));
trace("new Array(1) : ", getSize(new Array(1)));


trace("{} : ", getSize({}));
trace("{a: 'a'} : ", getSize({a: 'a'}));
trace("{a: 'ab'} : ", getSize({a: 'ab'}));
trace("{a: {}} : ", getSize({a: {}}));

trace("{a: 'a', b: 1} : ", getSize({a: 'a', b: 1}));
trace("{a: null, b: null} : ", getSize({a: null, b: null}));


trace("1 : ", getSize(1));
trace("1.1 : ", getSize(1.1));

trace("'A' : ", getSize('A'));
trace("'AB' : ", getSize('AB'));
trace("'ABC' : ", getSize('ABC'));

function fun1():void{};
function fun2(arg1:*):void{var a:* = 1;};

trace("fun1 : ", getSize(fun1));
trace("fun2 : ", getSize(fun2));

输出结果:

new Number() :  4
new int() :  4
new uint() :  4
new Boolean() :  4
new Object() :  24
new Array() :  40
new String() :  28
new Date() :  32
new XML() :  16
new XMLList() :  32
new RegExp() :  48
new Function() :  588
new Sprite() :  464
new MovieClip() :  496
Number :  1133
int :  856
uint :  856
Boolean :  452
Object :  3282
Array :  4204
String :  3319
Date :  8235
XML :  4818
XMLList :  3118
RegExp :  1008
Function :  977
Sprite :  1602
MovieClip :  2182
[] :  40
[0] :  44
[0, 1] :  48
[null, null] :  48
new Array(0) :  40
new Array(1) :  40
{} :  24
{a: 'a'} :  32
{a: 'ab'} :  32
{a: {}} :  32
{a: 'a', b: 1} :  40
{a: null, b: null} :  40
1 :  4
1.1 :  8
'A' :  30
'AB' :  32
'ABC' :  34
fun1 :  32
fun2 :  32

相关连结:
ActionScript 3 Sampler 相关文档公布

Read more...

Flash AS3 No Border Scale Background Image   [+/-]

Ticore's Blog

利用 ActionScript 3.0 简单实作 No Border 等比例缩放的 Background Image

这只有背景图满版而已
假如还有其它需要自动调整位置的对象
全部都要个别加以控制
程序码比起用 Flex 实作多出很多

使用时,须要先准备一个 MovieClip 指定 Class Name 为 MC
作为满版背景图之用

ActionScript 3.0 Code:

/*
 Ticore's Blog
 http://ticore.blogspot.com/
*/
package {
 import flash.display.*;
 import flash.events.*;
 
 public class Main extends MovieClip {
  
  public var bg:MovieClip = new MC();
  
  public function Main () {
   
   if (stage) {
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = "TL";
    stage.addEventListener(Event.RESIZE, onStageResize);
   }
   
   this.addChild(bg);
   onStageResize();
  }
  
  public function onStageResize (evtObj:Event = null):void {
   bg.scaleX = bg.scaleY = 1;
   
   if (!stage) {
    return;
   }
   
   var bgWidth:Number = bg.width;
   var bgHeight:Number = bg.height;
   var stageWidth:Number = stage.stageWidth;
   var stageHeight:Number = stage.stageHeight;
   
   var ratioFlag:Boolean = (stageWidth / stageHeight) > (bgWidth / bgHeight);
   bg.width = ratioFlag ? stageWidth : stageHeight * (bgWidth / bgHeight);
   bg.height = !ratioFlag ? stageHeight : stageWidth * (bgHeight / bgWidth);
   
   bg.x = (stageWidth - bg.width) / 2;
   bg.y = (stageHeight - bg.height) / 2;
  }
  
 }
}

Online Demo

相关连结:
Flex - 简单实作 No Border Image

Read more...