<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-31  評論-257  文章-0  trackbacks-0
     
    最近由於種種緣故又要開始做點教育訓練的事,先趁現在有空把手邊的資料整理一下。

    *Flex 的基礎架構

    關於 flex 基本上常被問到的不外乎就是「如何可以學好它?」,要瞭解這個問題的答案基本上只要看懂下面這圖就ok了。



    *Actionscript 該學的重點

    從最底層看起,最下面的 actionscript 3是一切的基礎,它是 flash/flex 編程使用的唯一程式語言,因此任何人想學好 flex 第一件事絕對是先摸熟 actionscript 這個語言,包含:

    1. 它的基本語法與結構(array, hash, loop, if else…)

    2. DisplayList (DisplayObject, DisplayObjectContainer)與 Event system(bubbling, propagating…)

    3. Sound, Video, NetConnection 與 Graphics class

    掌握 as3 的精華後,接下來就可以進入 flex framework。

    *Flex framework 的重點

    基本上 flex framework 就是用 actionscript 寫成的框架,因此也可以把它看成是 as3的最好示範,看著 framework source 學 actionscript 也是挺不錯的,只是路會變很長。

    Flex Framework 整個體系非常博大精深,通常一般人不太可能完整把它學完,只需要針對最常用到的部份熟悉就好,圖中列出的那三塊(component, managers, style/skin)就是我個人認為所有初學者最優先該學會的。

    *Component 該學些什麼

    Component 是整個 flex framework 的基礎,幾乎80% 的元素都是由 UIComponent 繼承而來,例如最根本的的 它本身就是一個 UIComponent,因此,熟悉 component 就成為學好 flex framework 最根本也最重要的基本功

    Flex 內建了 二十幾個 UI controls, 例如 Button, DataGrid, HBox等,以種類來分,這些 components 可以概分為三大類:

    -Controls: Button, DateChooser, Slider…
    -Containers: Box, DividedBox, Panel…
    -List: DataGrid, Tree, TileList…

    初學者第一步至少該學會怎麼用這些元件,瞭解每個元件的 properties, events, styles, effects…,知道怎麼在手冊裏查它的 API 文件,以及何時該用何種元件。

    進階一點,則是學會怎麼修改這些元件,例如繼承一個 Button 下來加上不同的功能,或是寫不同的 skin border 來改變它的外觀。

    再更進階,則是開始研究元件的生命週期,瞭解每個元件是何時初始化,元件內部有那些關鍵指令與它們個別的功用,然後可以試著建立自已的 custom component。

    這一關看起來容易但實際上最困難,因為 flex 的 component framework 寫的非常龐大,雖然亂中有序但要在混沌中看出隱藏的架構然後抓住重點整串提起,就非得有人帶著指引正確的途徑才比較可能達成。

    *manager 是什麼

    圖中最上方的第二塊就是 manager。

    flex 裏有很多的 managers,負責做各種不同的工作(廢話…),幾個比較重要的包含:

    -SystemManager:
    它是每支 flex app 的根源,最先被下載,也最早啟動,由它進行一連串的 app boot流程

    -StyleManager:
    它負責整支app 的 css style 套用與 skin 生成,如果想玩動態 css 載換也靠它

    -DragManager:
    Flex最大的賣點就是 drag and drop,這個 manager 就是背後的英雄,初學者至少要學會怎麼處理 drag 行為的五個事件,以及如何在不同元件間做拖放;進階的玩家則應該深入研究這支 manager 是怎麼寫成的,詳細閱讀它的 source 會得到意想不到的無窮樂趣(如果你讀完卻沒有這種感覺,呃,那代表你該再多讀幾次,如果還是沒有,那請私下聯絡我 :D)

    -ModuleManager:
    使用 Flex 開發大型應用程式時,往往會將程式切割成許多小的 module, 這個 manager 就是負責載入並管理所有的 module (包含它的 class partition),初心者或許用不到,但有志深入的玩家一定要很熟。

    -CursorManager:
    這個用到的時機不是很多,但偶爾要換一下 cursor 時還是會用到,初學者至少要知道怎麼用指定的圖案去換掉系統cursor。

    *Style/Skin 的重點

    CSS style 與 skinning 是 Flex 最大的賣點之一,也是開發過程中較為麻煩也最耗時的部份。

    初學者應該要徹底瞭解如何使用 CSS style 來打點一支 flex app 的外觀,換顏色、素材,使用外部 assets 修飾介面。

    中階玩家則應該瞭解 skinning 的系統,包含 programmatic skinning 與 graphical skin,它們兩的差別?使用時機?如何客製化?

    更高階的玩家則應該熟悉整個 Styling system 的運作模式,外加如何動態載入 css 在 runtime 換掉整個介面。

    簡而言之,flex app 寫的好不好,外行人其實看不太出來,但一支 app UI 美不美則是一翻兩瞪眼,比較漂亮的那就先加十分

    (當然,有一種情況是刻意用心去美化了介面結果弄巧成拙搞的怨聲載道人人喊打,但那種比較不多見,也不是每家公司都會搞到這步田地,就先不討論)

    *學完基本功後下一步

    在我的標準裏,當一個 developer 對上圖內每一塊都有中等程度的瞭解後,就算是完成 flex 養成教育,可以邁向下一個階段。

    也就是開始熟悉 application 的製作手法,這包含

    -瞭解至少一種以上的開發框架,例如 Cairngorm,老實說我對這個框架沒什麼好感(因為手法太複雜,只適合超複雜登月計畫或火星探勘時使用),但它結構設計良好,又是業界公認的聖盃,等於是專家們共通的語言,因此至少要先瞭解它在做什麼,將來在專業場合才好溝通(俗話說 know the rules so you know what you are breaking, 就是指這情況)

    -接著可以看看比較簡單的手法,像 Riawave, Model-Glue:Flex, PureMVC…等,基本上這些框架設計方式都大同小異,每個都有不同的應用場合,可以挑一個喜歡的再自行修改。

    -瞭解基本的概念,例如 Value Object, DAO, MVC 等,它們在大部份的程式框架裏都會出現,早點學會日子比較輕鬆。

    接著就是開始實際 coding,寫一個中小型規模的app,不論是單純的 CRUD app,或是留言版、電話簿、進銷存管理都可以,籍由多寫來強化編程的概念,然後透過大量的 peer code review 來找出可改進的地方。

    *結論

    結論還是老話一句:要入門 flex 超級簡單,只要不是白癡應該一小時就行,但要成為可獨當一面的專業開發者,路就很長,如果沒有走對方向很容易就迷失甚至最後放棄。

    換句話說,要能成為職場上真正需要的 professional developer,並不如表面上想像的容易(其實我想每種技術領域跟產業都一樣吧),這也是我過去半年來協助很多公司做 recruiting 後的感想。

    posted @ 2008-07-29 14:46 姜大叔 閱讀(1316) | 評論 (0)編輯 收藏
         摘要:       做Flex做久了做大了,就會覺得之前寫的的Flex代碼開始有點亂,哪怕你寫的規范了,但總覺得結構松散,維護不方便,相信很多人剛開始做Flex的時候,都是想到什么功能,就寫什么功能,或者有些好點的,就先畫了個大體的流程圖之類的,因為現在Flex普及得還不夠,很多人做Flex也是試探階段,不敢用作商業項目或其它大項目,只會用來試水技術層面的...  閱讀全文
    posted @ 2008-07-29 14:44 姜大叔 閱讀(4991) | 評論 (32)編輯 收藏
          在上一篇文章中,為大家介紹了Flex中皮膚的簡單且基本也是最常用的用法,就是先在外部程序中做好皮膚樣式,之后再在Flex中加載這些皮膚資源,比如是PNG圖片,或者是SWF文件等,這些方法都是比較直接且方便簡單的。不過靈活性還是不太好,而現在這篇文章中要講的,就是從程序里AS編寫的皮膚,你可以更靈活自由地控制皮膚的樣式與表達方式等,而不用依賴于外部的圖片或SWF資源,不過這樣還是有些缺點的,就是擴展或是改變時就比較不靈活,像圖片資源的皮膚的話,可以很輕易的改變不同的圖片的路徑資源等就可以修改了不同的皮膚模式,而用AS Graphics寫的皮膚的話,要修改一下那些代碼,當然,你也可以在AS代碼里寫上動態加載其它圖片資源又或者作一些更高級的效果等等。

          先在這里解析一下,要以代碼方式自定義一個皮膚的話,需要自已編寫一個皮膚子類,繼承ProgrammaticSkin這個類,這個是所有編寫自定義皮膚的基類,該類也派生了另外兩個類:RectangularBorder 與 Border 類,都是差不多的,如果你是寫Icon之類的小皮膚的話,比如CheckBox或者RadioButton這類皮膚不需要太復雜的畫圖邏輯,而且大小固定,就像是一個小Icon吧,只是有幾個狀態而已,這類小皮膚的話,繼承ProgrammaticSkin就可以了,而寫一些復合的控件,背景大小可以調節之類的皮膚(其實就是大部分皮膚)就用Border或者RectangularBorder類。但都有一個相同點,就是繼承了那些類之后,都必需覆蓋 updateDisplayList 這個方法,這個方法是由程序自動調用,當需要用到控件時,需要控件的皮膚進行表現時,就會調用那個方法,所以你必需覆蓋它,并將你的畫圖邏輯代碼寫在那個方法里面。還有要注意的是,這個皮膚類會與你應用這皮膚的控件的Style設置共享,也就是說你可以在編寫這個皮膚類代碼里面,使用getStyle()等等方法獲得設置在目標控件中的風格屬性,比如說是<mx:Panel backgroundColor="0xffffff" borderSkin="MySkin"> 那么你可以在MySkin代碼里獲取這個顏色值來進行畫出該顏色的圖片或其它操作,而直接將顏色值寫死在代碼里是不規范的,就如我下面貼出來的的代碼,不過出于自已懶,快速代個示例代碼,所以犯這個錯了。說多了,下面看看代碼先。

    好了,我們先看看看代碼,這份代碼是寫了一個Panel的皮膚:
     1 package com.jiangzone
     2 {
     3     import mx.skins.Border
     4     import mx.core.EdgeMetrics;
     5     import mx.core.Container;
     6     import mx.graphics.RectangularDropShadow;
     7    
     8     public class MyPanelBorderSkin extends Border {
     9        
    10         public function MyPanelBorderSkin():void {
    11         }
    12        
    13         /**
    14          * 該方法必需要覆蓋,如果你要自定義自已的皮膚的話,
    15          * 該方法當在控件更新外觀時將會被自動調用
    16          * 會傳入兩個參數數,第一個是Width,第二個是Height,即是該控件的寬與高
    17          * */
    18         override protected function updateDisplayList(w:Number,h:Number):void {
    19             super.updateDisplayList(w,h);
    20            
    21             var ba:uint = 1;                //backgroundAlpha    背景透明度
    22             var bg:uint = 0xffffff;            //backgroundColor    背景顏色
    23             graphics.clear();                //graphics這個屬性是父類里已經提供了的
    24             var p:Container = parent as Container;        //獲取該皮膚所應用在的父容器,這里為Panel
    25            
    26             //這里需要注意,一定要判斷父容器是否已被設置,在文章里作解釋
    27             if(p){
    28                 //獲取容器定義的區域邊界信息對象           
    29                 var vm:EdgeMetrics = p.viewMetrics;       
    30                 //設置四個角的圓度
    31                 var radiusContent:Object = {tl:vm.top,tr:0,bl:0,br:vm.top};   
    32                 //標題欄圓度   
    33                 var radiusTitle:Object = {tl:vm.top,tr:0,bl:0,br:0};       
    34                 //畫一個圓角矩形,整個背景
    35                 this.drawRoundRect(0,0,w,h,radiusContent,bg,ba);
    36                 //畫一個圓角矩形,標題欄   
    37                 this.drawRoundRect(0,0,w,vm.top,radiusTitle,0xff0000,.7);
    38                 //畫一個圓角矩形,標題欄的那個高光水晶條
    39                 this.drawRoundRect(0,0,w,vm.top / 2,radiusTitle,0xffffff,.3);
    40                
    41                 //下面是畫陰影的。
    42                 var dropShadow:RectangularDropShadow = new RectangularDropShadow();
    43                 dropShadow.distance = 8;
    44                 dropShadow.angle = 60;
    45                 dropShadow.color = 0x000000;
    46                 dropShadow.alpha = 0.4;
    47        
    48                 dropShadow.tlRadius = radiusContent.tl;
    49                 dropShadow.trRadius = radiusContent.tr;
    50                 dropShadow.blRadius = radiusContent.bl;
    51                 dropShadow.brRadius = radiusContent.br;
    52        
    53                 dropShadow.drawShadow(graphics, 00, w, h);
    54             }
    55         }
    56     }
    57 }


    上面的代碼就是皮膚的代碼,之后你還要做的,就是將該皮膚應用到Panel這個容器里:
     1 <mx:Application
     2     xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()"
     3     layout="absolute">
     4 
     5     <mx:Style>
     6         .myPanelSkin {
     7             borderSkin: ClassReference( "com.jiangzone.MyPanelBorderSkin" );
     8         }
     9     </mx:Style>
    10    
    11     <mx:Panel borderSkin="com.jiangzone.MyPanelBorderSkin"
    12               width="200" height="150"  x="24" y="23"/>
    13    
    14 </mx:Application>


          代碼很簡單,這里要說一下,viewMetrics 這個屬性是Container控件所獨有的屬性,是一個只讀屬性,編寫Container子類的時候都要覆蓋它,是用于定義這個容器正文區與邊界值的,比如Canvas的四周都是0,所以沒有標題欄與邊條,而Panel就有四周的邊界,而Top邊界比較大,用作顯示title的,所以如果你要做容器的皮膚的話,注意一下這個值。還有就是,為什么獲取了皮膚應用的控件引用(parent)后還要判斷它是否為空?因為當程序加載到這個控件時,是先加載那個皮膚的,所以parent的值未被設置,是空的,如果你不作判斷的話,將會出現空引用的錯誤(parent.viewMetrics),當加載完皮膚后,再加載控件并設置控件的屬性和設置皮膚,這時將會再次調用updateDisplayList的方法,這時parent才有值,就是那個控件的引用。當改變了style或一些屬性后,又會自動觸發調用updateDisplayList方法。

    我們來看看最終運行效果:



    補充一下:
    在第一篇文章里,說了將皮膚做在SWF文件里再加載,想一下,可以將該皮膚做成動畫MC的,而不單單只是一個畫面,可以做成一些動畫作為皮膚,之后在Flex引用該SWF的Symbol,這樣皮膚就有了動畫效果了,不只只是單純的不動的平面圖!

          Flex中的皮膚教程就說到這里,皮膚還有很多可探索的,只要大家有求知欲,多點看看英文文檔,看看別人的例子程序代碼,現在Flex也開源了,也可以多看看Flex的源碼,會得到很多知識!



    posted @ 2008-07-29 14:40 姜大叔 閱讀(2437) | 評論 (2)編輯 收藏
          好久沒有寫文章了,一直用“忙”來為自已找籍口,其實是懶,不過這個月發生了這么大的事情 5.12 讓我們每個人都永記心中,看到中國人的團結,看見解放軍們志愿者們這么努力地為災區奉獻,我也不能再為自已找借口了,雖然我遠在廣東,不能到現場去參與救緩,錢也捐過了,但想想,我還有事情可以做的,就是用我自已的知識,寫點技術文章,雖則不能直接的幫助到災區,但也為國民提高Flex技術知識出分力,做好本職工作。在這里哆嗦點也得說句:為災區遇難者祈禱,為災區救緩不懈努力的軍民給與崇高的敬意!
    .....................................................(三分鐘后)

          好了,我們轉入正題,之前我也寫過Flex的動畫與變換的文章,不知道大家有沒有看過。現在我要寫的就是Flex中的皮膚樣式方面的,我技術不太好,算是自已學習Flex過程中的理解體會吧。
          這里是第一篇,將講述一下Flex中如何應用UI的皮膚,其實應用UI皮膚不難,你們在使用Flex的過程中是否覺得Flex中自帶的皮膚樣式不太好看?或者是想自已做個比較有特色的?下面就我們來說說皮膚吧,先來個簡單的,你們在做網頁時,做導航按鈕什么的很多人都是用一個圖片來作為一個按鈕吧?之后做幾個不同的顏色,之后就在CSS或者JS里設置一下當鼠標Over和Down和Out等等動作時,就切換不同顏色的圖片,這樣實現動態效果。在Flex里也可以如此簡單的做皮膚。你可以先畫好一個UI的皮膚,之就就將該圖片應用到Flex里面。
    先來看看效果:


    之后我們來看看代碼:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" width="257" height="182" backgroundGradientColors="[#ffffff, #ffffff]">
     3    
     4     <mx:Script>
     5         <![CDATA[
     6            
     7             //Embed標簽是用于將一些外部資源加入到Flex中,隨Flex的編譯成SWF文件,
     8             //這里是加入一張PNG圖片,即是做好的Skin圖片
     9             [Embed(source="images/buttonskin.png",
    10                    scaleGridTop="26",
    11                    scaleGridBottom="64",
    12                    scaleGridLeft="30",
    13                    scaleGridRight="106")]
    14             //上面的Embed標簽下面要緊跟著這個Class,意思就是將上面的資源加入到Flex
    15             //后變為這個Class的內容,即調用這個Class時,就是調用那些資源
    16             private var MyBtnSkin:Class;
    17            
    18             //在程序創建完成時會調用該函數,在函數里面設置Button的樣式(Style)
    19             //這里就是設置按鈕的up,over,down三個鼠標狀態時的皮膚,就是上面加入的圖片資源
    20             private function init():void{
    21                 btn.setStyle("upSkin",MyBtnSkin);
    22                 btn.setStyle("overSkin",MyBtnSkin);
    23                 btn.setStyle("downSkin",MyBtnSkin);
    24             }
    25         ]]>
    26     </mx:Script>
    27     <mx:Button id="btn" label="Hello World" width="190" height="90"/>
    28 </mx:Application>


          怎么樣?很簡單吧?大家需要注意一下的是在Embed標簽里,我定義了一些scaleGridTop之類的屬性,這是跟皮膚的縮放有關的,如果不定義那些屬性的話,那么圖片是多大的,就按多大來進行縮放,當你的按鈕很大時,那些皮膚圖片就會被拉大,出現馬賽克與變形等,這都是不好看的。加入了9格縮放模式后,當你縮放按鈕時,九個格中的四個角的區域不會被縮放,保持原樣,中間格會寬高同時縮放,中間上下格會僅是寬度縮放,中間左右格只會高度縮放,這樣,那個皮膚的邊框無論你如何縮放,都是原來的大小比例,而不會將整個圖片一起拉申。
          現在的按鈕太單調了,只有一個外觀,現在大家可以再加多兩個不同顏色或者其它圖案的圖片作為不同狀態的皮膚就可以了,比如將overSkin改成紅色邊框的圖片等。

          其實大家有沒有發現,上面代碼的寫法感覺比較麻煩的。我們可以用CSS來實現,我們可以直接點,將皮膚直接寫在Button上,如下:
    1 <mx:Button label="Hello World"
    2         upSkin="@Embed('images/buttonskin.png')"
    3         overSkin="@Embed('images/buttonskin.png')"
    4         downSkin="@Embed('images/buttonskin.png')"
    5     />

    這樣也是同樣的效果。省事好多了吧。或者我們用CSS來寫:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="257" height="182" backgroundGradientColors="[#ffffff, #ffffff]">
     3     <mx:Style>
     4         Button{
     5             up-skin:Embed(source="images/buttonskin.png",
     6                           scaleGridTop="26",
     7                           scaleGridBottom="64",
     8                           scaleGridLeft="30",
     9                           scaleGridRight="106");
    10             over-skin:Embed(source="images/buttonskin.png",
    11                           scaleGridTop="26",
    12                           scaleGridBottom="64",
    13                           scaleGridLeft="30",
    14                           scaleGridRight="106");
    15         }
    16     </mx:Style>
    17     <mx:Button id="btn" label="Hello World" width="190" height="90"/>
    18 </mx:Application>

    如果覺得加上CSS代碼會令程序代碼混亂的話,就將CSS代碼寫在CSS文件里去,在程序里導入CSS文件就可以了。(至于CSS的用法,我就不說了,反正Flex里的CSS方式與Html里的用法用樣。只是要注意一下CSS里面設置的屬性的名字就可以了)

    <mx:Style source="styles/styles.css" />

          但有人可能會問,這樣做的話,如果一個程序有很多不同的UI,并有不同的皮膚,那不就是要生成很多的圖片?這個問得好,確實,如果以這種方式的話,就像一個網站里的images文件夾一樣,有很多的小圖片,這樣太麻煩了,而且也不好維護。既然有這樣的問題,我們就將皮膚干脆做成在一個文件里面算了,方便快捷,維護又方便,而這個文件,就是SWF文件。我們如果有Flash基礎的話,基本對MC都不會陌生,對,這次我們的主角就是SWF里面的MC,我們可以將一個皮膚做成一個MC,在Flash里將所有用到的皮膚都做在一個SWF里,一個圖片就像是一個MC,之后發布該SWF文件,在Flex里加載這個SWF文件,再在需要的皮膚里調用SWF里面相應皮膚的MC的名字就可以了。如下:
    這個是在Flash里做好的皮膚SWF文件,里面有三個不同顏色的皮膚模式
    [swf]attachments/month_0805/p2008518233635.swf[/swf]
    這里要注意一下,在Flash里做這些皮膚時,要將MC加上鏈接,鏈接的名稱,就是你在Flex里調用該皮膚的名稱,圖片如下:




    在做好皮膚的SWF后,讓我們回到Flex 里面,在Flex里寫如下代碼:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="257" height="182" backgroundGradientColors="[#ffffff, #ffffff]">
     3     <mx:Style>
     4         Button{
     5             up-skin:Embed(source="images/btnSkin.swf",symbol="btnUP");
     6             over-skin:Embed(source="images/btnSkin.swf",symbol="btnOVER");
     7             down-skin:Embed(source="images/btnSkin.swf",symbol="btnDOWN");
     8         }
     9     </mx:Style>
    10     <mx:Button id="btn" label="Hello World" width="100" height="60"/>
    11 </mx:Application>


    注意一下的就是,在Embed標簽里,要導入的資源文件不是PNG了,而是一個SWF,就是我們剛才在Flash里做好的皮膚文件,注意看,后面還跟著一個symbol屬性,該屬性就是指明你要調用哪一個MC,就是SWF里面的MC,記得,都要為每個MC做鏈接,并鏈接名字要與symbol里的名字致。至此,我們的皮膚就完成了。一個SWF文件就搞掂。這里是最終效果:


    好了,這篇教程就到些結束,上面介紹的都是Skin的比較簡單快捷的用法,不過靈活性就不是很大,但也是皮膚技術的最基礎的,大家也可以再擴展一下其它用法等等的,在下篇文章,也就是Flex皮膚系列文章的(二)中,我會介紹一下用程序代碼來編寫皮膚,這就是不依賴于外部的資源文件,直接用AS3代碼用Graphics來自已畫皮膚。下篇將會用到AS3的Draw API方面的知識,請大家做好準備。

    在此再次向我們的災區戰士們給與崇高的敬意!
    posted @ 2008-07-29 14:37 姜大叔 閱讀(7276) | 評論 (5)編輯 收藏
         摘要:       好久沒有發表文章了,這天寫了一個Flash的一個動畫菜單的效果,在之前看到一個站的一個菜單效果挺不錯,就試著自已也用純AS3寫一個出來試試。看了一下研究了一個算法,自已也寫了個出來,寫得比較粗糙,所以運行時可能還會有點小問題,有空要再優化一下算法才行。 有點像 Apple 的菜單效果。原本是計劃用圖片的,不過后...  閱讀全文
    posted @ 2008-07-29 14:33 姜大叔 閱讀(1389) | 評論 (0)編輯 收藏
    用PV3D做的一個Flex效果,有時間會整理一下代碼與文檔貼出來!
    以下是效果:
    posted @ 2008-07-29 14:31 姜大叔 閱讀(12060) | 評論 (133)編輯 收藏
    這篇文章是Flex動畫效果變換的最后一編了,這篇將會講述Flex中的“變面”(我自已的理解)技術,即是Transitions!

    如果看過Flex SDK里面的自帶的例子程序,有一個叫“Flex Store”的應用,在里面的手機列表中看某一個手機的詳細時,就是這種效果,不多說,這篇會比較簡單,先看看效果:


    看到了效果了吧,這種的變換不難實現,再來看看代碼再解析:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="695" height="555">
     3 <mx:states>
     4 <mx:State name="A">
     5     <mx:SetProperty target="{windowA}" name="width" value="500"/>
     6     <mx:SetProperty target="{windowA}" name="height" value="300"/>
     7     <mx:SetProperty target="{windowC}" name="width" value="150"/>
     8     <mx:SetProperty target="{windowC}" name="height" value="150"/>
     9     <mx:SetProperty target="{windowC}" name="y" value="333"/>
    10     <mx:SetProperty target="{windowD}" name="x" value="373"/>
    11     <mx:SetProperty target="{windowD}" name="width" value="150"/>
    12     <mx:SetProperty target="{windowD}" name="height" value="150"/>
    13     <mx:SetProperty target="{windowD}" name="y" value="333"/>
    14     <mx:SetProperty target="{windowB}" name="x" value="23"/>
    15     <mx:SetProperty target="{windowB}" name="y" value="333"/>
    16     <mx:SetProperty target="{windowB}" name="width" value="150"/>
    17     <mx:SetProperty target="{windowB}" name="height" value="150"/>
    18     <mx:SetProperty target="{windowC}" name="x" value="200"/>
    19 </mx:State>
    20 <mx:State name="B">
    21     <mx:SetProperty target="{windowD}" name="width" value="150"/>
    22     <mx:SetProperty target="{windowD}" name="height" value="150"/>
    23     <mx:SetProperty target="{windowC}" name="width" value="150"/>
    24     <mx:SetProperty target="{windowC}" name="height" value="150"/>
    25     <mx:SetProperty target="{windowA}" name="width" value="150"/>
    26     <mx:SetProperty target="{windowA}" name="height" value="150"/>
    27     <mx:SetProperty target="{windowB}" name="width" value="500"/>
    28     <mx:SetProperty target="{windowB}" name="height" value="300"/>
    29     <mx:SetProperty target="{windowA}" name="y" value="333"/>
    30     <mx:SetProperty target="{windowC}" name="x" value="200"/>
    31     <mx:SetProperty target="{windowC}" name="y" value="333"/>
    32     <mx:SetProperty target="{windowB}" name="x" value="23"/>
    33     <mx:SetProperty target="{windowD}" name="x" value="373"/>
    34     <mx:SetProperty target="{windowD}" name="y" value="333"/>
    35 </mx:State>
    36 <mx:State name="C">
    37     <mx:SetProperty target="{windowD}" name="width" value="150"/>
    38     <mx:SetProperty target="{windowD}" name="height" value="150"/>
    39     <mx:SetProperty target="{windowB}" name="width" value="150"/>
    40     <mx:SetProperty target="{windowB}" name="height" value="150"/>
    41     <mx:SetProperty target="{windowA}" name="width" value="150"/>
    42     <mx:SetProperty target="{windowA}" name="height" value="150"/>
    43     <mx:SetProperty target="{windowC}" name="width" value="500"/>
    44     <mx:SetProperty target="{windowC}" name="height" value="300"/>
    45     <mx:SetProperty target="{windowA}" name="y" value="333"/>
    46     <mx:SetProperty target="{windowB}" name="x" value="200"/>
    47     <mx:SetProperty target="{windowB}" name="y" value="333"/>
    48     <mx:SetProperty target="{windowC}" name="x" value="23"/>
    49     <mx:SetProperty target="{windowC}" name="y" value="19"/>
    50     <mx:SetProperty target="{windowD}" name="x" value="373"/>
    51     <mx:SetProperty target="{windowD}" name="y" value="333"/>
    52 </mx:State>
    53 <mx:State name="D">
    54 <mx:SetProperty target="{windowC}" name="width" value="150"/>
    55 <mx:SetProperty target="{windowC}" name="height" value="150"/>
    56 <mx:SetProperty target="{windowB}" name="width" value="150"/>
    57 <mx:SetProperty target="{windowB}" name="height" value="150"/>
    58 <mx:SetProperty target="{windowA}" name="width" value="150"/>
    59 <mx:SetProperty target="{windowA}" name="height" value="150"/>
    60 <mx:SetProperty target="{windowD}" name="width" value="500"/>
    61 <mx:SetProperty target="{windowD}" name="height" value="300"/>
    62 <mx:SetProperty target="{windowA}" name="y" value="333"/>
    63 <mx:SetProperty target="{windowB}" name="x" value="200"/>
    64 <mx:SetProperty target="{windowB}" name="y" value="333"/>
    65 <mx:SetProperty target="{windowD}" name="x" value="23"/>
    66 <mx:SetProperty target="{windowD}" name="y" value="19"/>
    67 <mx:SetProperty target="{windowC}" name="x" value="373"/>
    68 <mx:SetProperty target="{windowC}" name="y" value="333"/>
    69 </mx:State>
    70 </mx:states>
    71 <mx:transitions>
    72 <mx:Transition fromState="*" toState="*">
    73 <mx:Parallel targets="{[windowA, windowB, windowC, windowD]}">
    74 <mx:Move />
    75 <mx:Resize />
    76 </mx:Parallel>
    77 </mx:Transition>
    78 </mx:transitions>
    79 <mx:TitleWindow x="23" y="19" width="250" height="200" layout="absolute" title="A" id="windowA" click="currentState='A'" />
    80 <mx:TitleWindow x="309" y="19" width="250" height="200" layout="absolute" title="B" id="windowB" click="currentState='B'" />
    81 <mx:TitleWindow x="23" y="260" width="250" height="200" layout="absolute" title="C" id="windowC" click="currentState='C'" />
    82 <mx:TitleWindow x="309" y="260" width="250" height="200" layout="absolute" title="D" id="windowD" click="currentState='D'" />
    83 </mx:Application>


    代碼會比較多,我們先看看<mx:states>標簽,它是一個集合,就是你的程序有多少個狀態,什么是狀態呢?我自已理解就即是有多少個“面譜”,即是現在程序里面有四個顯示界面狀態,所以里面有四個<mx:State>標簽,每個<mx:State>狀態都需要有一個名字name屬性,以區分是哪個界面狀態,在每個狀態里面都有很多<mx:SetProperty>的標簽,看英文都知道了,該標簽用于設置這個狀態下的所有界面元素的屬性(組件的屬性),因為每個界面狀態中各個組件的大小布局都不同,所以在狀態標簽里就要預先設置好該狀態下的組件的位置與大小,那個target="{windowC}"屬性就是設置你要設置的哪個組件的名字拉,name="height"就是你要設置的屬性value="333"就是你要設置該屬性的值,我們細心看看的話,可能會發現,每個狀態里面設置的屬性,都是width,height,x,y這四個屬性,我們看看上面的最終效果就知道無論切換哪個狀態,組件間的變換來來去去都是移動位置與大小改變,就是說當你變換狀態時,需要改動哪些屬性的,就將它的目標值設置在<mx:SetProperty>標簽里。再看看下面的<mx:transitions>標簽,這個也是個集合,里面放著不同的變換方法<mx:Transition>,我們來看看變換標簽的代碼:
    1 <mx:Transition fromState="*" toState="*">
    2 <mx:Parallel targets="{[windowA, windowB, windowC, windowD]}">
    3 <mx:Move />
    4 <mx:Resize />
    5 </mx:Parallel>
    6 </mx:Transition>

    formState與toState屬性是要設置該狀態變換是怎樣觸發的,里面要填上狀態的名字,<mx:State name="C">   C就是狀態的名字,即是如果你formState="A",toState="C"的話,只有從A狀態切換到C狀態時,才會產生以上的變換動畫效果,如果不附合該規則如A切換到B狀態的話,則只會按狀態的屬性設置值來直接生成視圖,而沒有動畫漸變效果了。如果填上“*”的話,就是無論是哪個狀態切換到哪個,都會運行動畫效果,至于變換期間用到哪種動畫效果來進行漸變,就在它的下級標簽里定義了,這里它用到了<mx:Parallel>并列播放移動與重整大小的動畫效果,之前文章講過,這里不多說了。基本上,一個變換就做好了,但我們還需要觸發它,也就是去改變程序當前的顯示狀態:click="currentState='A'" 在每個組件的click事件里,改變程序的currentState值,就是改變程序的當前顯示狀態!之后動畫效果就會觸發了!

    遲點有時間,再做一個3D的動畫效果,將會用到PV3D的框架,再整理一個代碼與教程也貼出來跟大家分享吧,不過不知道大家對PV3D這個東東熟悉不,不熟悉的話,可能看得痛苦點,至于PV3D方面的教程,我也看看抽點時間寫寫吧!先謝過大家的支持!
    posted @ 2008-07-29 14:28 姜大叔 閱讀(6902) | 評論 (6)編輯 收藏
    在上篇文章《Flex的動畫效果與變換(一)》中講到了使用Flex系統里面自帶的一些動來效果的使用,但很多開發者都并不滿足Flex里提供的簡單的漸變大小,透明,移動,遮罩等的效果,如果是Flash的開發者的話,更不用說了,在Flash,多數人都是隨意的制作一些動畫效果等,而且形態多變。但是不是Flex里就不能實現呢?肯定不是,在Flex里也可以自定義動畫效果,只不過就是沒有Flash里面那么簡單隨意了。不過熟悉了之后,也會覺得在Flex里制作動畫也不是什么難事,不多說了,轉入正題!

    在這里我先介紹一下Flex里面的動畫效果機制,在Flex里面要使用動畫效果的話,先要創建一個效果標簽,之后在組件里(如TextInput)寫上效果觸發器,但可能會有人問,如果程序里我就只定義一個移動效果
    <mx:Move>,之后我程序里面有5個組件,每個組件的動畫效果都指向這個Move效果,那么它是不是組件一運行了效果后,組件二再觸發效果,是不是組件一的效果會消失才會到組件二里播放?其它不是,雖然我們只定義了一個Move,但我們定義的只是Move效果的工廠,這里就用到了設計模式中的“工廠方法”模式,其實5個組件都可以同時運行效果,而5個效果都是不同的一個實例,彼此獨立。所謂工廠方法模式,就好比是一家衣服制造工廠,A走進這家工廠說要一件衣服,工廠就制作一件合適A的Size的衣服,B進去,就會生產合適B的衣服,但A與B的衣服都是一樣的。就好等于面向對象中的類與對象的關系一樣。(我可能說多了-_-)
    效果運行的時候,其實運行的不是Move這個對象,而是MoveInstance這個對象,Move只是工廠,既然一個動畫效果就主要分這兩大部份,我們就先建造一個工廠吧!

    在Flex里面所有的效果的工廠都是繼承自 mx.effects.Effect 這個類,我們也不能搞特殊,我們自定義的效果也要繼承那個類,先看以下整個工廠類的代碼:
     1 package com.jiangzone.flex.effects {
     2     import mx.effects.Effect;
     3     import mx.effects.EffectInstance;
     4    
     5     public class MyEffect extends Effect {
     6         private var _color:Number = 0xFF0000;
     7                
     8                 public function set color(value:Number):void {
     9                          _color = value;
    10                 }
    11 
    12         public function MyEffect(newTarget:Object = null) {
    13             super(newTarget);
    14             instanceClass = MyEffectInstance;
    15         }
    16        
    17         override public function getAffectedProperties( ):Array {
    18             return [];
    19         }
    20        
    21         override protected function initInstance(instance:EffectInstance):void {
    22             super.initInstance(instance);
    23                         MyEffectInstance(instance).color = _color;
    24         }
    25     }
    26 }


    大家看看上面的代碼,其中先看構造函數,構造函數要接收一個默認為空的Object對象
    public function MyEffect(newTarget:Object = null)
    之后在該構造函數里面調用父類的構造函數,并且將instanceClass這個屬性設置為你的該效果的實例類,因為這個類是工廠類,所以要知道你這個工廠生產什么產品,即上面說的“衣服”,所以這里我們將其命名為MyEffectInstance,注意:在Flex中的所有效果實例類都是在工廠類后面加Instance,也不是一定,只是規范而已。還有注意,下面一會定義的實例類的類名一定要跟這里的一致。
    大家還會看到,上面的代碼中,復寫(override)了二個方法:getAffectedProperties( )與initInstance(instance:EffectInstance)
    這兩個方法都是要復寫的,先說說getAffectedProperties( )這個方法,這個方法是獲取被改變的屬性值,怎么說呢,比如說,你做的動畫效果如果要用到組件對象的一些屬性的話,就要返回這些屬性的名字,如:你的效果是對組件做旋轉的話,則:
    1 override public function getAffectedProperties( ):Array {
    2     return ["rotation"];
    3 }

    反正你做的效果需要對組件修改什么屬性的話,都在這個方法里返回名字,修改多個屬性的話就往數組里加就是了。
    后面就是這個方法了initInstance,該方法接收一個instance:EffectInstance參數,也就是效果實例類啦,因為每個效果實例類都要繼承EffectInstance類,所以這個方法里的參數寫的是父類,在里面要做其它的話,需要將 instance 轉換為你相應的效果類。在這個方法里面,也是要調用父類的同名方法:super.initInstance(instance);
    基本上,一個工廠類就寫好了,但這樣只是最簡單的寫法,試想想,每個人穿衣服的Size不同,喜歡的顏色也不同,所以,是不是可以由用戶來定義他們想要的效果的顏色等屬性呢?當然,你對衣服有什么要求,都是向工廠提出的,沒有人會對衣服說吧?所以,這些可設置的屬性也是定義在工廠類里面,所以下面,我們為該衣服可定制顏色為例,在工廠類里面加入如下代碼:
    1 private var _color:Number = 0xFF0000;
    2 public function set color(value:Number):void {
    3         _color = value;
    4 }

    你想運行時的效果可以設置不同的顏色的話,就可以直接設置MyEffect的color屬性,之后將這個屬性傳給效果實例類:
    1 override protected function initInstance(instance:EffectInstance):void {
    2     super.initInstance(instance);
    3         MyEffectInstance(instance).color = _color;
    4 }

    這些對效果實例類的設置,都是要定在initInstance方法里了,你想對運行時的效果設置什么屬性的話,都要先告訴工廠類,之后工廠類在這個方法里面轉嫁給實例類,這樣,同一個效果,可以運行不同的顏色。但前提是你后面要寫的實例類要有color這個屬性。
    現在已做好了工廠類了,下面要做效果實例類了,先貼出完整代碼:
     1 package com.jiangzone.flex.effects {
     2     import mx.effects.EffectInstance;
     3     import flash.display.Shape;
     4     import flash.events.Event;
     5    
     6     public class MyEffectInstance extends EffectInstance {
     7                
     8         private var _color:Number;
     9         private var shape:Shape;
    10        
    11         public function set color(value:Number):void {
    12             _color = value;
    13         }
    14        
    15         public function MyEffectInstance(newTarget:Object) {
    16             super(newTarget);
    17         }
    18        
    19         override public function play( ):void {
    20             super.play( );
    21             drawShape();
    22         }
    23        
    24         private function drawShape():void{
    25             shape = new Shape();
    26             shape.graphics.beginFill(_color);
    27             shape.graphics.drawRect(target.width * -0.5,target.height * -0.5,target.width,target.height);
    28             shape.graphics.endFill();
    29             shape.x = target.x + target.width * 0.5;
    30             shape.y = target.y + target.height * 0.5;
    31             target.parent.rawChildren.addChild(shape);
    32             target.addEventListener(Event.ENTER_FRAME,onEnterFrame);
    33         }
    34        
    35         private function onEnterFrame(e:Event):void{
    36             shape.scaleX += 0.1;
    37             shape.scaleY += 0.1;
    38             shape.alpha -= 0.05;
    39             if(shape.alpha <= 0){
    40                 target.parent.rawChildren.removeChild(shape);
    41                 target.removeEventListener(Event.ENTER_FRAME,onEnterFrame);
    42             }
    43         }
    44     }
    45 }


    我們看到,每一個動畫效果實例類,都要繼承自EffectInstance這個類,構造函數也是需要接收一個Object,這個Object其實就是你要應用到的組件對象,這個會是系統自動傳遞的,接收了Object后還要用該Object 調用父類的構造函數:super(newTarget);
    之后還有一件必做的事,就是重寫play()這個方法:override public function play( ):void
    是不是對play()很熟悉?因為第一篇文章中,就用到這個方法來發動效果的播放的,所以,你需要做的動畫編程都是在這個方法里。但還是要先調用父類的同名方法,super.play();之后的,就是你想怎么畫就怎么畫啦。我將畫一個與要應用效果的組件一樣大小的矩型,之后該矩形會放大并透明,效果都寫在drawShape()方法里了。看到這個方法里面的代碼,是不是跟Flash里的一樣了?
    這里再貼上MXML代碼:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application layout="absolute" xmlns:mx="http://www.adobe.com/2006/mxml"
     3                                                         xmlns:pf="com.jiangzone.flex.effects.*">
     4         <pf:MyEffect id="myEffect" color="0xFFFFFF" />
     5         <mx:VBox x="100" y="43">
     6                 <mx:TextInput focusInEffect="{myEffect}" />
     7                 <mx:TextInput focusInEffect="{myEffect}" />
     8                 <mx:TextInput focusInEffect="{myEffect}" />
     9                 <mx:TextInput focusInEffect="{myEffect}" />
    10         </mx:VBox>
    11 </mx:Application>

    這里先看看最終效果:


    在這里,我用了ENTER_FRAME的寫法,但是如果不用ENTER_FRAME方式制作動畫的話,還有另外一種方法的,那就是Tween了,Tween是以“時間”為準,而ENTER_FRAME是以“幀”為準,其實到這里,一個基本的Flex自定義動畫效果就完成了,但擴展一下的,還可以用Tween來實現,而且建議用Tween來寫動畫效果,易控制,清淅一點。用Tween實現的話,效果與寫法都是差不多的,要用Tween就要將效果實例類繼承自TweenEffectInstance這個類,并重寫它的onTweenUpdate( )方法與onTweenEnd( )方法,這種Tween效果的寫法,將會比ENTER_FRAME的寫法方便,因為它根據的是時間,所以,你可以指定效果播放的時間,并且當播放完畢會自動調用onTweenEnd()方法,你可以在該方法里寫一些處理操作,如釋放資源等等
    由于編幅關系,就不在這里詳細介紹TweenEffectInstence了,就簡單貼出該類的寫法與注釋吧:
     1 package com.jiangzone.flex.effects {
     2     import mx.effects.effectClasses.TweenEffectInstance;
     3     import flash.display.Shape;
     4     import flash.events.Event;
     5     import mx.effects.Tween;
     6    
     7     public class MyEffectInstance extends TweenEffectInstance {
     8                
     9         private var _color:Number;
    10         private var shape:Shape;
    11        
    12         public function set color(value:Number):void {
    13             _color = value;
    14         }
    15        
    16         //構造函數
    17         public function MyEffectInstance(newTarget:Object) {
    18             super(newTarget);
    19         }
    20        
    21         //同樣的要重寫play()方法與調用父類同名方法
    22         override public function play( ):void {
    23             super.play();
    24             drawShape();        //先創建一個矩形
    25             /*注意:用Tween效果寫法的話,就一定要創建一個Tween對象
    26             第一個參數是偵聽器,即偵聽Update與End的,這兩個方法都在這個類里,
    27             所以這里就寫this,第二和第三個參數都是一個數組
    28             第二個參數是初始值數組,第三個是結果值數組,都要一一對應,第四個是變化時間
    29             這里的是[1,1]分別是初始時的scale比例與alpha,[3,0]就是最終結果數值
    30             系統會自動在1000毫秒里平分這些值來得到漸變效果
    31             并將每一次數值的改變時調用Update方法,結束后調用End方法
    32                     你也可以將時間的參數發布到工廠類屬性里,可以方便設置播放時間,像Flex自帶效果一樣
    33                          */
    34             new Tween(this,[1,1],[3,0],1000);
    35         }
    36        
    37         override public function onTweenUpdate(value:Object):void{
    38             //這里將改變的數值應用到組件對象中。注意:也要與上面的數值數組相對應。
    39             shape.scaleX = Number(value[0]);
    40             shape.scaleY = Number(value[0]);
    41             shape.alpha = Number(value[1]);
    42         }
    43        
    44         override public function onTweenEnd(value:Object):void {
    45             //當播放完時會自動調用該方法,這里就做刪除該矩形的操作吧
    46             target.parent.rawChildren.removeChild(shape);
    47         }
    48        
    49         private function drawShape():void{
    50             shape = new Shape();
    51             shape.graphics.beginFill(_color);
    52             shape.graphics.drawRect(target.width * -0.5,target.height * -0.5,target.width,target.height);
    53             shape.graphics.endFill();
    54             shape.x = target.x + target.width * 0.5;
    55             shape.y = target.y + target.height * 0.5;
    56             target.parent.rawChildren.addChild(shape);
    57         }
    58     }
    59 }


    就寫到這里吧,關于Tween其它的,就留作為作業,讓大家思考與探索吧!之后如果有時間的話,將會寫完下篇文章介紹Flex的“變面”動畫,即狀態變換!這里先謝謝大家支持!
    posted @ 2008-07-29 14:24 姜大叔 閱讀(5680) | 評論 (7)編輯 收藏
    在Flex里面不像在Flash里面隨意制作動畫了,Flex更趨向于應用程序,而不是動畫制作了,所以沒有了時間軸的概念。在Flex中使用動畫效果,可以用Flex自帶的Effect,或者自已定制Effect,因為很多人都想借Flash里面的一樣操作Flex,比如在Flash里面做一個動態按鈕很容易,當鼠標移動到上面時,會有很多發光的點跑出來(熒火蟲效果),這種效果在Flash十分容易實現,但在Flex里面要實現這種效果就不是那么簡單的了,下面說說在Flex里的的動務效果的使用與自定義制作。

    首先介紹一下Flex里面的自帶的效果有以下幾種:
      Blur                            模糊效果
      Move                          移動效果
      Fade                          淡入淡出效果            
      Glow                          發光效果
      Resize                       調整大小效果
      Rotate                       旋轉效果
      Zoom                         縮放效果
      WipeLeft                    用遮罩實現畫面收放效果,下同,分別為不同方向
      WipeRight
      WipeUp
      WipeDown

    不同的效果所需要設置的屬性也不一樣,比如Blur效果需要設置它的X與Y軸的模糊像素
    <mx:Blur id="blur" blurXFrom="0" blurXTo="10" />
    而Move效果需要設置移動的位置信息
    <mx:Move id="moveEffect" xFrom="-100" />
    其它設置可以參考Flex語言參考

    下面說說如何使用這些效果。要運行這些效果有兩種方法:一種是調用該效果的play()方法,另外一種是使用觸發器來觸發效果。
    (1)使用play()方法:
    先看效果:

    以下代碼:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
     3     <mx:Script>
     4         <![CDATA[
     5             private function onClick(event:Event):void {
     6                 be.target = event.currentTarget;
     7                 be.play( );
     8             }
     9         ]]>
    10     </mx:Script>
    11    
    12     <mx:Blur id="be" blurXTo="50" blurYTo="50" duration="1000" />
    13 
    14     <mx:Panel id="p" width="200" height="180" click="onClick(event)" />
    15 </mx:Application>


    在代碼中看到,要使用效果,先定好一個效果,如上面的<mx:Blur ...>該標簽就是模糊效果的MXML標簽,定好效果后在Panel的點擊事件里再對該效果進行一些設置,如be.target = event.currentTarget 設置該效果將要應用到的目標組件(Component),之后再調用play()方法后,該效果就會應用在Panel上面播放!

    (2)使用觸發器播放效果:
    使用觸發器播放效果的話,可以不用寫ActionScript代碼,直接在組件的效果觸發器上指明使用哪個效果就可以了,比較簡單明了,但就不能進行更多的屬性定制,而用AS控制播放的話,可以對效果進行很多的設置再相應根據情況播放,先看看觸發器播放的代碼:
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    3    
    4     <mx:Blur id="be" blurXTo="50" blurYTo="50" duration="2000" />
    5 
    6     <mx:Panel id="p" width="200" height="180" creationCompleteEffect="{be}" />
    7 </mx:Application>


    看以上代碼,先寫好了Blur的效果并設置好屬性后,duration="2000"這個是播放的時間以毫秒為單位。
    在Panel標簽里有這樣一句:creationCompleteEffect="{be}" 這個就是觸發器,是該Panel組件的效果觸發器,當Panel組件加載完成時,會由系統自動調用該效果觸發器,觸發器里面指了觸發 be 這個Blur效果
    在Flex里面還有很多觸發器如:
      addedEffect                                       被添加進容器時觸發效果
      removedEffect                                   被從容器中移除時觸發效果
      creationCompleteEffect                     被創建成功時觸發效果
      focusInEffect                                     獲得焦點時觸發
      focusOutEffect                                   失去焦點時觸發
      hideEffect                                          被隱藏時(visible=false)觸發
      showEffect                                        被顯示時(visible=true)觸發
      rollOverEffect                                     鼠標經過時觸發
      rollOutEffect                                       鼠標離開時觸發
      mouseDownEffect                              鼠標按下時觸發
      mouseUpEffect                                   鼠標松開時觸發
      moveEffect                                         被移動時觸發
      resizeEffect                                       被重整大小時觸發

    注意:這些都是效果觸發器,不要與事件觸發器混亂了。事件觸發器是rollOver,事件觸發器與效果觸發器差不多,事件觸發器是當用戶執行相就操作時觸發事件,將會調用自定的事件觸發處理函數,而效果觸發器是執行相應操作時被觸發并由系統自動調用所定的效果的play()方法。

    現在說說效果的一些其它屬性:
    每個效果都有reverse( );方法,該方法是反向播放,原本由小到大的變化,而調用reverse( );后再運行play()的話,效果將會從大到小進行播放。
    但要注意的一點是,reverse( );不會自動播放,即是單單調用reverse( );的話,效果并不會播放,他只會記錄該效果為倒轉,而要再調用play()后倒轉效果才會開始播放。而調用pause( )與resume( )就是暫停與繼續播放效果

    startDelay這個屬性是設置效果的播放延時,以毫秒為單位,即要等待多少毫秒后效果才開始播放,如:
    <mx:Blur id="be" blurXTo="50" startDelay="3000" />
    該模糊效果將會在調用play()之后3秒才開始播放

    repeatCount這個屬性是設置效果的重復次數,默認為1,設置為0的話就是不停循環播放
    <mx:Blur id="be" blurXTo="50" startDelay="3000" repeatCount="5" />

    每個效果都有兩個事件:effectStart 與 effectEnd
    你可以在該效果事件的處理函數里面對效果作相應的操作,如:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
     3     <mx:Script>
     4         <![CDATA[
     5             import mx.events.EffectEvent;
     6             public function onEffEnd(e:EffectEvent):void{
     7                 e.effectInstance.reverse();
     8                 e.effectInstance.play();
     9             }
    10         ]]>
    11     </mx:Script>
    12     <mx:Blur id="be" blurXTo="50" blurYTo="50" duration="2000" />
    13 
    14     <mx:Panel id="p" width="200" height="180" creationCompleteEffect="{be}" effectEnd="onEffEnd(event)" />
    15 </mx:Application>

    當效果播放完時,系統將會自動觸發effectEnd事件,在處理函數里面,將該效果Instance即現時播放的效果實例進行倒轉并播放,當播放完,又會觸發effectEnd事伯,這樣一直循環!

    現在再來說說效果的組合:
    通常如果你覺得只應用一個效果很單調的話,可以進行效果組合應用,即多個效果同時播放或者順序播放,
    如,當加載頁面時,你想Panel先模糊到一定程度,再將Panel移動到某個位置,再把Panel還原成原來的清淅度(即消退模糊)。這樣分析一下,一共用了三個效果,一,先應用Blur(由清至模)效果,當Blur完成時,再應用Move效果,當Move完成時,再應用另外一個Blur(由模至清)效果。這樣三個效果組合就是按順序組合,先后運行。先來看看效果:

    再來看看代碼:
     1 <?xml version="1.0" encoding="utf-8"?>
     2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
     3    
     4     <mx:Sequence id="sequenceEffect">
     5         <mx:Blur id="beOut" blurXTo="50" blurYTo="50" duration="500" />
     6         <mx:Move id="mv" xTo="200" yTo="150" duration="500" />
     7         <mx:Blur id="beIn" blurXFrom="50" blurYFrom="50" blurXTo="0" blurYTo="0" duration="500" />
     8     </mx:Sequence>
     9    
    10     <mx:Panel id="p" width="200" height="180" mouseDownEffect="sequenceEffect"  />
    11 </mx:Application>

    看以上代碼,<mx:Sequence id="sequenceEffect">標簽就是順序組合效果標簽,當應用sequenceEffect效果的時候,它會按順序播放該標簽里面的三個子效果。

    另外的就是同時播放了,
    1 <mx:Parallel id="parallelEffect">
    2           <mx:Blur id="beOut" blurXTo="50" blurYTo="50" duration="500" />
    3       <mx:Move id="mv" xTo="200" yTo="150" duration="500" />
    4 </mx:Parallel>

    這個標簽就是同時播放的效果標簽,放在它里面的子效果都會同時播放,即一邊模糊一邊移動。這個都可以自由組合,<mx:Parallel>與<mx:Sequence>標簽都可以自由組合,例如先按順序先播放模糊,再同時播放移動與隱藏等。這里就不多說了。

    使用Flex自帶的效果基本用法就這些,下篇文章將討論自定義效果的制作,下篇將會詳細說說這篇文章上面說到的 effectInstance 即實例與工廠的概念。



    posted @ 2008-07-29 14:20 姜大叔 閱讀(20792) | 評論 (6)編輯 收藏
          近來在學習Flash的3D技術,現在我看過的就PV3D 與Away3D這兩個開源框架,感覺還不錯,好像Away3D的效果好點,但效率不如PV3D,PV3D算是亻為(不會用五筆打這個字-_-,我機子里又沒拼音輸入,將就下吧!)3D,不管這么多了,做個東西練練手,先看效果:



    [url=http://www.jiangzone.com.cn/jiang/3dmusic/soundtest.swf]這里看看效果![/url]

        這個程序很簡單到沒無簡單了,就只是用了PV3D框架中的Cube的3D對象,一口氣生成64個放在數組里待用,之后用Flash里的聲音類加載并播放聲音,之后在ENTER_FRAME事件里檢測當前聲音的頻譜,之后根據頻譜的高低來調整Cube格子的高低,在Flash里獲取的聲音頻譜有512個Float數據,代表512級頻譜,而前256級為LeftChangle,后256級為RightChangle,由于如果生成256個3D對象的話,對CPU來說是個考驗,所以就折中間隔抽取64個頻段來顯示,由于懶于寫代碼了,就只寫了LeftChangle的頻譜。

        以下是代碼:
      1 //************導入需要用到的類
      2 import flash.display.Sprite;
      3 import org.papervision3d.scenes.Scene3D;
      4 import org.papervision3d.cameras.FreeCamera3D;
      5 import org.papervision3d.objects.Cube;
      6 import org.papervision3d.materials.MaterialsList;
      7 import org.papervision3d.materials.WireframeMaterial;
      8 import org.papervision3d.materials.ColorMaterial;
      9 import org.papervision3d.cameras.Camera3D;
     10 import     org.papervision3d.objects.Plane;
     11 
     12 //************定義需要用到的對象
     13 var cont:Sprite;
     14 var scene:Scene3D;
     15 var camera:FreeCamera3D;
     16 var ml:MaterialsList;
     17 var material:ColorMaterial;
     18 var cubeArr:Array;
     19 
     20 //***********設置放置3D東東的容器
     21 cont = new Sprite();
     22 cont.x = 150;
     23 cont.y = 120;
     24 this.addChild(cont);
     25 
     26 //******設置一個3D場景,并設置好Camera的位置與角度
     27 scene = new Scene3D(cont);
     28 camera = new FreeCamera3D();
     29 camera.z = 1200;
     30 camera.x = 100;
     31 camera.y = 700;
     32 camera.rotationX = -30;
     33 camera.rotationY = 180;
     34 camera.focus = 100;
     35 camera.zoom = 10;
     36 
     37 //***********定義一個存放所有格子的數組
     38 cubeArr = new Array();
     39 
     40 //定義一個顏色材質與材質列表,用于應用于格子的6個面的貼圖
     41 material = new ColorMaterial(0x096288);
     42 ml = new MaterialsList();
     43 ml.addMaterial(material,"front");
     44 ml.addMaterial(material,"back");
     45 ml.addMaterial(material,"top");
     46 ml.addMaterial(material,"bottom");
     47 ml.addMaterial(material,"left");
     48 ml.addMaterial(material,"right");
     49 
     50 var i:int = 0;
     51 var j:int = 0;
     52 
     53 //生成64個小格子并排列好位置
     54 for(;i<64;i++){
     55     ml.addMaterial(new ColorMaterial(0xB9DFCF),"top");
     56     var c:Cube = new Cube(ml,20,20,20);
     57     c.x = (i % 8* (20 + 5);
     58     c.z = (j % 8* (20 + 5);
     59     (i % 8 == 0? j++:j=j;
     60     cubeArr[i] = c;
     61     scene.addChild(c);
     62 }
     63 
     64 //創建一個面板,設置好位置放在小格子隊列的下面(地板)
     65 var plane:Plane = new Plane(new WireframeMaterial(0xaaaaaa),300,300,7,7);
     66 plane.rotationX = -90;
     67 plane.y = -50;
     68 plane.x = 70;
     69 plane.z = 60;
     70 scene.addChild(plane);
     71 
     72 //以上是3D部分,以下是聲音部分
     73 //建立一個字節數組用于存放獲取到的頻譜信息
     74 var bArr:ByteArray = new ByteArray();
     75 //讀取聲音文件并播放
     76 var req:URLRequest = new URLRequest("a.mp3");
     77 var sound:Sound = new Sound(req);
     78 sound.play();
     79 
     80 //添加一個事件偵聽器
     81 this.addEventListener(Event.ENTER_FRAME,onEnter);
     82 
     83 function onEnter(e:Event):void{
     84     //獲取當前聲音頻譜,將數據存放在bArr里面。
     85     //true為頻譜模式,0為采樣率代號
     86     SoundMixer.computeSpectrum(bArr,true,0);
     87     i=0;
     88     //讀取前256個數據,即Left聲道的頻譜
     89     for(;i<256;i++){
     90         var temp:Number = bArr.readFloat();
     91         //間隔4個數據中獲取一個顯示
     92         if(i % 4 == 0){
     93             //從數組中獲取相應的格子
     94             var c:Cube = cubeArr[i/4] as Cube;
     95             //設置格子在三維坐標中的高。
     96             //由于頻譜數據是0-1,所以將其放大100倍
     97             c.y = temp * 100;
     98         }
     99     }
    100     //鏡頭旋轉移動
    101     camera.moveLeft(12);
    102     camera.rotationY += 0.6;
    103     scene.renderCamera(camera);
    104 }



    posted @ 2008-07-29 14:16 姜大叔 閱讀(1456) | 評論 (1)編輯 收藏
    僅列出標題
    共4頁: 1 2 3 4 下一頁 
    主站蜘蛛池模板: 午夜在线免费视频| 亚洲高清日韩精品第一区| 在线观看免费精品国产| 成人免费午夜在线观看| 18禁止观看免费私人影院| 国产免费一区二区三区| 日韩免费一区二区三区在线 | 亚洲国产精品无码第一区二区三区| 亚洲成人网在线观看| 亚洲一区二区三区精品视频| 亚洲w码欧洲s码免费| 日韩亚洲不卡在线视频中文字幕在线观看| 亚洲国产成人精品青青草原| 亚洲午夜精品一区二区公牛电影院| 亚洲一级毛片免费看| 亚洲区日韩精品中文字幕| 久久精品国产亚洲AV电影网| 免费人成大片在线观看播放电影| 日韩在线视频线视频免费网站| jzzjzz免费观看大片免费| 久久免费区一区二区三波多野| 24小时免费看片| 在线观看免费宅男视频| 全黄性性激高免费视频| 亚洲中文字幕无码久久2017 | 在线观看人成网站深夜免费| 免费人成视频在线观看不卡| av在线亚洲欧洲日产一区二区| 亚洲国产精品久久久天堂| 亚洲国产视频网站| 亚洲成a人片在线观看天堂无码| 看成年女人免费午夜视频| 91成人免费观看在线观看| 999久久久免费精品播放| 久久久久久99av无码免费网站| 国产成人精品免费视频软件| 亚洲色成人中文字幕网站| 亚洲综合免费视频| 色偷偷亚洲男人天堂| 成人性生交大片免费看中文| 丁香花免费完整高清观看|