使用濾鏡時,請注意幾點可能讓您混淆或困擾的問題成因。
濾鏡和點陣圖快取
若要將濾鏡套用至顯示物件,必須啟用該物件的點陣圖快取功能。若您套用濾鏡的物件,其
cacheAsBitmap
屬性設為
false
,則該物件的
cacheAsBitmap
屬性會自動設為
true
。若您稍後從顯示物件移除所有濾鏡,
cacheAsBitmap
屬性會重設為原本的設定。
在執行階段變更濾鏡
如果顯示物件已經套用了一個或多個濾鏡,您就不可以將其它濾鏡加入
filters
屬性陣列中,或從中移除濾鏡來變更濾鏡組。若要加入或變更要套用的濾鏡組,您必須變更個別的陣列,然後將該陣列指定給顯示物件的 filters 屬性,才能讓濾鏡套用到物件上。最簡單的方式是將
filters
屬性陣列讀入 Array 變數,然後修改這個暫存陣列。接著,您可以將此陣列重新指定給顯示物件的
filters
屬性。在較為複雜的案例中,您可能需要保留濾鏡的個別主陣列。請對該主濾鏡陣列進行任何變更,然後在每個變更後,將主陣列重新指定給顯示物件的
filters
屬性。
加入其它濾鏡
下列程式碼示範將其它濾鏡加入已經套用一或多個濾鏡之顯示物件的程序。首先,將光暈濾鏡套用至名為
myDisplayObject
的顯示物件;之後,每當按一下顯示物件時,就呼叫
addFilters()
函數。兩個額外的濾鏡就會透過這個函數套用至
myDisplayObject
:
import flash.events.MouseEvent;
import flash.filters.*;
myDisplayObject.filters = [new GlowFilter()];
function addFilters(event:MouseEvent):void
{
// Make a copy of the filters array.
var filtersCopy:Array = myDisplayObject.filters;
// Make desired changes to the filters (in this case, adding filters).
filtersCopy.push(new BlurFilter());
filtersCopy.push(new DropShadowFilter());
// Apply the changes by reassigning the array to the filters property.
myDisplayObject.filters = filtersCopy;
}
myDisplayObject.addEventListener(MouseEvent.CLICK, addFilters);
從一組濾鏡移除一個濾鏡
如果顯示物件已經套用多個濾鏡,而且您想要在繼續將其它濾鏡套用到該物件時移除其中一個濾鏡,您可以將濾鏡複製到暫存陣列、從該陣列移除不想要的濾鏡,然後將暫存陣列重新指定給顯示物件的
filters
屬性。從任何陣列移除一個或多個元素的數種方式詳述於
擷取值以及移除陣列元素
中。
最直接的方式,便是移除物件最上層的濾鏡 (套用到物件的最後一個濾鏡)。您可以使用 Array 類別的
pop()
方法來移除陣列中的濾鏡:
// Example of removing the top-most filter from a display object
// named "filteredObject".
var tempFilters:Array = filteredObject.filters;
// Remove the last element from the Array (the top-most filter).
tempFilters.pop();
// Apply the new set of filters to the display object.
filteredObject.filters = tempFilters;
同樣地,若要移除最下層的濾鏡 (套用到物件的第一個濾鏡),您可以使用相同的程式碼替代 Array 類別的
shift()
方法來取代
pop()
方法。
若要從濾鏡陣列的中間移除濾鏡 (假設該陣列有兩個以上的濾鏡),您可以使用
splice()
方法。您必須知道要移除之濾鏡的索引 (陣列中的位置)。例如,下列程式碼會從顯示物件移除第二個濾鏡 (索引 1 的濾鏡):
// Example of removing a filter from the middle of a stack of filters
// applied to a display object named "filteredObject".
var tempFilters:Array = filteredObject.filters;
// Remove the second filter from the array. It's the item at index 1
// because Array indexes start from 0.
// The first "1" indicates the index of the filter to remove; the
// second "1" indicates how many elements to remove.
tempFilters.splice(1, 1);
// Apply the new set of filters to the display object.
filteredObject.filters = tempFilters;
判斷濾鏡的索引
您必須知道要從陣列移除哪個濾鏡,才會知道該濾鏡的索引。此外,您也需要知道 (根據設計應用程式的方式) 或計算要移除的濾鏡索引。
最好的方法是在設計您的應用程式時,讓您要移除的濾鏡永遠位於濾鏡組中的相同位置。例如,如果所擁有的單一顯示物件已套用迴旋濾鏡與投影濾鏡 (以該順序),而且您想要移除投影濾鏡但保留迴旋濾鏡,濾鏡會位於已知的位置 (最上層的濾鏡),因此您可以事先知道要使用的 Array 方法 (此範例是使用
Array.pop()
來移除投影濾鏡)。
如果您要移除的濾鏡永遠是特定類型,但不一定位於濾鏡組中的相同位置,您可以檢查陣列中的每個濾鏡資料類型來決定要移除的濾鏡。例如,下列程式碼會判斷哪個濾鏡組是光暈濾鏡,並從濾鏡組中移除該濾鏡。
// Example of removing a glow filter from a set of filters, where the
//filter you want to remove is the only GlowFilter instance applied
// to the filtered object.
var tempFilters:Array = filteredObject.filters;
// Loop through the filters to find the index of the GlowFilter instance.
var glowIndex:int;
var numFilters:int = tempFilters.length;
for (var i:int = 0; i < numFilters; i++)
{
if (tempFilters[i] is GlowFilter)
{
glowIndex = i;
break;
}
}
// Remove the glow filter from the array.
tempFilters.splice(glowIndex, 1);
// Apply the new set of filters to the display object.
filteredObject.filters = tempFilters;
在較為複雜的案例中,例如,如果要移除的濾鏡是在執行階段選取的,最好的方法是保留當做主濾鏡清單之濾鏡陣列的個別、持續副本。每當您要變更濾鏡組時,請變更主清單,然後套用該濾鏡陣列,做為顯示物件的
filters
屬性。
例如,下面列出的程式碼會將多個迴旋濾鏡套用至顯示物件來建立不同的視覺效果,並在稍後於應用程式中移除其中一個濾鏡,而保留其它的濾鏡。在此案例中,程式碼會保留濾鏡陣列的主副本,以及要移除之濾鏡的參考。尋找並移除特定的濾鏡與前述方法類似,但是不會製作濾鏡陣列的暫存副本,而是直接操作主副本,然後套用到顯示物件。
// Example of removing a filter from a set of
// filters, where there may be more than one
// of that type of filter applied to the filtered
// object, and you only want to remove one.
// A master list of filters is stored in a separate,
// persistent Array variable.
var masterFilterList:Array;
// At some point, you store a reference to the filter you
// want to remove.
var filterToRemove:ConvolutionFilter;
// ... assume the filters have been added to masterFilterList,
// which is then assigned as the filteredObject.filters:
filteredObject.filters = masterFilterList;
// ... later, when it's time to remove the filter, this code gets called:
// Loop through the filters to find the index of masterFilterList.
var removeIndex:int = -1;
var numFilters:int = masterFilterList.length;
for (var i:int = 0; i < numFilters; i++)
{
if (masterFilterList[i] == filterToRemove)
{
removeIndex = i;
break;
}
}
if (removeIndex >= 0)
{
// Remove the filter from the array.
masterFilterList.splice(removeIndex, 1);
// Apply the new set of filters to the display object.
filteredObject.filters = masterFilterList;
}
利用這個方法 (在您比較已儲存在濾鏡陣列中的項目濾鏡參考來判斷要移除的濾鏡時),您「必須」保留濾鏡陣列的個別副本;如果您是在從顯示物件之
filters
屬性複製的暫存陣列中,比較已儲存的元素濾鏡參考,則該程式碼沒有作用。這是因為當您在內部將陣列指定給
filters
屬性時,執行階段會製作陣列中每個濾鏡物件的副本。這些副本 (而非原始物件) 會套用到顯示物件,而且當您將
filters
屬性讀入暫存陣列時,暫存陣列中會包含已複製之濾鏡物件的參考,而非原始濾鏡物件的參考。因此,如果您在上述範例中,透過比較
filterToRemove
與暫存濾鏡陣列中的濾鏡來嘗試判斷其索引,則不會找到任何相符項目。
濾鏡與物件變形
位於顯示物件的矩形範圍框外面的無濾鏡區域 (如投影) 會被視為具有感應區偵測用途 (判斷實體與其它實體重疊或相交) 的表面之一部分。由於 DisplayObject 類別的感應區偵測方法屬於向量架構,您無法在點陣圖結果上執行感應區偵測。例如,如果您將斜角濾鏡套用到按鈕實體,實體的斜角部分就沒有感應區偵測作用。
濾鏡不支援縮放、旋轉和傾斜;當有濾鏡的顯示物件本身縮放時 (
scaleX
和
scaleY
不是 100%),濾鏡效果並不會跟著實體一起縮放。這表示實體的原始形狀會旋轉、縮放或傾斜,但是濾鏡並未跟著實體一起旋轉、縮放或傾斜。
您可以將含有濾鏡的實體做成動畫以建立具真實感的特效,或巢狀放置實體並使用 BitmapData 類別進行濾鏡的動畫以達到此效果。
濾鏡和點陣圖物件
當您將任何濾鏡套用至 BitmapData 物件時,
cacheAsBitmap
屬性就會自動設為
true
。這樣一來,濾鏡會實際套用至物件副本上,而不是套用至原始物件上。
接著,此副本會放置到主要顯示中 (於原始物件上) 且儘可能地接近最靠近的像素。如果原始點陣圖的邊界變更,就會從原始物件重新建立含濾鏡的點陣圖副本,而不是加以延伸或扭曲。
如果您清除了顯示物件的所有濾鏡,會將
cacheAsBitmap
屬性重設為套用濾鏡之前的屬性。