數據存儲
TM的作品,通常將數據都擺放在一個XML文件內,而不同作品中的這個文件的內容基本上都遵從著同一個格式:
<?xml version="1.0" encoding="iso-8859-1"?>
<content>
<!-- general vars -->
<section name="settings">
<item name="textSelectable">true</item>
<item name="copyright"><![CDATA[]]></item>
<item name="companyName"><![CDATA[]]></item>
<item name="slogan"><![CDATA[]]></item>
</section>
<!-- menu -->
<section name="menu">
<link systemOrder="1"><![CDATA[About IDS]]></link>
<link systemOrder="2"><![CDATA[Solution]]></link>
</section>
<!-- pages -->
<section name="pages">
<page name="about ids">
<image imageUrl="_pic01.png" link="http://www.yourcompany.com"/>
<image imageUrl="_pic02.png"/>
<texts>
<pageText><![CDATA[<b>A Few Words About IDS</b>]]></pageText>
</texts>
<link linkType="readMoreLink">
<item name="title"><![CDATA[Read More 1]]></item>
</link>
</page>
<page name="markets">
<texts>
<pageText><![CDATA[
<b> What you can get with it?</b>
]]></pageText>
</texts>
</page>
<page name="partners">
<texts>
<pageText><![CDATA[<b>Affiliate Program</b>]]></pageText>
</texts>
</page>
<page name="contacts">
<texts>
<pageText><![CDATA[<b>Contact Information</b>]]></pageText>
</texts>
</page>
</section>
<!-- privacy policy -->
<section name="privacyPolicy">
<item name="pageTitle"><![CDATA[Privacy Policy]]></item>
</section>
<!-- privacy policy -->
<!-- terms of use -->
<section name="termsOfUse">
<item name="pageTitle"><![CDATA[TERMS OF USE</font>]]></item>
<item name="pageText"><![CDATA[]]></item>
</section>
<!-- terms of use -->
</content>
首先,根節點下的子節點必然是section節點,section節點的個數可能會因項目不同而不同,但下面幾個是必然有的:settings,menu,pages,privacyPolicy,termsOfUse。另外也可能會有:configuration,global_text,global_img,contactForm等等。
Section Menu,這個節點的子節點通常是五個link節點,一般來說TM的Flash都是有五個頁面,分別對應。
Section Pages,這個節點的子節點是page,page內的節點則可能根據情況不同而異,但通常都一定會出現texts節點,而texts節點的子節點是一些pageText節點。
page節點通常是五個,與菜單個數一樣,這五個的名字通常是:home,about,portfolio,services,contact;當然也不儘然,也可能會有其他名,但是名字不重要。
contact是必然會有的page。
多數情況下,葉節點的節點名都是item。比如settings下面的節點。
數據訪問函數
首先看看在action層上面的第一幀的as代碼:
function onFinish(success_boolean, results_obj, xml)
{
if (success_boolean)
{
play ();
} // end if
} // End of the function
Stage.align = "MC";
Stage.scaleMode = "noScale";
url = "27019";
_root.linkGallery = 0;
_root.titleGallery = 0;
_root.cacheKiller = "true";
stop ();
var parsed_obj = {};
var unCash = new Date().getTime();
if (_root.cacheKiller == "true")
{
fileToLoad = url + "_main.xml?cacheKiller=" + unCash;
fileToLoad = url + "_main.xml";
}
else
{
fileToLoad = url + "_main.xml";
} // end else if
gs.dataTransfer.XMLParser.load(fileToLoad, onFinish, parsed_obj);
_root.emp.useHandCursor = 0;
_root.mus = 1;
_root.n = 1;
_root.num = 1;
上面這段代碼是從反編譯的文件中拷貝出來的,其實它跟原版的.fla上的代碼除了順序上略微有不同之外,幾乎沒有大的出入。這裡面有一個被引入的類,就是:
gs.dataTransfer.XMLParser
簡單來講,這個類的作用是加載XML文件,並且將這個XML文件的內容分析然後轉換成一個多維數組。轉換的規則大致是:將節點轉換成一個對象,其屬性轉換成對象的屬性,如果同名的節點超過一個,那麼就把轉換后的對象放在一個索引數組里面,把這個數組作為其父節點的一個屬性。這個最終被轉換好的數組就是parsed_obj,在所有的TM的Flash里都是如此。
而在原版里,這個XMLParser類是通過import加載的,注意:TM的Flash都是基於Actionscript2.0的。
下面來看看第二幀上面的as代碼,在反編譯的版本里,比較長,裏面有很多獲取數據的函數,事實上,原版的做法是,將這些數據訪問的全局函數寫在了一個獨立的as文件內:xmlFunctions.as,然後通過#include "path_of_script"指令導入,它通常也被放在路徑gs\dataTransfer\下,和XMLParser一樣。
xmlFunctions.as中的函數大多都是工作在parsed_obj之上的,現在來看看具體做些什麽。
首先,是這個最為基本的函數:
function getXmlSection (obj, itemName, sectionName)
{
i=0;
while (obj[itemName][i])
{
if (obj[itemName][i].name==sectionName)
{
returnedResult=true;
return (i);
break;
}
i++;
}
}
表面看起來,它所做的事情是,尋找一個屬性名為itemName的數組裏面,name屬性為sectionName的元素,並將它的索引值返回。這個函數的設計使其有一定的靈活性,然而在TM的所有Flash中,它所接收的obj必然是上面提到的parsed_obj,即從XML得到的數據,而itemName的值必然是"section",所以它扮演的實際作用就是尋找名稱為sectionName(比如“settings”)的元素,返回其索引值。
依賴於getXmlSection()的函數有:
// settings functions
function getSettingsValue (obj, itemName, itemType)
{
sectionNum=getXmlSection(obj, "section", "settings");
k=0;
while (obj["section"][sectionNum][itemType][k])
{
if (obj["section"][sectionNum][itemType][k].name==itemName)
{
return (obj.section[sectionNum][itemType][k].value);
break;
}
k++;
}
}
// menu functions
function getMenuLink (textObj, linkNum)
{
sectionNum=getXmlSection(mainObj, "section", "menu");
textObj.htmlText=mainObj["section"][sectionNum].link[linkNum].value;
textSelectable(textObj);
}
function getMenuSystemOrder (linkNum)
{
sectionNum=getXmlSection(mainObj, "section", "menu");
return (mainObj["section"][sectionNum].link[linkNum].systemOrder);
}
// contact form functions
function getContactFormText(textObj, textNumber)
{
sectionNum=getXmlSection(mainObj, "section", "contactForm");
textObj.htmlText=mainObj["section"][sectionNum]["texts"][0]["pageText"][textNumber].value;
textSelectable(textObj);
}
function getContactFormText_only(textNumber)
{
sectionNum=getXmlSection(mainObj, "section", "contactForm");
return htmlText=mainObj["section"][sectionNum]["texts"][0]["pageText"][textNumber].value;
}
function getContactFormParams() {
sectionNum=getXmlSection(mainObj, "section", "contactForm");
ContactFormParams=new Array();
servNum=getXmlSection(mainObj["section"][sectionNum], "item", "serverOption");
recNum=getXmlSection(mainObj["section"][sectionNum], "item", "recipient");
ContactFormParams['rec']=mainObj["section"][sectionNum]["item"][recNum].value;
ContactFormParams['serv']=mainObj["section"][sectionNum]["item"][servNum].value
return (ContactFormParams);
}
// gallery functions
function getGallerySystemProperty(propName)
{
sectionNum=getXmlSection(galleryObj, "section", "systemOptions");
propNum=getXmlSection(galleryObj["section"][sectionNum], "option", propName);
return (galleryObj["section"][sectionNum]["option"][propNum].value);
}
function getGallerySettings(propName)
{
sectionNum=getXmlSection(galleryObj, "section", "settings");
propNum=getXmlSection(galleryObj["section"][sectionNum], "option", propName);
return (galleryObj["section"][sectionNum]["option"][propNum].value);
}
function getGalleryImage(imageNum, categoryNum)
{
sectionNum=getXmlSection(galleryObj, "section", "imagesData");
imageParams=new Array();
image=galleryObj["section"][sectionNum]["category"][categoryNum]["image"][imageNum];
nameNum=getXmlSection(image, "item", "imageUrl");
commentNum=getXmlSection(image, "item", "imageComment");
imageParams['name']=image['item'][nameNum].value;
imageParams['comment']=image['item'][commentNum].value;
return (imageParams);
}
function getCurrentGalleryName(categoryNum)
{
sectionNum=getXmlSection(galleryObj, "section", "imagesData");
return (galleryObj["section"][sectionNum]["category"][categoryNum].name);
}
function getCurrentText(textObj, textNumber)
{
sectionNum=getXmlSection(mainObj, "section", "pages");
currentPage=_root.link-_root.firstPageFrame;
textObj.htmlText=mainObj["section"][sectionNum]["page"][currentPage]["texts"][0]["pageText"][textNumber].value;
textSelectable(textObj);
}
function getCurrentImageName(imageNumber)
{
sectionNum=getXmlSection(mainObj, "section", "pages");
currentPage=_root.link-_root.firstPageFrame;
imageParams=new Array();
imageParams['name']=mainObj["section"][sectionNum]["page"][currentPage]["image"][imageNumber]["imageUrl"];
imageParams['linkToOpen']=mainObj["section"][sectionNum]["page"][currentPage]["image"][imageNumber]["link"];
imageParams['target']=mainObj["section"][sectionNum]["page"][currentPage]["image"][imageNumber]["target"];
return (imageParams);
}
function getCurrentImageName_splash(imageNumber)
{
sectionNum=getXmlSection(mainObj, "section", "settings");
imageParams=new Array();
imageParams['name']=mainObj["section"][sectionNum]["image"][imageNumber]["imageUrl"];
imageParams['linkToOpen']=mainObj["section"][sectionNum]["image"][imageNumber]["link"];
return (imageParams);
}
實際上這部份函數會因為項目數據的不同而有所差異,有時會另外增加一些函數。比如這個文件中:
function getGlobalText(textObj, textsNumber, optional:Boolean, fontCorlor:String)
{
sectionNum = getXmlSection(mainObj, "section", "global_text");
if (fontCorlor){
textObj.htmlText = '<font color="'+fontCorlor+'">'+mainObj["section"][sectionNum].texts[textsNumber].value+'</font>';;
}else{
textObj.htmlText = mainObj["section"][sectionNum].texts[textsNumber].value;
}
if (optional == undefined) {
textSelectable(textObj);
} else {
// do nothing
}
}
function getGlobalImageName(imageNumber) {
sectionNum = getXmlSection(mainObj, "section", "global_img");
//currentPage = _root.link-_root.firstPageFrame;
imageParams = new Array();
imageParams['name'] = mainObj["section"][sectionNum]["image"][imageNumber]["imageUrl"];
imageParams['linkToOpen'] = mainObj["section"][sectionNum]["image"][imageNumber]["link"];
return (imageParams);
}
這些函數通常將將要訪問的section的name預定,通過getXmlSection函數得到該section的索引,然後在通過while循環根據指定的item的name得到它的值。差不多都是這樣工作的。
下面的函數則是依賴於getSettingsValue:
function textSelectable(selectedObject)
{
isTextSelected=getSettingsValue(mainObj, "textSelectable", "item");
if (isTextSelected=="true")
{
selectedObject.selectable=true;
}
}
function getCopyright (textObj) {
textObj.htmlText=getSettingsValue(mainObj, "copyright", "item");
textSelectable(textObj);
}
function getCompanyName (textObj) {
textObj.htmlText=getSettingsValue(mainObj, "companyName", "item");
textSelectable(textObj);
}
function getSlogan (textObj) {
textObj.htmlText=getSettingsValue(mainObj, "slogan", "item");
textSelectable(textObj);
}
function getSystemValue (textObj, systemOptionName) {
textObj.htmlText=getSettingsValue(mainObj, systemOptionName, "item");
textSelectable(textObj);
}
這一系列函數做的事情是獲取settings的section中的值,然後將其賦值給傳入的TextField控件(文本控件)的內容,第一個函數有些不同,它除了得到值,還會根據這個值設定文本控件的可選屬性,後面的函數也用到它。
一個實際使用中的函數鏈:
_root.getSystemValue(thisText,"companyName");
function getSystemValue (textObj, systemOptionName) {
textObj.htmlText=getSettingsValue(mainObj, systemOptionName, "item");
textSelectable(textObj);
}
function getSettingsValue (obj, itemName, itemType)
{
sectionNum=getXmlSection(obj, "section", "settings");
k=0;
while (obj["section"][sectionNum][itemType][k])
{
if (obj["section"][sectionNum][itemType][k].name==itemName)
{
return (obj.section[sectionNum][itemType][k].value);
break;
}
k++;
}
}
function getXmlSection (obj, itemName, sectionName)
{
i=0;
while (obj[itemName][i])
{
if (obj[itemName][i].name==sectionName)
{
returnedResult=true;
return (i);
break;
}
i++;
}
}
function checkLinkType (linkTextType, linkNumber)
{
k=0;
typeCount=0;
finalLinkNumber=parseInt(linkNumber)+1;
currentPage=_root.link-_root.firstPageFrame;
sectionNum=getXmlSection(mainObj, "section", "pages");
linkTypeCkeck=mainObj["section"][sectionNum]["page"][currentPage]["link"][k]["linkType"];
while (linkTypeCkeck)
{
if (linkTypeCkeck==linkTextType)
{
typeCount++;
}
if (typeCount==finalLinkNumber)
{
return(k);
break;
}
k++;
linkTypeCkeck=mainObj["section"][sectionNum]["page"][currentPage]["link"][k]["linkType"];
}
}
function more_click_func(number)
{
_root.output();
tempNumber = number.split(" ");
number=tempNumber.join("");
number=number.toLowerCase();
num=_root.pagesReadMoreFrame;
currentPage=_root.link-_root.firstPageFrame;
if( isNaN(Number(number)) )
{
readMoreType = number;
}
else
{
readMoreType = 'readmore';
}
if( (_root.link<>num || _root.readMoreFrameType!=readMoreType) and _root.animation==1)
{
_root.animation=0;
if(_root.link<>_root.pagesReadMoreFrame)
{
_root.link_prev=_root.link;
}
if (_root.link<>_root.pagesReadMoreFrame && _root.SP<>1)
{
_root.menu_mov["item" + getMenuPreviousLink(_root.link)].gotoAndPlay("s2");
}
if (number=='privacypolicy')
{
_root.readMoreFrameType = 'privacypolicy';
sectionNum=getXmlSection(mainObj, "section", "privacyPolicy");
titleNum=getXmlSection(mainObj.section[sectionNum], "item", "pageTitle");
textNum=getXmlSection(mainObj.section[sectionNum], "item", "pageText");
_root.readMoreTitle=mainObj.section[sectionNum]["item"][titleNum].value;
_root.readMoreText=mainObj.section[sectionNum]["item"][textNum].value;
}
else if (number=='termsofuse')
{
_root.readMoreFrameType = 'termsofuse';
sectionNum=getXmlSection(mainObj, "section", "termsOfUse");
titleNum=getXmlSection(mainObj.section[sectionNum], "item", "pageTitle");
textNum=getXmlSection(mainObj.section[sectionNum], "item", "pageText");
_root.readMoreTitle=mainObj.section[sectionNum]["item"][titleNum].value;
_root.readMoreText=mainObj.section[sectionNum]["item"][textNum].value;
}
else
{
_root.readMoreFrameType = 'readmore';
sectionNum=getXmlSection(mainObj, "section", "pages");
linkCount=checkLinkType("readMoreLink", number);
i=0;
linkTitleNum=getXmlSection(mainObj["section"][sectionNum]["page"][currentPage]["link"][linkCount], "item", "title");
linkTextNum=getXmlSection(mainObj["section"][sectionNum]["page"][currentPage]["link"][linkCount], "item", "linkText");
_root.readMoreTitle=mainObj["section"][sectionNum]["page"][currentPage]["link"][linkCount]["item"][linkTitleNum].value;
_root.readMoreText=mainObj["section"][sectionNum]["page"][currentPage]["link"][linkCount]["item"][linkTextNum].value;
}
_root.link=num;
if (_root.SP == 0)
{
//_root.ch_cont.ch_pages.gotoAndPlay("s1");
_root.ch_cont.gotoAndPlay("s2");
}
if (_root.SP == 1)
{
//_root.ch_cont.ch_pages.gotoAndPlay("s1");
_root.ch_cont.gotoAndPlay("s1");
_root.menu_mov.item0.cont.gotoAndPlay("s2");
//_root.SP = 0;
}
}
}
function loadBitmapSmoothed(url:String, target:MovieClip) {
// Create a movie clip which will contain our
// unsmoothed bitmap
var bmc:MovieClip = target.createEmptyMovieClip("bmc", target.getNextHighestDepth());
// Create a listener which will notify us when
// the bitmap loaded successfully
var listener:Object = new Object();
// Track the target
listener.tmc = target;
// If the bitmap loaded successfully we redraw the
// movie into a BitmapData object and then attach
// that BitmapData to the target movie clip with
// the smoothing flag turned on.
listener.onLoadInit = function(mc:MovieClip) {
mc._visible = false;
var bitmap:BitmapData = new BitmapData(mc._width, mc._height, true);
this.tmc.attachBitmap(bitmap, this.tmc.getNextHighestDepth(), "auto", true);
bitmap.draw(mc);
};
// Do it, load the bitmap now
var loader:MovieClipLoader = new MovieClipLoader();
loader.addListener(listener);
loader.loadClip(url, bmc);
}
loadBitmapSmoothed()是一個獨立工作的函數,它所做的事情就是先在傳入的MC——姑且稱為目標MC——上創建一個空的臨時MC,然後加載傳入的url指定的圖片到這個臨時MC,在加載完畢后,創建一個Bitmap,將臨時MC的內容繪製到Bitmap上,在繪製中指定smooth標誌為true,然後再將這個Bitmap加入到目標MC中。這樣就做到了smooth地加載圖片。在使用這個函數的地方,都會根據XML中的設定來判斷是否要通過這個函數來加載圖片。