跳到主要內容

AS3.0網站架構程式碼設計新手篇。

AS3.0網站架構程式碼設計新手篇。
來講解一下一般網站在程式碼設計時, 應該要怎麼製作
第一篇奶老師我所寫的方法
是採用所謂的"直覺式"寫法。
按下A按鈕,叫b和C做事情。
按下B, 叫D做事情, 很直覺

接來來會有進階篇和物件導向篇。
寫時間軸的方法我就不多加介紹。
Step1:建立類別包資料夾
好比客戶公司是:milkmidi
這次專案名稱是:demo
那資料夾結構就會是
milkmidi--demo
然後再依不同的fla開啟對映的資料夾
首頁是index.fla, 就會搭配一個IndexMain.as檔
路徑如下:
milkmii--demo--index--IndexMain.as
所以類別包的寫就也就是
package milkmidi.demo.index{
public class IndexMain extends MovieClip(){}
}

Step2:因為一個專案, 除了專案的類別檔, 還會再額外的使用其他類別。
這樣資料夾會有一大堆, 不好管理。
所以會再加開一個名為src的資料夾
把所有的類別通通放被去。
這時候的資料夾結構為:
src--milkmidi--demo--
那是不是類別包路徑也要跟著改, 在這兒是不需要的
新增一個index.fla檔, 並放在跟src資料夾下
在下方的工頁面版, 發怖設定
點選ActionScript version選單右方的 Settings按鈕
新增一組Classpatch路徑:./src

這樣當發怖的時候就會去抓src資料夾裡的類別。
同時把 Automatically declare stage instances的選項取消。

Step3:確認網站單元架構
因為for教學, 所以我們單純一點
點選選單, 會載入其他的swf。
同時會切換網站左上角display_mc裡的文字。
而外部的swf也只要製作二個, 分別為about.swf和link.swf。

Step4:撰寫IndexMain.as
因為我們把自動宣告場景上的實體選項取消了
所以場景上的實體名稱需要在類別裡宣告一次, 並設成public
但不需要建構。
public var display_mc   :MovieClip; //影格二,左上角的物件。
public var navigationContainer_mc:MovieClip; //影格二,右上角的主選單。
public var loading_txt   :TextField; //影格一的動態文字, 用來跑百分比。

偵聽主程式的載入資訊, 
public function IndexMain()  {  
this.stop();  
this.addEventListener(Event.ENTER_FRAME , _onLoaderInfoProcess);      
//偵聽主檔的載入資訊。
}  
private function _onLoaderInfoProcess(e:Event):void{
var _bl   :int = this.loaderInfo.bytesLoaded;
var _bt   :int = this.loaderInfo.bytesTotal;
var _percentage :int = Math.floor(_bl / _bt * 100);
if (_bl && _bt && _bl == _bt) {
this.removeEventListener(Event.ENTER_FRAME, _onLoaderInfoProcess);    
onLoaderInfoComplete();
//載入完成, 取消ENTER_FRAME事件, 並執行onLoaderInfoComplete函式。    
} else  {
loading_txt.text = _percentage + "%";
}
}  
載入完成會執行onLoaderInfoComplete函式。
private function onLoaderInfoComplete():void {
this.gotoAndStop(2);   
} 
Step5:建立選單元件的程式碼
milkmidi.demo.index.view.NavigationItem

效果很單純,
滑入時, 就播放over標籤
滑出時, 就播放out標籤
public class NavigationItem extends MovieClip {    
public function NavigationItem()  {   
stop();
this.addFrameScript(0 , stop);
this.addFrameScript(9 , stop);
//動態增加程式碼在指定的影格。
//第一格是0 ,二格是1。
this.buttonMode = true;
this.addEventListener(MouseEvent.ROLL_OVER , rollOverHandler);
this.addEventListener(MouseEvent.ROLL_OUT , rollOutHandler);
//偵聽
}    
private function rollOverHandler(e:MouseEvent):void {
this.gotoAndPlay("over");
}  
private function rollOutHandler(e:MouseEvent):void {
this.gotoAndPlay("out");
}
} 
Step6:建立選單元件容器的程式碼
milkmidi.demo.index.view.NavigationContainer
這裡面就放了二個NavigationItem元件。
用迴圈來偵聽click事件。
public class NavigationContainer extends Sprite{  
public var a0_mc :NavigationItem;
public var a1_mc :NavigationItem;
public function NavigationContainer()  {      
for (var i:int = 0; i < 2; i++) {
var _mc:NavigationItem = this.getChildByName("a" + i +"_mc") as NavigationItem;      
_mc.addEventListener(MouseEvent.CLICK , clickHandler);
}
}    
private function clickHandler(e:MouseEvent):void {
if (e.currentTarget == a0_mc) {    
//直覺式的寫式。
//按下後,呼叫root的loadSWF函式。
//同時叫root的display_mc.label_txt更改其文字。
MovieClip(root).loadSWF("flash/about.swf");
MovieClip(root).display_mc.label_txt.text = "ABOUT";
}else {
MovieClip(root).loadSWF("flash/link.swf");
MovieClip(root).display_mc.label_txt.text = "LINK";
}
} 
} 
Step7:回到IndexMain.as 補上二個函式。
public function loadSWF(pURL:String):void {
//public的函式, 用來給其他類別來呼叫。
_ldr.load(new URLRequest(pURL));
}   
private function loaderCompleteHandler(e:Event):void {
this.addChildAt(_ldr, 0);   
//Loader載入完成。
} 
Step8:新增一個about.fla,依照index.fla的設定 關掉自動宣告舞台實體的選項, 新增一個./src的class path milkmidi.demo.about.AboutMain 就只有偵聽一個EnterFrame事件。
import flash.display.MovieClip;
import flash.events.Event;

public class AboutMain extends MovieClip{  
public var content_mc:MovieClip;
public function AboutMain()  {   
this.addEventListener(Event.ENTER_FRAME , enterFrameHandler);
}  

private function enterFrameHandler(e:Event):void {

}
} 
另一個link.fla也是一樣的寫法 這樣就完成啦。 程式碼沒有做優化, 只是為了for教學。 來說明一下這樣寫的缺點: 1.什麼函式都寫在root, 這樣每次要呼叫的時候就要寫MovieClip(root); 2.物件沒有被封裝, 所以要更改其屬性, 就要寫成xxxx.xxx.xxx_txt.text。如果突然原件換了路徑或位置,就會....你懂的 3.好比切換單元, 第一個單元可能logo要大, 第二個單元可能logo要往右移之類的 這樣寫就要寫很多的if else if else,寫到客戶滿意為止。 下一篇再來分享進階篇。 SourceCodeDownload

留言

阿咩寫道…
奶老師教 AS 也是很直覺~~

很棒呢~
milkmidi寫道…
感謝啦
下一篇再來分享進階版
jerry寫道…
好酷哦~感謝您的分享,最近剛好在傷腦筋有關framework的事,剛好可以給參考^^
感謝
小白寫道…
謝謝奶綠
我喜歡看這種文章~
期待進階版喔!
Maaaaatt表示…
受教了奶老師,
檔案果然好整理很多,
但也遇到如老師提到的那些缺點問題...

期待進階版啦 :)

之前上課奶老師不是說要出書了嗎?
請問還要等多久呢 :P
milkmidi寫道…
謝謝支持
出版社預計是五月底會發行
有任何消息我會貼在我的blog上的
Focus1921寫道…
奶綠老師你好,如何使用UILoader載入外部圖片,載入失敗時使用內部元件庫的一張失敗預設圖來代替呢?以下是我嚐試寫的code:
(UILoader的實體名稱為uiLdr、自動載入、無預設source,要動態指定source)

uiLdr.source="test.jpg";
uiLdr.addEventListener(IOErrorEvent.IO_ERROR, onUiLdrErr);

function onUiLdrErr(e:IOErrorEvent):void {
uiLdr.source=ErrorPic;
/*help裡寫到source可以是外部圖片路徑,也可以是元件庫影片片段連結類別,所以我把預設錯誤圖片包成MovieClip後匯出給actionscript使用*/
}

以上的程式碼在找不到test.jpg後,還是會用元件庫的預設錯誤圖代替,但會發生「無法存取 Null 物件參考的屬性或方法」,但是trace uiLdr卻有[Object UILoader]的物件...真是很困擾,煩請老師替我解決這個鬼打牆的問題...
milkmidi寫道…
UILoader不能用Library的圖
只能外載
當判斷是載入失敗時
就再去載入你設定的預設圖片路徑就好了
Focus1921寫道…
謝謝奶綠老師,最後也是用這樣的方式來作的~
mel表示…
奶綠老師您好~
我用了你的方法試做了一下,場景上第一格是loading的文字框,第二格放一些movieClip元件,把自動宣告取消,並在indexMain.as宣告元件名稱...
但是匯出測試的時候,會出現"TypeError: Error #1009:無法存取 Null 物件參考的屬性或方法"...
可是這些movieClip如果放在場景的第一格,就不會有這樣的問題...
請問是為什麼呢?那我又該如何修正?需要再加上偵聽Event.ADDED_TO_STAGE嗎?
milkmidi寫道…
你是不是在.as檔就直接寫
xxx_mc.屬性或方法
但xxx_mc是第二個影格才出現的呢
因為xxx_mc還沒出現, 就去使用他的屬性或方法, 就會產生'無法存取null的屬性或方法'
決解辦法:
到了第二影格再呼叫xxx_mc
.as加寫
addFrameScript(1, addFrameScript1);
//在影格2(0是第1格)加入addFrameScript1這個函式
private function addFrameScript1():void{
xxx_mc.屬性。
}
這樣就可以了
mel表示…
多謝奶老師指點~已經可以了^^
匿名表示…
奶綠老師您好
初來貴寶地,
想與您請教Loading的問題

最近在做網頁
網站結構如下:
共有5個fla檔
1.loading+開頭動畫+四選單一個檔,名為"Menu.fla"
2.四個單元分別為"a.swf","b.swf","c.swf","d.swf",

轉換單元部份
我是在Menu.fla裏面用gotoAndStop("a")//跳至該影格標籤
影格標籤a,code如下:
var a : Loader=new Loader();
var url_1:String="a.swf";
var urlReq1:URLRequest=new URLRequest(url_1);
a.load(urlReq1);
addChild(a);

影格標籤b,code如下:
gotoAndStop("b")
var b : Loader=new Loader();
var url_2:String="b.swf";
var urlReq2:URLRequest=new URLRequest(url_2);
b.load(urlReq2);
addChild(b);//請依此類推

問1.請問是否有辦法設定載入的swf深度?
因為swf載入以後為最top的層級了(選單被swf遮住了)

問2.主選單的檔裡有四個影格,皆有不同的Loader
切換多次單元後發現很占系統資源(速度變慢)
是否要onload()?(如何判斷目前已經載入的swf將之onload?

問3.因為每個swf檔有點大,怕載入耗時,所以分開載入
讓5個fla都有各自的loading,
請問有沒有更好的結構建議呢?

問4.請問名為"a.swf"裏面的btn如何訪問Menu.fla裏面的影格或mc呢?
用MovieClip(parent)也不對,
找過幾種方法都不行,
所以上來請教老師

感激不盡
milkmidi寫道…
問1.請問是否有辦法設定載入的swf深度?
因為swf載入以後為最top的層級了(選單被swf遮住了)
答1.試試用 addChildAt(b,0); 這樣就是把 b 加到最下方。


問2.主選單的檔裡有四個影格,皆有不同的Loader
切換多次單元後發現很占系統資源(速度變慢)
是否要onload()?(如何判斷目前已經載入的swf將之onload?

答2.看起來你用了很多的 Loader , 理想應該是只要用一個 Loader 來載入比較好
這樣入了新的,舊的就會被蓋掉

問3.因為每個swf檔有點大,怕載入耗時,所以分開載入
讓5個fla都有各自的loading,
請問有沒有更好的結構建議呢?

答3.Loading應該寫在主網站,被載入的就不需要寫。

問4.請問名為"a.swf"裏面的btn如何訪問Menu.fla裏面的影格或mc呢?
答4.你可以試試打氣泡事件給最上層物件來偵聽
阿政表示…
我會好好認真思考老師您的回覆
並且嘗試您的方法

謝謝奶綠茶老師的指導
小弟受益良多
匿名表示…
謝謝奶綠大的教學~十分受教~
學習了很多觀念~感謝!!!
下雨的妍寫道…
我套用了一下~ 怎麼出現『1180:呼叫可能未定義的方法 addFrameScript』
而且為什麼我在『navigationContainer_mc』按鈕影片片段內做一段動畫想設stop停下來會出現錯誤…
還是有需要傳檔案請您幫我看一下~?
milkmidi寫道…
是因為你 extends Sprite?嗎
下雨的妍寫道…
我把底下的else刪掉~才出現,因為沒刪除他出現未預期的else。
下雨的妍寫道…
https://sites.google.com/site/54wewe/FLASH.rar?attredirects=0&d=1
不好意思~ 我看了一下您有一篇『優化你的flash, Part2』其中有人說到,有問題要看FLASH才知道,一個檔案勝過千言萬語。
上面是我製作的,請您看一下。
milkmidi寫道…
因為你在該元件最後影格加了
stop();

把 NavigationContainer extends MovieClip 就可以了
下雨的妍寫道…
您好~ 現在stop沒出現錯誤了~ 但如果我是三個以上的按鈕該怎麼增加和修改?
還有如果我需要點下後將剛剛點下的按鈕停在滑入的畫面要怎麼做呢?
下雨的妍寫道…
對不起~ 我又有問題了~
我將底下改成
if (e.currentTarget == a0_mc)
{
//直覺式的寫式。
//按下後,呼叫root的loadSWF函式。
//同時叫root的display_mc.label_txt更改其文字。
MovieClip(root).loadSWF("flash/news.swf");
MovieClip(root).display_mc.label_txt.text = "最新活動";
}
if (e.currentTarget == a1_mc){}
else
{
MovieClip(root).loadSWF("flash/play.swf");
MovieClip(root).display_mc.label_txt.text = "桌上遊戲";
}
if (e.currentTarget == a2_mc){}
else
{
MovieClip(root).loadSWF("flash/gourmet.swf");
MovieClip(root).display_mc.label_txt.text = "美食響宴";
}
他出現『NavigationContainer extends MovieClip』這段有錯誤~
對不起我剛碰as3,對一切都非常不熟,是不是我內部的影片動作的概念也錯了~ 不能用stop來停止動作?
匿名表示…
奶綠老師您好:
我是使用Flash Builder 4.5 for Mobile Project.

假如我有兩個mxml,就稱他們為A.mxml和B.mxml

現在A.mxml裡面有function要呼叫B.mxml裡面的function,目前我是可以呼叫到這個function, 不過因為B.mxml裡面有一些元件,例如button,label...等等,當我在呼叫B的function時需要改變這些元件的狀態,例如內容,顏色,也可能在這個function去呼叫B的其他function,不過我現在一直遇到同一個error,
"TypeError: Error #1009:無法存取 Null 物件參考的屬性或方法",錯誤就是在B.mxml中被呼叫的function裡面的元件或是其他function.

找了很多文章還是無法解決,所以上來請教奶綠老師!!
milkmidi寫道…
那段錯誤指的是你呼叫了一個 null 的物件
一個一個 trace, 看那個物件沒有被建構
匿名表示…
我知道是哪個物件沒有被建起來,不過我想問奶綠老師的是怎麼讓B.mxml被呼叫的同時就把這些物建起來?
匿名表示…
奶綠茶老師可以幫我解決上面那個問題嗎?? 找了好多文章還是不清楚如何解決....@@

這個網誌中的熱門文章

webpack2 入門實戰 1

大家好,我是奶綠茶
前端戰場不再只是寫寫 js / css , 各種框架、前處理工具百花齊放
身為前端工程師,不只要把程式寫完,還要寫好
老師說:選對好工具,事情就完成一半
如果你還在一隻 JS 打完全部程式,一隻 css 寫所有的 style
每次存檔還在手動 reload 網頁, 圖片壓 K 壓到不要不要的
透過奶綠伯的系列教學,讓你了解 webpack2 帶來的優勢
學會 webpack 可能不會加薪,但至少可以準時下班(誤)
1. 安裝 nodejs
請參考 gulp 安裝編

2. 安裝 global webpack , 筆者使用的是 2.2.1 版本
npm i webpack@2.2.1 -g
3. 在專案的根目錄放一隻 webpack.config.js
entry:你的主 js 進入點
output.filename:webpack 打包後的檔名
output.path:webpack 打包後的路徑
var path = require('path'); module.exports = { entry: './src/app.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
4. require , module.exports
現在前端都 module 化
可以每個獨立的功能都寫成單一的 js module
除了好管理,也方便讓團隊使用
寫一隻 module_exports_util.js
每隻經過 webpack 打包的 js , 都會是獨立的檔案
所以變數都是私有的, 外部成員都無法得到
在這個 module 裡,我們想開放二個函式
add , getName
所以在最後的 module.exports 指定
筆記加入 jsdoc , 為了方便在開發時,能夠有型別的提示

var name = "milkmidi"; /** * @param {number} num1 * @param {number} num2 * @return {number} */ function ad…

webpack2 入門實戰 3 scss,html,file-loader

大家好,我是奶綠茶
上一篇介紹了 webpack 的核心功能 loader
這篇再來補強各種常用的 loader
css-loader:解悉 css 檔
extract-loader:這個有點難翻,下面會介紹
file-loader:存成實體的檔案, 如圖片
html-loader:解悉 html 檔
sass-loader:解悉 scss 檔
url-loader:解悉圖片路徑
webpack.config.js
module.exports = { resolveLoader: { // 所有用到的 loader, -loader 可以不用打 moduleExtensions: [ "-loader" ], }, resolve: { // 在 require 檔案, 如果不想寫完整的路徑 // 可以加入這些目錄, 讓 webpack 自動尋找對的檔案 // 請注意我們加入了 src/img 路徑,後面會再介紹到 modules: [ path.resolve( 'src/html' ), path.resolve( 'src/img' ), path.resolve( 'src/css' ), path.resolve( 'src/js' ), path.resolve( "node_modules"), ], // 在 require 時可以不用打副檔名 extensions: [ ".js", ".scss" ] }, } 再來就是 loader 的介紹
scss
在這要做多組合的應用
先將 .scss 透過 scss-loader 轉換, 並產生 sourceMap 檔
再過 css-loader
最後再過 style-loader
{ test: /\.scss$/, // 多個 loader 組合, 可寫成一行,或…

Android完全入門篇-01 安裝SDK與裝置USBDriver

大家好,我是奶綠茶
筆者以 Windows 系統來介紹安裝
1. 下載 Android SDK
http://developer.android.com/sdk/index.html
有分 32 位元和 64 位元的版本
為了教學方便,筆者將檔案放置在 D:\ 下
壓開後會有
eclipse資料夾:Eclipse程式碼編譯器
sdk:Android 開發用的 SDK
SDK Manager.exe:sdk管理用的軟體


2. 開啟手機的"開發人員選項"
部份手機該選項被隱藏起來了
要開啟的話,點選"關於手機"
接著連點"版本號碼"七次,就會重新開啟該功能
接著再開啟"USB偵錯"功能
接上你的 USB 線後
這樣你的電腦才能透過 USB 線來偵錯手機的資訊
3. 為裝置安裝 adb usb driver
因為各家廠牌的 Driver 都不同也不通用,所以需要自行 Google 找 Driver
可以用"XXX廠牌 型號 adb usb driver"關鍵字來找
例:HTC Newone adb usb driver
接著找到 我的電腦 / 內容


裝置管理員

會看到一個金嘆號未知的裝置, 按右鍵更新驅動程式軟體

選擇"瀏覽電腦上的驅動程式軟體"

完成後就會看到裝置啟動,並出現 XXX Android ADB Interface

4.測試是否連接成功
進入到第一步下載的 sdk 資料夾裡
D:\adt-bundle-windows-x86_64-20131030\sdk
然後在 platform-tools 資料夾上按住 Shift 鍵,然後再按滑鼠右鍵
選擇"在此處開啟命令視窗"
(此功能只有 Win7 之後的版本才支援, XP使用者就要自行輸入 dos 指令進入到資料夾)
輸入 adb devices
如果看到一串數字,並顯示 device 就表示連線成功
5.新增環境變數(選擇性設定)
為了方便的使用 adb 指令
可以為 windows 設定變數
開啟我的電腦 / 內容 / 左邊的"進階系統設定"
點選下方 環境變數

下方系統變數,找到 Path的選項,按下編輯

在變數值欄位的最後方加入
;D:\adt-b…