0.8.0さまざまな色と大きさの円を、それぞれの向きに動かします(サンプル001)。速さは大きさと比例させました。フィルタで縁をぼかし、重なった色を加算することにより、光のような表現にしています。0.8.0)に対応させるとともに、スクリプトの構成をわかりやすく書き改めました。簡単な最適化の手法も加えています。ランダムな色と大きさの円をステージに置くまずは、ランダムな色と大きさの円を、予め決めた数だけステージに置きましょう。アニメーションは後回しです。Shapeインスタンスをつくって返す関数(createCircle())は、つぎのようなかたちで定めます。引数には、xy座標と色、および半径を渡します。以下に抜書きするスクリプトの行番号は、後にまとめたコード001にもとづきます。myShape;}円のインスタンスをつくる関数(createCircle())は、つぎのように初期設定の関数(initialize())からfor文で、予め変数(count)に定めた数だけ呼出します(第1行目および第10行目〜)。つくる円の色(randomColor)とxy座標(xとy)、および半径(radius)は、ランダムに定めました(第11〜14行目)。initialize;これてで、さまざまな色と大きさのShapeインスタンスがつくられて、ランダムな位置に置かれます。Canvasの背景色は黒に定めました(図001)。ここまで書いたJavaScriptコードは、以下のコード001にまとめたとおりです。色の効果とアニメーションを加えるでは、つぎにアニメーションを加えます(後掲コード002)。円の動く速さは半径(radius)に比例させ、角度(angle)をランダムに定めます(第13および第17行目)。半径と角度からxy座標の成分を求める式はつぎのとおりです(「sinとcosは何する関数?」02「理解すれば覚えることは減る」)。半径×sin(角度)速さのxy成分値はPointオブジェクト(velocity)に納めて、円をつくる関数(createCircle())に引数として渡します(第17〜19行目)。関数はその引数を、Shapeインスタンス(myShape)のプロパティ(velocity)に加えました(第26および第34行目)。Ticker.tickイベントにリスナー関数(tick())を定めています。velocity;}Ticker.tickイベントのリスナー関数(tick())は、Container.numChildrenプロパティでStageオブジェクトに加えた子インスタンスの数を調べ、forループでContainer.getChildAt()メソッドにより子インスタンスを順に取出します(第39〜41行目)。あとは、インスタンスに定めた速度のプロパティ(velocity)から、xy座標値を加えればよいでしょう(第44および第46〜47行目)。インスタンスがステージの外に出たら、反対の端に戻しました。そのとき、円のインスタンスの基準点は中心に置いていますので、半径(radius)の大きさだけ位置を調整しています(第48〜59行目)。ステージの外側に完全に消えたら、反対の端の隠れた位置から表れるようにしました。y;}stage.update();}そして、重ねたオブジェクトのピクセルごとの描画の仕方を決めるのがDisplayObject.compositeOperationプロパティです(第10行目)。値を"lighter"に定めると、ピクセルのカラー値を加算しますので、描画するオブジェクトが重なるほど明るくなります(「時間差をつけたトゥイーン」の「DisplayObject.compositeOperationプロパティでイメージのピクセルを合成する」参照)。"lighter";}これで、インスタンスが半径と比例した速さで、ランダムな向きにアニメーションします。重なったピクセルのカラー値は加算されて、光って見えるようになりました(図002)。ここまでのJavaScriptコードをまとめたのが、コード002です。アニメーションするインスタンスにぼかしを加える円のインスタンスには、BlurFilterオブジェクトでぼかしを加えます。一般に、オブジェクトにフィルタをかけるには、つぎの3つの操作を行います。フィルタのインスタンスをつくる。フィルタオブジェクトを配列に入れてDisplayObject.filtersプロパティに定める。フィルタをDisplayObject.cache()メソッドで描画する。第1に、フィルタのインスタンスをつくります。BlurFilter()コンストラクタには3つの引数が渡せます。初めのふたつは,それぞれ水平と垂直のぼかし幅で、単位はピクセルです。3つ目は、ぼかしのきめ細かさを1から3の整数を目安として与えます(デフォルト値は1)。この整数は、内部的にぼかしを重ねる回数になるので、増やせば負荷が上がります。水平および垂直ぼかしの幅は、BlurFilter.blurXとBlurFilter.blurYプロパティで後から定めることもできます。ぼかし品質)手順の第2は、フィルタオブジェクトを配列に入れて、DisplayObject.filtersプロパティに与えます。配列に加えるのは、フィルタを複数かけられるように考えられた仕組みです。第3に、設定されたフィルタをDisplayObject.cache()メソッドで描画しなければなりません。内部的には、Canvasが新たにつくられ、そこでフィルタの演算と描画を行った後、ステージにその結果が加えられます。引数は矩形領域を示す4つの座標値で、その範囲にフィルタのかかったイメージが描かれます[*1]。高さ)インスタンスにBlurFilterのフィルタを加える関数(setBlur())は、つぎのように定めました。ぼかし幅は円の半径に比例させます。初期設定の関数(initialize())で円のインスタンスをつくったすぐ後に呼出しました。でき上がったJavaScriptコードは、後にコード003としてまとめています。Rectangleオブジェクト)関数(setBlur())は、ぼかし幅を引数値(blur)、フィルタがかかる領域は円の半径(radius)から求め、引数のBlurFilterオブジェクト(blurFilter)とRectangleオブジェクト(rect)のプロパティに定めたうえで、インスタンス(myShape)をぼかします(第41〜48行目)。rect.height);}これでお題はでき上がりました。色とりどりのさまざまな円が、ぼんやりとした光のように交錯します。初めに掲げたサンプル001のJavaScriptコードが以下のコード003です。ぼかしフィルタをかけると、もとのイメージより領域が広がります。DisplayObject.cache()メソッドの引数に渡す矩形座標は、もとのイメージの値で構いません。フィルタをかけて変わる矩形座標は、内部的に調べられて値が調整されるからです。フィルタによって変わる矩形座標は、Filter.getBounds()メソッドによりRectangleオブジェクトのかたちで得られます。DisplayObject.cache()メソッドの実装は、内部的にDisplayObject.updateCache()メソッドを用いており、その中からプライベートなメソッド_getFilterBounds()が呼出されます。このメソッドは、インスタンスにかけられたすべてのフィルタについてFilter.getBounds()メソッドにより矩形座標を調べるのです。0.8.0から、Filter.getBounds()メソッドに引数(オプション)として、もとのイメージの矩形座標がRectangleオブジェクトで渡せるようになりました。最適化のヒント前掲コード003は、最適化にも少し気をつかいました。オブジェクトの数も処理も少ないので、目に見えて変わるところはありません。大量の処理を行うときのヒントと考えてくださればよいでしょう。ひとつ目は、つぎのオブジェクトを動かすための演算です。プロパティ値を、予めローカル変数に納めています(第53〜56行目)。1行1行のステートメントは短くなったものの、行数そのものは増えてしまいました。y;つぎのようにローカル変数を使わなくても、アニメーションに変わりはありません。行数は2/3になります。オブジェクトからプロパティを取出すより、ローカル変数の方が速く参照できます。多くのオブジェクトをループ処理で扱う場合には、何度か参照する値はローカル変数に入れた方がお得です。circle.radius;}ふたつ目は、インスタンスをぼかす関数(setBlur())に渡した引数です。前掲コード003では、BlurFilterとRectangleオブジェクトを引数に含め、それらは関数を呼出すforループの外でつくりました(前掲コード003第7〜8行目)。以下のように関数の中でオブジェクトをつくった方が、引数もふたつに減ってすっきりするように感じられます(第43および第46行目)。オブジェクトを新たにつくるより、すでにあるものを使い回す方が、わずかに負荷が減ります。それより大切なのは、BlurFilterとRectangleオブジェクトはつくって一度使うだけの使い捨てだということです。これらのオブジェクトをたくさんつくり続けると、用済みのオブジェクトがメモリに溜まります。それらを自動的にかたづけるJavaScriptの手間が増えてしまうのです。詳しくは、「オブジェクトの使い回しとアニメーション素材の変更」の「ガベージコレクションを減らす」をお読みください。注[*1]を加え、それにともない本文とコード003を修正。