フィルターを操作する際には、混乱やトラブルの原因になる可能性があるため注意を必要とする事項がいくつかあります。
フィルターとビットマップキャッシュ
表示オブジェクトにフィルターを適用するには、そのオブジェクトのビットマップキャッシュを有効にする必要があります。
cacheAsBitmap
プロパティが
false
に設定されている表示オブジェクトにフィルターを適用すると、オブジェクトの
cacheAsBitmap
プロパティが自動的に
true
に設定されます。表示オブジェクトのすべてのフィルターを削除すると、
cacheAsBitmap
プロパティは現在の設定値の直前の設定値にリセットされます。
実行時のフィルターの変更
表示オブジェクトに 1 つ以上のフィルターが既に適用されている場合、
filters
プロパティ配列にフィルターを追加したり、配列からフィルターを削除したりして、フィルターのセットを変更することはできません。その代わり、適用されているフィルターのセットを追加または変更するには、独立した配列に対して変更を行い、その配列を表示オブジェクトの filters プロパティに割り当てて、フィルターをオブジェクトに適用する必要があります。その最も簡単な方法は、
filters
プロパティ配列を Array 変数に読み込み、この一時配列に対して修正を行うことです。 次に、この配列を表示オブジェクトの
filters
プロパティに再度割り当てます。 さらに複雑な場合には、独立したマスタフィルター配列の保持が必要になる場合があります。マスタフィルター配列に対して変更を行い、変更ごとにマスタ配列を表示オブジェクトの
filters
プロパティに再度割り当てます。
フィルターの追加
次のコードは、1 つ以上のフィルターが既に適用されている表示オブジェクトにフィルターを追加するプロセスを示しています。まず、グローフィルターが
myDisplayObject
という名前の表示オブジェクトに適用されます。その後、この表示オブジェクトがクリックされたときに、関数
addFilters()
が呼び出されます。この関数では、2 つの追加フィルターが
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);
フィルターセットからのフィルターの削除
表示オブジェクトに複数のフィルターが適用されており、そのうち 1 つのフィルターを削除する一方、他のフィルターはオブジェクトに適用し続ける必要がある場合には、フィルターを一時配列にコピーし、不要なフィルターをその配列から削除して、表示オブジェクトの
filters
プロパティに一時配列を再度割り当てます。 配列から 1 つ以上の要素を削除する方法については、
値の取得と配列要素の削除
で説明します。
最も簡単なのは、オブジェクトの一番上のフィルター(オブジェクトに最後に適用されたフィルター)を削除する場合です。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 クラスの
pop()
メソッドを
shift()
メソッドに置き換える以外は同じコードを使用します。
フィルターの配列の中間(配列に 3 つ以上のフィルターがあると仮定)からフィルターを削除するには、
splice()
メソッドを使用します。 削除するフィルターのインデックス(配列内の位置)を確認しておく必要があります。 例えば、次のコードでは、表示オブジェクトから 2 番目のフィルター(インデックス 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;
フィルターのインデックスの確認
フィルターのインデックスを確認するには、どのフィルターを配列から削除するのかを知っておく必要があります。削除するフィルターのインデックスを確認する(アプリケーションの設計方法による)か、または計算する必要があります。
最良の方法は、削除するフィルターが常にフィルターのセット内の同じ位置にくるように、アプリケーションを設計することです。例えば、畳み込みフィルターとドロップシャドウフィルターを(この順序で)1 つの表示オブジェクトに適用し、ドロップシャドウフィルターを削除する一方、畳み込みフィルターを保持する場合、どの 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
プロパティとして適用します。
例えば、次のコードでは、複数の畳み込みフィルターが表示オブジェクトに適用されて、様々な視覚効果が作成されます。さらに、アプリケーションの後半では、これらのフィルターのうちの 1 つが削除され、他のフィルターは保持されます。この場合、コードでは、フィルター配列のマスタコピーおよび削除するフィルターへの参照が保持されます。特定のフィルターの検索および削除の方法は、フィルター配列の一時コピーを作成する代わりに、マスタコピーが操作された後に表示オブジェクトに適用されることを除いて、前述の方法に似ています。
// 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
プロパティは、フィルター適用前の値にリセットされます。