サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

EaselJS 0.7.1: ColorFilterクラスでインスタンスの塗りのグラデーションを反転させる

ID: FN1312005 Technique: HTML5 and JavaScript Library: EaselJS 0.7.1

ColorFilterクラスが定めるのは、インスタンスのカラーをチャネルごとに変換するフィルタです。RGBとアルファチャネルの出力が変えられます。本稿では、Shapeインスタンスに塗ったグレースケールのグラデーションを反転してみます。また、使い方が少しわかりにくい、メソッドDisplayObject.getBounds()DisplayObject.setBounds()についてもご説明します。


01 ColorFilterクラスでインスタンスのカラーを変える

先にjsdo.itのサンプルコードを掲げます(サンプル001)。ステージの真ん中に置いた矩形のShapeインスタンスには、放射状のグレーのグラデーションを塗りました。グラデーションは中心が白で外枠に向かって黒く定めてあります。インスタンスをクリックすると、中心が黒で外へ白く変わるグラデーションに反転します。さらにクリックすると、もとの塗りに戻ります。

サンプル001■インスタンスに塗ったグレースケールのグラデーションを反転する

まず、ColorFilterクラスを使った基本的なカラー変換の仕方からご説明しましょう。RGBAカラーチャネルごとのカラー値は、それぞれふたつのパラメータで操作します。ひとつは乗数で、現在の値を1として掛け算する比率で0まで下げられます。もうひとつが、増減する階調数です。-255から255までの値が定められます。

  • チャネル×乗数 + 増減階調

ColorFilter()コンストラクタには、この乗数と階調をRGBAチャネルごとに計8つの引数として渡します。

new ColorFilter(赤乗数, 緑乗数, 青乗数, アルファ乗数, 赤階調, 緑階調, 青階調, アルファ階調)

たとえば、塗りが白のインスタンスに、ColorFilterオブジェクトのフィルタで赤チャネルの乗数を0に定めると、カラー値の赤成分がなくなりますので塗りはシアンに変わります。あるいは、黒の塗りはカラー値がRBGすべて0ですので、乗数値にいくつを掛けても0のままです。けれども、赤成分に255階調を加えれば、カラーは赤に変わります。

Flash Professional CCでつくるコンテンツは、[プロパティ]パネルでインスタンスの[カラー効果]を操作でき、アルファ・赤・緑・青のチャネルごとに乗数のパーセンテージと階調の増減が定められます(図001)。EaselJSのColorFilterクラスは、JavaScriptコードでこの変換を行うものです。

図001■Flash Professional CCの[プロパティ]パネルにおける[カラー効果]の設定
図001

たとえば、マゼンタで塗ったShapeインスタンスのカラーは、ColorFilterクラスを使った以下のコード001 でシアンに変わります。まず、ColorFilter()コンストラクタに与えた乗数は、赤と緑が0で青とアルファが1です(第1行目)。カラー値の赤が0になり、緑はもともとありませんので、青のみそのまま1で残ります。そして、緑に255階調加えることで、カラーはシアンになります。

つぎに、Filterオブジェクトは配列に納めてインスタンス(instance)のDisplayObject.filtersプロパティに定めます(第2行目)。そのうえで、DisplayObject.cache()メソッドによりキャッシュを書替えます(第3行目)。キャッシュする矩形領域(Rectangleオブジェクト)は変数(bounds)に納められているものとします。テスト用のコードをサンプル002として掲げました。

コード001■ColorFilterオブジェクトでインスタンスの赤と緑の乗数を0にして緑に255階超加える
  1. var colorFilter = new createjs.ColorFilter(0, 0, 1, 1, 0, 255, 0, 0);
  2. instance.filters = [colorFilter];
  3. instance.cache(bounds.x, bounds.y, bounds.width, bounds.height);
  4. stage.update();

サンプル002■インスタンスの塗りをマゼンタからシアンに変える

02 ColorFilterオブジェクトのフィルタで白と黒を反転させる

前述のとおり、ColorFilter()コンストラクタのRGBの乗数(第1〜第3引数)には、0から1までの値を与えるのが普通です。負数を定めてもカラー値に0が定められたときと見た目は変わりません。けれども、階調数(第5〜第7引数)と組合わせると、カラー値0を255に、255を0に反転することができます。つまり、白と黒を逆転できるのです。

初めにご紹介したサンプル001のとおり、Shapeインスタンスに塗ったグレースケールのグラデーションを反転させます。この例では、ColorFilter()コンストラクタにつぎのような引数を与えました。RGBチャネルの乗数を-1、階調数は255に定めています。

var colorFilter = new createjs.ColorFilter(-1, -1, -1, 1, 255, 255, 255, 0);

各チャネルの値がこれらの乗数と階調数でどうかわるのか。カラー値0と255について確かめてみましょう。カラー値0に乗数-1を掛けても0のままです。けれど、階調数255を加えることで、255になります。また、カラー値255に乗数-1を掛けると-255になるものの、見た目は0と変わりません。しかし、階調数255を加えて0になるのです。

  • カラー値0:
    0×(-1) + 255 = 255
  • カラー値255:
    255×(-1) + 255 = 0

サンプル001のポイントとなるスクリプトは、後にコード002としてまとめて掲げました。その中で、ColorFilterオブジェクトのフィルタをインスタンスに適用するコードは以下に抜書きしたとおりです。

まず、ColorFilter()コンストラクタに渡す引数は、前述のとおりです(第1行目)。つぎに、Shapeインスタンス(instance)のDisplayObject.clickイベントにEventDispatcher.on()メソッドでリスナー(changeColor())を加えています。なお、EventDispatcher.on()は、EaselJS 0.7.0から加わったリスナーを登録するメソッドです(EventDispatcher.addEventListener()と同じ機能)。

そして、リスナー関数(changeColor())は、クリックしたインスタンスの参照(instance)を得ます(第6行目)。その後、インスタンスにフィルタが掛かっていなければ加え、掛かっていたら外す処理になります。DisplayObject.filtersプロパティを調べて、配列があれば変数(filters)に取出し、なければ空の配列を与えます(第8行目)。なお、この論理和演算子||の使い方については、「論理演算子を使った条件判定」の02「初期化されていない変数に値を与える」をご参照ください。

インスタンス(instance)にフィルタが加えられているかどうかは、配列(filters)の長さが0でないことによって確かめられます(第9行目)。フィルタがすでにあれば、長さを0に定めてエレメントを除きます(第10行目)。なければ、配列にColorFilterオブジェクト(colorFilter)を加えます(第12行目)。

後のフィルタの適用の仕方は、前掲コード001と同じです(第14〜16行目)。これで前掲サンプル001のように、グレースケールのグラデーションがクリックするたびに反転します。

  1. var colorFilter = new createjs.ColorFilter(-1, -1, -1, 1, 255, 255, 255, 0);
  1. instance.on("click", changeColor);
  2. function changeColor(eventObject) {
  3.   var instance = eventObject.target;
  1.   var filters = instance.filters || [];
  2.   if (filters.length) {
  3.     filters.length = 0;
  4.   } else {
  5.     filters[0] = colorFilter;
  6.   }
  7.   instance.filters = filters;
  8.   instance.cache(bounds.x, bounds.y, bounds.width, bounds.height);
  9.   stage.update();
  10. }

03 Shapeオブジェクトに矩形領域を定める ー DisplayObject.getBounds()とDisplayObject.setBounds()メソッド

EaselJS 0.7.0からDisplayObject.getBounds()DisplayObject.setBounds()メソッドが備わりました。サンプル001ではこれらのメソッドを用いています。ただ、誤解されがちなところもあるのでご説明します(「EaselJSの次期バージョンでオブジェクトの幅と高さを取得する実装」参照)。

DisplayObject.getBounds()メソッドは、矩形領域のRectangleオブジェクトが戻り値です。ところが、矩形を描いたShapeインスタンスでこのメソッドを呼出すとnullが返されます。そもそも、DisplayObject.getBounds()メソッドがインスタンスの正確な矩形領域のRectangleオブジェクトを返すのは、BitmapとSpriteインスタンスくらいです。後は、戻り値が概算であったり、Shapeインスタンスに至ってはデフォルト値はnullです。

今のところ、DisplayObject.getBounds()メソッドは、オブジェクトの矩形領域を扱う手助けになる、というくらいの位置づけです。Shapeインスタンスであれば、描画をするときに矩形領域は決められます。その値をRectangleオブジェクトにしてインスタンスに定めるのが、DisplayObject.setBounds()メソッドなのです。たとえば、Shapeインスタンス(instance)にグラデーションの矩形を描くとき、ふたつのメソッドをつぎのように用いることができます。

var instance = new createjs.Shape();
instance.setBounds(-25, -25, 50, 50);
draw(instance, ["black", "white"], [1, 0]);
function draw(instance, colors, ratios) {
  var myGraphics = instance.graphics;
  var bounds = instance.getBounds();
  var radius = bounds.width / 2 * Math.SQRT2;
  myGraphics.beginRadialGradientFill(colors, ratios, 0, 0, 0, 0, 0, radius)
  .drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
}

前掲サンプル001は、インスタンスのクリックでColorFilterオブジェクトによりグレースケールのグラデーションを反転させました。そのスクリプトの中ではつぎのコード002のように、予めShapeインスタンス(instance)にDisplayObject.setBounds()メソッドで矩形領域の値を与えています(第3行目)。そのうえで、DisplayObject.clickイベントのリスナー関数(changeColor())がインスタンスからDisplayObject.getBounds()メソッドでRectangleオブジェクトを得て、DisplayObject.cache()メソッドの適用領域として用いました(第7および第15行目)。

コード002■Shapeインスタンスに描いたグレーのグラデーションをColorFilterオブジェクトで反転する
  1. var colorFilter = new createjs.ColorFilter(-1, -1, -1, 1, 255, 255, 255, 0);
  2. var instance = new createjs.Shape();
  3. instance.setBounds(-25, -25, 50, 50);
  4. instance.on("click", changeColor);
  5. function changeColor(eventObject) {
  6.   var instance = eventObject.target;
  7.   var bounds = instance.getBounds();
  8.   var filters = instance.filters || [];
  9.   if (filters.length) {
  10.     filters.length = 0;
  11.   } else {
  12.     filters[0] = colorFilter;
  13.   }
  14.   instance.filters = filters;
  15.   instance.cache(bounds.x, bounds.y, bounds.width, bounds.height);
  16.   stage.update();
  17. }


作成者: 野中文雄
作成日: 2013年12月28日


Copyright © 2001-2013 Fumio Nonaka.  All rights reserved.