Adobe Air & Adobe Flex & ActionScript & Mobile Dev & HTML5 & RIA & User Experience
Flash AS 的 textfield 关于响应超链接的时候与 selectable 属性无关。
而在 Adobe Flex 中 TextArea, Text, Label 等用到 textfield 控件必须将 selectable 属性设置为 true,才能响应超链接。
原因在于 Adobe Flex 中对于 FoucsManager 的控制。
代码如下(FocusManager.as):
/** * @private * This gets called when mouse clicks on a focusable object. * We block player behavior */ private function mouseFocusChangeHandler(event:FocusEvent):void { // trace("FocusManager: mouseFocusChangeHandler in = " + this._form.systemManager.loaderInfo.url); // trace("FocusManager: mouseFocusChangeHandler " + event); // If relatedObject is null because we don't have access to the // object getting focus then allow the Player to set focus // to the object. The isRelatedObjectInaccessible property is // Player 10 only so we have to test if it is available. We // will only see isRelatedObjectInaccessible if we are a version "10" swf // (-target-player=10). Version "9" swfs will not see the property // even if running in Player 10. if (event.relatedObject == null && "isRelatedObjectInaccessible" in event && event["isRelatedObjectInaccessible"] == true) { // lost focus to a control in different sandbox. return; } if (event.relatedObject is TextField) { var tf:TextField = event.relatedObject as TextField; if (tf.type == "input" || tf.selectable) { return; // pass it on } } event.preventDefault(); }
关键的在于其中鼠标事件如果碰到为TextField的话,必须是可输入或者能选择的情况下,才会继续响应事件。
所以,如果需要相应,可以这么改写:
package { import flash.events.MouseEvent; import mx.controls.Label; public class UnselectableLinkEnableLabel extends Label { public function UnselectableLinkEnableLabel() { super(); addEventListener(MouseEvent.ROLL_OVER, handleRollOver); addEventListener(MouseEvent.ROLL_OUT, handleRollOut); } protected function handleRollOut(event:MouseEvent):void { // TODO Auto-generated method stub trace("handleRollOut") focusManager.activate(); } protected function handleRollOver(event:MouseEvent):void { // TODO Auto-generated method stub trace("handleRollOver") focusManager.deactivate(); } } }
哈哈,写完才发现2008年的时候,Ticore就已经发过类似的文章(Blogspot)了。
最近 Flash Catalyst CS 5.5 出了,聽說與 Flash Builder CS 5.5 整合更密切
而且也支援自訂組件的 Skin 轉換…
可是 Flash Catalyst Code Workspace 一樣只能看不能修改 (.mxml, .as 不行 .fxg 可以)
以下分享一個沒有公開的參數,可以讓你在 Flash Catalyst 內修改原始碼
到 Flash Catalyst CS 5.5 安裝目錄下找出 Adobe Flash Catalyst.ini 檔案
Windows 7 64bit 是在
C:\Program Files (x86)\Adobe\Adobe Flash Catalyst CS5.5\Adobe Flash Catalyst.ini
多加一個參數就好了
-DTHERMO_EDIT_CODE
不過需要特別注意的是,它只能讓 MXML, AS Editor 勉強能夠編輯
但仍然沒有歷史記錄與 Undo 等功能
打錯不能還原喔!
既然 Flash Catalyst 不給編輯程式碼,為什麼還要放 Code Workspace 功能呢?
我在文件上看到有趣的一句解釋
Code workspace
Viewing the MXML code gives designers the opportunity to understand how the application is programmed.
Flash CS 5 或 5.5 有支援 TLF 文字
在 AS3 設定裡面也可以發現多出一個 TLF RSL
只是它預設會先檢查本地 Flash Player Cache
沒有的話再到網路上載入 SWZ,失敗的話才會從相對路徑載入 SWZ
這對於多媒體光碟製作可能有些困擾
不過可以自行調整優先順序,相對路徑 SWZ 往上拉就好了
除此之外,假如是直接發布成 Projector 執行檔
基本上它是不支援 RSL 的,會出現警告訊息
然後一律變成 Merged into code 模式
Warning: No libraries were linked as Runtime Shared Libraries (RSLs) because of your publish settings: Windows Projector
假如改成 External 模式,就必須自己寫載入 RSL 的程式
一個比較好的方式是,先發布成 SWF,然後自己手動把具有動態載入 RSL 能力的 SWF 轉成 Projector
最近在論壇上看到有人問相關的問題
需要在 Flash 內用點陣圖作慢速移動效果
每次移動的單位小於一個像素
結果跑出來的效果會卡卡的感覺
看起來點陣圖還是以一個像素的距離在移動
下面是平滑與不平滑移動效果的比較範例
這是由於電腦螢幕最小單位是像素而已
倘若點陣圖不是位於整數座標上
Flash 渲染引擎必須要重新取樣
預設它可能是用 Nearest 方式而非 Linear or Cubic
所以才會無法模擬出點陣圖位於非整數座標的效果
可是我印象中,內嵌 SWF 的點陣圖只要打開 smoothing 就能夠很平滑的移動啊
於是測試了一下
假如點陣圖是內嵌 SWF 內,勾選 smoothing 並且不能 Export for AS
這樣在舞台的上的慢速移動是很順的
用 AS3 去 Trace 發現,點陣圖已經被轉成 Shape 也就是點陣圖填色
再進一步將載入的點陣圖,改用 AS3 作 Bitmap Fill 也能達到相同效果
總結下來,發現有好幾種方式都可以作到平滑移動
點陣圖移動平滑技巧 1. 使用 3D Transform 強迫柔化
import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.PixelSnapping; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Matrix3D; stage.scaleMode = StageScaleMode.NO_SCALE; var bmpData:BitmapData = new OrigamiMurexBmp(); var bmp:Bitmap = new Bitmap(bmpData, PixelSnapping.AUTO, true); bmp.transform.matrix3D = new Matrix3D(); bmp.y = 50; addChild(bmp); addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); function onEnterFrameHandler(e:Event):void{ bmp.x = (bmp.x + 0.051) % 200; }
點陣圖移動平滑技巧 2. 使用點陣圖填色
import flash.display.BitmapData; import flash.display.PixelSnapping; import flash.display.StageScaleMode; import flash.events.Event; import flash.display.Sprite; import flash.display.Graphics; stage.scaleMode = StageScaleMode.NO_SCALE; var bmpData:BitmapData = new OrigamiMurexBmp(); var sp:Sprite = new Sprite(); var g:Graphics = sp.graphics; g.beginBitmapFill(bmpData, null, false, true); g.drawRect(0, 0, bmpData.width, bmpData.height); g.endFill(); sp.y = 50; addChild(sp); addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); function onEnterFrameHandler(e:Event):void{ sp.x = (sp.x + 0.051) % 200; }
點陣圖移動平滑技巧 3. 稍微縮放 Bitmap 強迫柔化
import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.PixelSnapping; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Matrix; stage.scaleMode = StageScaleMode.NO_SCALE; var bmpData:BitmapData = new OrigamiMurexBmp(); var bmp:Bitmap = new Bitmap(bmpData, PixelSnapping.AUTO, true); var m:Matrix = new Matrix(); m.scale(1.001, 1.001); // 稍微放大強迫抗鋸齒 bmp.transform.matrix = m; bmp.y = 50; addChild(bmp); addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); function onEnterFrameHandler(e:Event):void{ bmp.x = (bmp.x + 0.051) % 200; }
點陣圖移動平滑技巧 4. 稍微旋轉 Bitmap 強迫柔化
import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.PixelSnapping; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Matrix; stage.scaleMode = StageScaleMode.NO_SCALE; var bmpData:BitmapData = new OrigamiMurexBmp(); var bmp:Bitmap = new Bitmap(bmpData, PixelSnapping.AUTO, true); var m:Matrix = new Matrix(); m.rotate(0.001221); // 極小的旋轉量強迫抗鋸齒 bmp.transform.matrix = m; bmp.y = 50; addChild(bmp); addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); function onEnterFrameHandler(e:Event):void{ bmp.x = (bmp.x + 0.051) % 200; }
以上四種方式都能達到不錯的效果
不過需要特別注意的是
Bitmap 本身到移動座標的外層容器之間絕對不能用點陣圖快取或是濾鏡,否則就破功了
Sprite 1 – Sprite 2 – Sprite 3 – Bitmap – BitmapData
假設實際作移動的對象是 Sprite 2
那麼 Sprite 2, Sprite 3, Bitmap 都不可用 cacheAsBitmap 或是濾鏡
上次介紹到利用 toPrecision 避免浮點數的計算偏差
那可以一直使用固定的 Precision 嗎?
不行,看下面的計算範例
trace((10000 – 10000.0001).toPrecision(8)) // -0.000099999999
浮點數有效位數是 15-16 位
10000 運算元就已經用掉 5 位整數有效數字
計算結果沒有整數部分,小數有效數字只剩下 16 – 5 = 11 位而已
再看 toPrecision 雖然只有用到 8 可是由於計算結果小數下 4 位都是 0
8 + 4 = 12 實際上是取到小數下 12 位
超出剛剛推算的 11 位有效數字
所以才會導致無法正確去除偏差
有一個比較偷懶的方式,就是運算元與計算結果通通都只取 8 位有效數字
這樣就不會遇到計算偏差,缺點是不能使用超過 8 位的有效數值
假如想要用超過 8 位有效數值,又要避開計算偏差怎麼辦?
那得自行要從運算元與計算結果,計算出結果數值最大有效位數了
以下面是藉由計算結果最大有效位數,來修正浮點數計算偏差的 function
/** * 藉由計算結果最大有效位數,修正浮點數計算偏差 * @param resNo 計算結果數值 * @param operands 所有參與計算的數值 * @return 修正後的計算結果數值,回傳 0 表示結果無有效位數可用 * @author Ticore Shih */ function fixFloatPrecision(resNo:Number, ...operands:Array):Number{ operands = operands.concat(resNo); var absOperands:Array = []; for each(var i:Number in operands) { absOperands.push(Math.abs(i)); } var maxIntPlace:Number = Math.log(Math.max.apply(null, absOperands)) / Math.LN10; var maxDecPlace:Number = 16 - maxIntPlace; var resIntPlace:Number = Math.log(Math.abs(resNo)) / Math.LN10; var maxResPrec:uint = Math.max(maxDecPlace + resIntPlace, 0); return maxResPrec ? parseFloat(resNo.toPrecision(maxResPrec)) : 0; }
以下是減法運算修正偏差的測試程式:
function testSub(no1:Number, no2:Number):void{
var res:Number = no1 - no2;
trace(no1 + " - " + no2 + " =\n\t\t" + res);
trace("\t\t" + fixFloatPrecision(res, no1, no2), "(precision fixed)");
trace("");
return;
}
testSub(123456, 123456.00001);
testSub(1234567, 1234000.0001);
testSub(1234567, 1100000.0001);
testSub(10000000, 10000000.01);
testSub(10, 10.00001);
testSub(10, 10.000001);
testSub(0.0000023, 0.00000230002);
testSub(100000000000000, 100000000000000.02);
testSub(10000000000000, 10000000000000.02);
輸出結果包含偏差修正前與修正後的數值:
123456 - 123456.00001 = -0.000010000003385357559 -0.00001 (precision fixed) 1234567 - 1234000.0001 = 566.999899999937 566.9999 (precision fixed) 1234567 - 1100000.0001 = 134566.99989999994 134566.9999 (precision fixed) 10000000 - 10000000.01 = -0.009999999776482582 -0.01 (precision fixed) 10 - 10.00001 = -0.000009999999999621423 -0.00001 (precision fixed) 10 - 10.000001 = -9.999999992515995e-7 -0.000001 (precision fixed) 0.0000023 - 0.00000230002 = -2.0000000000128558e-11 -2e-11 (precision fixed) 100000000000000 - 100000000000000.02 = -0.015625 0 (precision fixed) 10000000000000 - 10000000000000.02 = -0.01953125 -0.02 (precision fixed)
目前看起來可以修正絕大部分的浮點計算偏差
不需要自己設定愚蠢的固定小數位數
且能夠最大有效利用浮點數有效位數