2009年8月23日星期日
IE6 Upgrade Notice

ie6trash.jpg

有過網頁設計經驗的人,無論是部落格樣版或是其他頁面,都一定有個共同的痛,就是IE6這傢伙對CSS的呈現總是跟別人不同,偏偏它的市占率一直是最高的。

通常解決這個問題的方法有兩種,一種是修改CSS直到版面看起來正常,另一種則是直接放棄,在網頁開頭就提醒使用者升級瀏覽器。

我們今天要介紹的就是最後一種方法,為什麼我們要放棄IE6呢?

因為網頁技術不斷的進步,不單單是CSS的問題,IE6本身還有其他原因,它已經不適合這個世代了,加上最近許多知名網站也紛紛開始提倡升級IE6,例如You Tube、Twitter和Facebook等,IE6你真的玩完了,拜託還在使用IE6的人,請你快點更換瀏覽器吧!!(小聲:換Firefox吧)

youtubeie6

知名影音分享網站YouTube將停止對IE6的支援。

facebookie6 

連最近在台灣火熱的Facebook都要封殺IE6了,還在使用它的人,麻煩你快點更新吧!!!

剛好之前看到一篇重灌狂人寫的文章 "在網站加入警告標語,建議IE 6.0的使用者升級",裡面介紹了一些IE瀏覽器版本判斷的語法,可以分辨出使用者目前的IE瀏覽器是哪一個版本。

例如我要讓IE6以下的使用者看見提示的話:

   1: <!--[if lte IE 6]>
   2: 這裡的內容只有IE6以下的使用者才看的見。
   3: <![endif]-->
 
只要將提示內容放在<!--[if lte IE 6]><![endif]-->之中,就可以讓還在用IE6的人,看到你要傳達給他的訊息了。
 
語法說明:
 
   1: <!--[if IE]>
   2: 使用IE瀏覽器全部版本的人都看得見這裡的內容。
   3: <![endif]-->
 
   1: <!--[if IE 6]>
   2: 只有IE6的使用者才能看見這裡的內容
   3: <![endif]-->
 
   1: <!--[if lt IE 6]>
   2: 這裡是小於IE6的版本使用者才能看到,不含IE6。
   3: <![endif]-->
 
   1: <!--[if lte IE 6]>
   2: IE6以下版本的使用者能看見內容,包含IE6。
   3: <![endif]-->
 
   1: <!--[if gt IE 6]>
   2: 這樣IE6以上版本的使用者會看見內容,但不包含IE6。
   3: <![endif]--> 
 
   1: <!--[if gte IE 6]>
   2: IE6以上版本的使用者能看見內容,包含IE6。
   3: <![endif]-->

上面的版本編號也可以換,如果把[if lte IE 6]換成[if lte IE 7]的話,就是IE7以下使用者能看見內容。

  • gt:greater than (版本大於)
  • lt:less than (版本小於)
  • gte:greater than or equal (版本大於等於)
  • lte:less than or equal (版本小於等於)

最後分享一個自己寫的範本,加了jquery的sideup效果,有興趣的可以下載回去參考看看。

ie6notice

演示範例:

範本下載:

參考資料:

2009年8月20日星期四
Factory pattern 工廠模式

距離上一篇 Strategy pattern 策略模式已經兩個多月了,一直拖到現在才生出這篇文章...orz。
其實這篇工廠模式應該要當作第一篇 Design pattern 的文章會比較好,因為這個模式很容易懂,但是工廠模式中又細分出一些其他類似的模式,例如抽象工廠模式,所以我把一些相關的資料都讀了一遍後,分三篇作介紹。

工廠模式最主要的精神就是將 new Class 這個動作另外封裝成一個 Factory Class,這個Factory Class 專門負責實體化這些類別。

特地這樣做有什麼好處呢?

舉個例子,假如我們現在有兩個繼承 Product 的類別,它們擁有共同的方法 Operation(),如下圖:

SimpleFactoryPattern_01

一般來講,我們如果要實體化 ProductA 或 ProductB 的話,會這樣寫:

   1: namespace FactoryPattern
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             Product product = new ProductA();
   8:  
   9:             product.Operation();
  10:         }
  11:     }
  12: }

這樣做有什麼缺點呢?

如果我 product 型別要換成 ProductB 的話,就需要把第7行的 new ProductA() 改成 new ProductB(),若是繼承 Product 的類別一多,以後程式碼的維護上會很麻煩。

簡單工廠模式 Simple Factory Pattern (又稱靜態工廠模式 Static Factory Pattern):

SimpleFactoryPattern

按照上圖,將擁有共同介面類別的實體化動作封裝在 Factory 內,程式就可以在執行時動態決定要實體化哪個類別了。

Factory class:

   1: namespace SimpleFactoryPattern
   2: {
   3:     public class Factory
   4:     {
   5:         public Product CreateProduct(string name)
   6:         {
   7:             switch (name)
   8:             {
   9:                 case "ProductA":
  10:                     return new ProductA();
  11:                 case "ProductB":
  12:                     return new ProductB();
  13:                 default:
  14:                     return null;
  15:             }
  16:         }
  17:     }
  18: }

Client:

   1: using System;
   2:  
   3: namespace SimpleFactoryPattern
   4: {
   5:     class Program
   6:     {
   7:         static void Main(string[] args)
   8:         {
   9:             // productName可以動態決定要實體化的類別
  10:             string productName = "ProductA";
  11:         
  12:             Factory productFactory = new Factory();
  13:         
  14:             Product product = productFactory.CreateProduct(productName);
  15:  
  16:             product.Operation();
  17:         }
  18:     }
  19: }

到這裡可以看看使用 Factory 後,和使用之前的程式碼做比較,最大的差別就是現在可以靠變數來決定要實體化的類別了,若是需要改成 ProductB 的話,只需要將 productName 的值改成 "ProductB" 就行了。

如果覺得上面的 Factory productFactory = new Factory(); 這行有點礙眼的話,還可以將程式碼更簡單話一點,就是把 Factory class 的 CreateProduct() 方法改成 static:

   1: public static Product CreateProduct(string name)

這樣就可以直接跳過 new Factory() 的步驟,直接呼叫 CreateProduct() 方法:

   1: static void Main(string[] args)
   2: {
   3:      string productName = "ProductA";
   4:                 
   5:      Product product = Factory.CreateProduct(productName);
   6:  
   7:      product.Operation();
   8: }

使用簡單工廠模式雖然方便,但也是有缺點的。

如果每次新增一個 Product 子類別後,都必須修改 Factory class 中 CreateProduct() 的 switch 判斷式的話,這樣做不符合物件導向設計的 Open-Closeed Principle(開放-封閉原則) 精神。

什麼是開放-封閉原則呢?

簡單說就是程式容易擴充新功能,但是不用修改原始碼的意思。

如果因為要擴充 ProductC class 進來,而修改了 Factory class 的話,這樣的做法並不是很好,所以比較正統的工廠模式有另一種寫法,就是接著下一篇要介紹的工廠方法模式

工廠方法模式 Factory Method Pattern:

FactoryMethodPattern_thumb24

要解決簡單工廠模式的問題,工廠方法模式的做法是將 Factory 類別抽象化,讓每個 Product 子類別都有屬於自己的工廠類別,如上圖所示。

Factory interface:

   1: namespace FactoryMethodPattern
   2: {
   3:     public interface Factory
   4:     {
   5:         Product CreateProduct();
   6:     }
   7: }

ProductFactoryA class:

   1: namespace FactoryMethodPattern
   2: {
   3:     public class ProductFactoryA : Factory
   4:     {
   5:         public Product CreateProduct()
   6:         {
   7:             return new ProductA();
   8:         }
   9:     }
  10: }

ProductFactoryB class:

   1: namespace FactoryMethodPattern
   2: {
   3:     public class ProductFactoryB : Factory
   4:     {
   5:         public Product CreateProduct()
   6:         {
   7:             return new ProductB();
   8:         }
   9:     }
  10: }

Client:

   1: using System;
   2:  
   3: namespace FactoryMethodPattern
   4: {
   5:     class Program
   6:     {
   7:         static void Main(string[] args)
   8:         {
   9:             // ProductA
  10:             Factory productFactoryA = new ProductFactoryA();
  11:             Product productA = productFactoryA.CreateProduct();
  12:             productA.Operation();            
  13:             
  14:             // ProductB
  15:             Factory productFactoryB = new ProductFactoryB();
  16:             Product productB = productFactoryB.CreateProduct();            
  17:             productB.Operation();
  18:         }
  19:     }
  20: }

這樣就解決簡單工廠的擴充問題了,如果需要增加 ProductC 的話,只需要加入 繼承 Product 的ProductC class繼承 Factory 的 ProductFactoryC class 就可以了,不需要動到其他程式碼。

抽象工廠模式 Abstract Factory Pattern:

AbstractFactoryPattern_thumb54

最後要介紹的是抽象工廠模式,這個模式其實跟上面的工廠方法是差不多的,只是增加了第二組Product的概念,我們來看看它的定義:

抽象工廠模式,提供一個建立一系列相關物件的介面,而無需指定它們具體的類別。

從上圖來看,我們有兩組產品,Product1 和 Product2,可以把它們想像成Office的Word和Excel,這兩組產品如果要跨平台到Mac的話,就會分支出Windows版和Mac版的,但是軟體做的事情是一樣的,所以它們繼承了共同的方法,如下圖:

AbstractFactoryPattern_01_thumb24

看完上圖後,可以看出每個產品都有Windows和Mac兩種系列,所以我們可以為他們寫兩個工廠類別,一個專門負責生產Windows,一個專門負責生產Mac的產品,來看看程式碼:

Factory interface:

   1: namespace AbstractFactoryPattern
   2: {
   3:     public interface Factory
   4:     {
   5:         // 想像成CreateWindowsProduct()
   6:         Product1 CreateProduct1();
   7:  
   8:         // 想像成CreateMacProduct()
   9:         Product2 CreateProduct2();
  10:     }
  11: }

ProductFactoryA class:

   1: namespace AbstractFactoryPattern
   2: {
   3:     // 想像成WordFactory
   4:     public class ProductFactoryA : Factory
   5:     {
   6:         public Product1 CreateProduct1()
   7:         {
   8:             // 生產Windows的Word
   9:             return new Product1A();
  10:         }
  11:  
  12:         public Product2 CreateProduct2()
  13:         {
  14:             // 生產Mac的Word
  15:             return new Product2A();
  16:         }
  17:     }
  18: }

ProductFactoryB class:

   1: namespace AbstractFactoryPattern
   2: {
   3:     // 想像成ExcelFactory
   4:     public class ProductFactoryB : Factory
   5:     {
   6:         public Product1 CreateProduct1()
   7:         {
   8:             // 生產Windows的Excel
   9:             return new Product1B();
  10:         }
  11:  
  12:         public Product2 CreateProduct2()
  13:         {
  14:             // 生產Mac的Excel
  15:             return new Product2B();
  16:         }
  17:     }
  18: }

Client:

   1: namespace AbstractFactoryPattern
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             // Word工廠
   8:             Factory productFactoryA = new ProductFactoryA();            
   9:             // 製造Windows和Mac版本的Word
  10:             Product1 product1A = productFactoryA.CreateProduct1();            
  11:             Product2 product2A = productFactoryA.CreateProduct2();
  12:             // 跑兩種版本的Word
  13:             product1A.Operation();
  14:             product2A.Operation();
  15:  
  16:             // Excel工廠
  17:             Factory productFactoryB = new ProductFactoryB();
  18:             // 製造Windows和Mac版本的Excel
  19:             Product1 product1B = productFactoryB.CreateProduct1();
  20:             Product2 product2B = productFactoryB.CreateProduct2();
  21:             // 跑兩種版本的Excel
  22:             product2B.Operation();
  23:             product1B.Operation();
  24:         }
  25:     }
  26: }

這樣就完成抽象工廠模式了,將 Factory 抽象化後, Client端就能利用多型的方法實體化Product,而不需要知道具體的類別就能操作它,這就是抽象工廠的優點。

進階技巧:

到這邊其實已經把工廠模式都介紹完了,不過其實上面的抽象工廠還是有不完美的地方,例如我們現在加入了一個新的Product系列ProductC(可以想像成Linux版本的Office),那麼我們除了要寫 Product1C 跟 Product2C 這些基本的類別外,還要再為它們新增一個 ProductFactoryC 的類別,讓人覺得有一些麻煩。

這邊要介紹大話設計模式一書中作者提供的一個技巧,可以將工廠模式再修改的更加完美。

SimpleAbstractFactoryPattern_thumb24 

看到上圖後,可以發現我們將 Factory 的抽象化拿掉了,變回最初的簡單工廠模式,這時候的 Factory 會變成這樣:

Factory class:

   1: using System;
   2:  
   3: namespace SimpleAbstractFactoryPattern
   4: {
   5:     public class Factory
   6:     {
   7:         public static Product1 CreateProduct1(string name)
   8:         {
   9:             switch (name)
  10:             {
  11:                 case "Product1A":
  12:                     return new Product1A();
  13:                 case "Product1B":
  14:                     return new Product1B();
  15:                 default:
  16:                     throw new Exception();
  17:             }
  18:         }
  19:  
  20:         public static Product2 CreateProduct2(string name)
  21:         {
  22:             switch (name)
  23:             {
  24:                 case "Product2A":
  25:                     return new Product2A();
  26:                 case "Product2B":
  27:                     return new Product2B();
  28:                 default:
  29:                     throw new Exception();
  30:             }
  31:         }
  32:     }
  33: }

這樣寫的話,之前才提到的開放-封閉原則的缺點不是又出現了嗎?
如果增加了一個新的 ProductC 類別的話,就需要在 Factory 裡面增加新的 switch case 分支條件,不容易擴充的問題就出現了。

這裡要介紹 C# 跟 JAVA 都有提供的一個機制,Reflection(反射)它可以直接依照 class 的名稱來實體化類別,我們直接來看看用Reflection機制修改後的 Factory 程式碼吧:

Factory class:

   1: using System;
   2: using System.Reflection;
   3:  
   4: namespace SimpleAbstractFactoryPattern
   5: {
   6:     public class Factory
   7:     {
   8:         // 專案的namespace
   9:         private static readonly string AssemblyName = "SimpleAbstractFactoryPattern";
  10:  
  11:         public static Product1 CreateProduct1(string name)
  12:         {
  13:             // 如果傳進來的name是"Product1A"
  14:             // 那className就等於SimpleAbstractFactoryPattern.Product1A
  15:             string className = AssemblyName + "." + name;
  16:  
  17:             // 這裡就是Reflection,直接依照className實體化具體類別
  18:             return (IProduct1)Assembly.Load(AssemblyName).CreateInstance(className);
  19:         }
  20:  
  21:         public static Product2 CreateProduct2(string name)
  22:         {
  23:             string className = AssemblyName + "." + name;
  24:  
  25:             return (IProduct2)Assembly.Load(AssemblyName).CreateInstance(className);
  26:         }
  27:     }
  28: }

Client:

   1: namespace SimpleAbstractFactoryPattern
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             // 生產產品A
   8:  
   9:             Product1 product1A = Factory.CreateProduct1("Product1A");
  10:             Product2 product2A = Factory.CreateProduct2("Product2A");
  11:  
  12:             product1A.Operation();
  13:             product2A.Operation();
  14:  
  15:             // 生產產品B
  16:  
  17:             Product1 product1B = Factory.CreateProduct1("Product1B");
  18:             Product2 product2B = Factory.CreateProduct2("Product2B");
  19:  
  20:             product2B.Operation();
  21:             product1B.Operation();
  22:         }
  23:     }
  24: }

看到了嗎!?這樣就算加入了其他 Product 子類別後,也不需要修改 Factory 的程式碼,只要在 CreateProduct() 方法內傳入要實體化的類別名稱就可以了,相當方便吧。

範例檔案:

參考資料:

2009年7月23日星期四
swfobject - 網頁輕鬆嵌入Flash

Flash在網頁上的應用已經越來越普遍了,未來一樣占有一席之位,但是從以前到現在,對於發佈Flash到網頁上常常碰到一些不必要的問題,例如XP SP2更新後,IE瀏覽器上方會出現檔掉的訊息,或是Flash外框出現虛線,需要滑鼠點一下才能開始動作等...,而且使用者並未安裝Flash Player的情況下或版本太低都會無法順利的瀏覽。

最近剛好看到一個不錯的東西,就是這次要介紹的swfobject,一般我們要嵌入swf到HTML時,通常會寫的語法如下:

<object id="FlashID" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="300" height="120">
  <param name="movie" value="test.swf" />
  <param name="quality" value="high" />
  <param name="wmode" value="opaque" />
  <param name="swfversion" value="6.0.65.0" />
</object>

上面的程式碼使用到<object>標籤,早一點的甚至還要再寫<embed>才能動作,因為IE跟其他瀏覽器的種種原因,使得這種寫法不但又臭又長,也不符合標準。

那使用swfobject有什麼好處呢?我們繼續看下去吧。

首先我們得先去swfobject的網頁http://code.google.com/p/swfobject/,然後下載目前的最新版本swfobject_2_2.zip
01 02

下載解壓縮後可以看到以下檔案:
swfobject
├ src (原始碼資料夾)
│  ├ expressInstall.as (flash player版本升級原始碼)
│  ├ expressInstall.fla (flash player版本升級原始碼)
│  └ swfobject.js (swfobject javascript)

expressInstall.swf (flash player版本升級程式)
index.html (HTML範例檔)
index_dynamic.html (HTML範例檔)
swfobject.js (swfobject javascript)
test.swf (測試用swf檔)

上面灰色的檔案是比較不重要的範例檔,我們只需要swfobject.js跟expressInstall.swf就可以了。
在這裡先解釋一下,expressInstall.swf是用來幫助使用者升級flash player用的swf檔,如果你發佈了一個版本為10的swf到網頁,而使用者的瀏覽器版本只到9或更低,網頁就會自動載入expressInstall.swf協助使用者升級player的版本。

下面我們開始使用swfobject,先建立一個資料夾,暫時命名為MySwfobject,然後在資料夾裡在建立一個js資料夾,我們把swfobject.swf複製到js資料夾內,然後將expressInstall.swf複製到MySwfobject資料夾內,再來我們需要一個測試用的flash,就把剛剛下載的test.swf一樣複製到MySwfobject資料夾內,最後建立一個空白的HTML檔index.html,程式碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>MySwfobject</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
</body>
</html>

這時我們的目錄應該如下的結構:
MySwfobject
├ js
│ └swfobject.swf

├ expressInstall.swf
├ index.html
└ test.swf

我們開始把test.swf嵌入到index.html,先在<head>標籤內導入swfobject.js:

<script src="js/swfobject.js" type="text/javascript"></script>

然後在底下加上這幾行javascript:

<script type="text/javascript">
    swfobject.embedSWF("test.swf", "mySwfobjectDiv", "300", "120", "9.0.0", "expressInstall.swf");
</script>

最後在<body>內加入id="mySwfobjectDiv"的<div>標籤:

<div id="mySwfobjectDiv"></div>

這時候用你的瀏覽器開啟index.html就會發現test.swf成功被嵌入了。03

大家可以發現程式碼非常的簡短,而且不需要一堆<object><embed>標籤,只需要一個<div>就可以輕鬆嵌入Flash,其中的核心就是swfobject.embedSWF("test.swf", "mySwfobjectDiv", "300", "120", "9.0.0", "expressInstall.swf");這行,這裡我們介紹一下swfobject.embedSWF的幾個參數:
swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes, callbackFn)

swfUrl 要嵌入的swf檔的位置 (例如在這裡我們是test.swf)
id 要嵌入在哪的HTML標籤id (在這裡我們是嵌入在<div id="mySwfobjectDiv">)
width Flash的寬
height Flash的高
version Flash Player的版本 (可直接輸入整數 ex:9 or 10)
expressInstallSwfurl
expressInstall.swf的位置
flashvars 要傳給Flash的變數
params Flash的參數 ex:menu,wmode,quality等...
attributes Flash本身的一些屬性 ex:id,name...
callbackFn 要callback給javascript的function

最後這裡附上加了flashvars,paramsattributes的index.html程式碼:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>MySwfobject</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <script src="js/swfobject.js" type="text/javascript"></script>
    <script type="text/javascript">
        var flashvars = {
        };
        var params = {
            menu: "false"
        };
        var attributes = {
            id:"MySwfobject"
        };
        swfobject.embedSWF("test.swf", "mySwfobjectDiv", "300", "120", "9.0.0", "expressInstall.swf", flashvars, params, attributes);
    </script>
</head>
<body>
    <div id="mySwfobjectDiv">
        <a href="http://www.adobe.com/go/getflashplayer">請安裝Flash Player</a>
    </div>
</body>
</html>

我們新增了關閉player menu的參數給swfobject,然後將id命名為MySwfobject,並且在mySwfobjectDiv的div標籤內加入一個Flash Plyer的安裝連結,如果使用者的瀏覽器沒有安裝Flash Player,swfobject就不會將test.swf嵌入到mySwfobjectDiv,而是直接顯示這行連結通知使用者安裝。

更多進階的使用文件可以參考swfobject的documentation

範例程式:

參考資料:

2009年7月16日星期四
Visual Studio Code Snippets

最近在看聖殿祭司寫的ASP.NET 3.5 專家技術手冊,上面提到Visual Studio 2005之後,提供一個很不錯的功能叫做Code Snippets(程式碼片段),這是一個可以快速產生常用程式碼的好東西。

在VS編輯器上將游標停在要加入程式碼片段的地方->滑鼠右鍵->插入程式碼片段,或是使用快捷鍵,預設是Ctrl+K->Ctrl+X,就會列出目前可以使用的程式碼片段清單。
03

04

05

06

上圖範例是快速產生foreach迴圈的程式碼,使用Code Snippets的好處是當我們每次要打一些常用的程式碼語法時,例如if、do while、for等等...就不必自己打一遍了,一方面平常輸入這些老是反覆再寫的程式碼時,效率不佳,而且另一方面有時候還會發生打錯或是想不起來怎麼寫的情況。

但是C#語言內建的程式碼片段很少,而且都是一些無關痛癢的基本語法,所以網路上有很多人將一些常用的C#程式碼片段寫成VS的擴充套件提供大家下載:

微軟
http://msdn.microsoft.com/en-us/vs2005/aa718338.aspx (英文)
http://msdn.microsoft.com/zh-tw/vs2005/aa718338.aspx (繁體中文)

CodePlex
http://www.codeplex.com/site/search?projectSearchText=Snippet

gotCODESNIPPETS.Net
http://gotcodesnippets.com/default.aspx

這邊我用微軟提供的程式碼片段作範例,首先要先去MSDN網站下載。
08 

點選 I accept。
09

下載完成後點擊Code_Snippets.msi進入安裝,安裝路徑為「Microsoft Visual Studio位置\VC#\Snippets\1033\自訂命名」,例如「C:\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\C# Snippets」。

接下來開啟VS2005或VS2008,點選工具->程式碼片段管理員
10

開啟程式碼片段管理員後,點擊加入->選擇剛剛安裝的目錄「C:\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\C# Snippets」->確定,完成後就可以看到C# Snippets目錄被加入到清單內了。
11

成功加入後我們馬上來試試,在要加入程式碼片段的地方右鍵->插入程式碼片段->C# Snippets->database->Create a local SQL Connection to SQL Server(or Express),然後在下一行繼續插入程式碼片段->C# Snippets->database->Create a Parameterized SELECT Command,這樣就完成一個資料庫的連接跟查詢功能,程式碼都幫我們產生好了,只需要改改變數或字串就可以了,非常方便吧!!!
12

除了下載安裝別人提供的套件外,當然也可以寫一份屬於個人的程式碼片段擴充套件,畢竟平常在寫哪些程式碼,只有自己是最清楚的,可以去微軟 Snippet EditorSnippy - Visual Studio code Snippet Editor下載編輯工具,詳細的介紹各位可以參考聖殿祭司的ASP.NET 3.5 專家技術手冊I-使用C#這本書,內容適合中高階經驗的人,值得一看!!!

2009年6月30日星期二
AS3 如何複製DisplayObject

最近正在寫一個FLASH的相片大頭貼截取程式,碰到了一個複製MovieClip的問題,AS3已經沒有AS2的duplicateMovie()方法可以用,所以我找了一些解決方法分享上來。

第一種方式是比較好的解決方法,是PTT的CJCAT大提供的,可以直接複製一個相同的Class。

假如場景上面有一個clip_mc,它的class是MyClip,在不使用 new MyClip() 的前提下,以下的code可以生出一個新的MyClip物件。

// 先抓到MyClip的constructor
var mcClass:Class = Object(clip_mc).constructor;
 
// 這樣就生出一個新的MyClip物件了
var clip2_mc:DisplayObject = new mcClass();
 
// 加入到舞台後就成功了
this.addChild(clip2_mc);

不過上面這個方法我試不出來,不知道是不是哪裡出錯了,所以又找了第二種方法,Copying a Sprite using BitmapData,這個方法可以將Sprite的畫面複製到另一個DisplayObject上,因為我只是需要複製一個靜態的圖,所以可以不需要使用第一種複製Class的方式。

// 先實體一個clip_mc大小的BitmapData
var myBitmapData:BitmapData = new BitmapData(clip_mc.width, clip_mc.height);
// 然後繪製一個相同的clip_mc
myBitmapData.draw(clip_mc);
 
// 實體一個複製的Bitmap
var clip2_mc:Bitmap = new Bitmap(myBitmapData);
 
// 加入到舞台後就成功了
this.addChild(clip2_mc);

參考資料:

載入中...