2009年09月07日
AS3.0 で光るテキスト効果を作ってみた

TVCM とか映画予告編などでよく見かける「文字が左から右に光るエフェクト」を ActionScript 3.0 で作ってみた。
完成品はこんな具合。
文字を編集することもできる。編集後の文字ですぐに光り始める!
やってること
- TextField を表示
- TextField を BitmapData に表示して、GlowFitler で光らせる (
bmpGlow) - 円形のマスク Sprite を用意 (
msk)。周りに行くに従って透明になるようにしておく。 - 2. で作った
bmpGlowに 3. のマスクmskを適用する。マスクを徐々に右に移動していけば、光ってるところが移動しているように見える。
苦労したのはグラデーションのマスクを適用させるところ。マスクとマスクされる DisplayObject の両方の cacheAsBitmap プロパティを true に設定しておく必要がある。
当初、それに気付かずに、copyPixel() を使って泥臭く実装していたんだけど、cacheAsBitmap すればアルファの Sprite で透明度を利用したマスクを作れることを教えてもらった。cacheAsBitmap を使って 書き直したら、10行短くなって、ソースコードも素直になって万歳。
ソースコードは以下に(73行)。
// Glowing Hellow World revised. (lines: 83 -> 73)
//-------------------------------------------------------
// An experiment on creating a dynamic glow text effect.
// You can edit the text!!!
package{
import flash.display.*;
import flash.events.Event;
import flash.filters.GlowFilter;
import flash.geom.*;
import flash.text.*;
[SWF(backgroundColor="#000000", width="450", height="80")]
public class GlowingHelloWorld extends Sprite{
public function GlowingHelloWorld(){
stage.scaleMode = "noScale";
var ptZero:Point = new Point();
// initialize canvas.
var bmpGlow:Bitmap = addChild(new Bitmap()) as Bitmap;
// Show original text (input)
var text:TextField = new TextField();
text.autoSize = "left";
text.type = "input";
text.htmlText = <font size="50" color="#ffffff">HELLO WORLD</font>.toXMLString();
addChild(text);
text.addEventListener("change", function(event:Event):void{ updateGlow() });
// Create a glow BitmapData.
var bmdGlow:BitmapData, bmdCanvas:BitmapData;
var updateGlow:Function = function():void{
// dispose existing BitmapData.
if (bmdGlow) bmdGlow.dispose();
// Glow it.
bmdGlow = new BitmapData(text.textWidth + 10, text.textHeight + 10, true, 0);;
bmdGlow.draw(text);
var glow:GlowFilter = new GlowFilter(0xffffff, .9, 8, 8, 4);
bmdGlow.applyFilter(bmdGlow, bmdGlow.rect, ptZero, glow);
// Update canvas BitmapData.
bmpGlow.bitmapData = bmdGlow;
}
updateGlow();
// Create a mask sprite.
var msk:Sprite = new Sprite();
msk.graphics.beginGradientFill("radial", [0xffffff, 0xffffff], [1, 0], [64, 255]);
msk.graphics.drawCircle(0, 0, 100);
msk.graphics.endFill();
addChild(msk);
// Set mask.
msk.y = 50 - text.textHeight / 2;
bmpGlow.cacheAsBitmap = msk.cacheAsBitmap = true;
bmpGlow.mask = msk;
// Start animation loop.
var counter:int = 0;
addEventListener("enterFrame", function(event:Event):void{
// move the mask
msk.x = counter;
// update counter...
counter += 14;
if (counter > 800){
counter = -10;
}
});
}
}
}