AS3.0 で光るテキスト効果を作ってみた

TVCM とか映画予告編などでよく見かける「文字が左から右に光るエフェクト」を ActionScript 3.0 で作ってみた。

完成品はこんな具合。

文字を編集することもできる。編集後の文字ですぐに光り始める!

やってること

  1. TextField を表示
  2. TextField を BitmapData に表示して、GlowFitler で光らせる (bmpGlow)
  3. 円形のマスク Sprite を用意 (msk)。周りに行くに従って透明になるようにしておく。
  4. 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; 
            } 
        }); 
    } 
} 
}