Typography #001 BubbleType
/**
* Copyright amane ( http://wonderfl.net/user/amane )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/bDgi
*/
package {
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
public class test extends Sprite
{
public function test()
{
var tfm:TextFormat, tf:TextField,bt:BubbleType;
tfm = new TextFormat("Arial","70",0x000000);
tf = new TextField();
tf.defaultTextFormat = tfm;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.text = "?";
bt = new BubbleType(tf);
bt.init(1000, 500, 250, 1000, 5, 0xff0000ff, 0x00ffffff, 500, 0.03, false , true, true, true, false);
addChild(bt);
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
/**
* ...
* @author
*/
class BubbleType extends Sprite
{
private const FRIC_COEF:Number = 0.95; //摩擦係数
private const BUOY_COEF:Number = 0.3; //浮力係数
private const DIFFUSE_COEF:Number = 10; //拡散係数
private const PI:Number = Math.PI; //π
private var m_stage:Stage; //stage
private var m_bmdCanvas:BitmapData; //canvas
private var m_recFill:Rectangle = new Rectangle(); //bitmapdata描画用rectangle
private var m_tfText:TextField; //text
private var m_vprtParticle:Vector.<Particle> = new Vector.<Particle>(); //Particle
private var m_vbPixel:Vector.<Boolean> = new Vector.<Boolean>(); //ピクセル位置
private var m_nAngle:Number = 0; //signwave用カウンタ
private var m_nStageW:Number = 0; //stageW
private var m_nStageH:Number = 0; //stageH
private var m_nAdjustX:Number = 10; //余白x
private var m_nAdjustY:Number = 10; //余白y
private var m_nSize:Number = 5; //サイズ係数
private var m_nMoveY:Number = 0; //移動距離Y
private var m_nMoveCoef:Number = 0.1; //運動係数
private var m_uiColor:uint = 0xff009be2; //カラー(文字)
private var m_uiBackColor:uint = 0x00000000; //カラー(背景)
private var m_bColor:Boolean = false; //カラーフラグ
private var m_bSize:Boolean = false; //サイズフラグ
private var m_bBrownian:Boolean = false; //ブラウン運動フラグ
private var m_bTouch:Boolean = false; //MouseOverアクションフラグ
private var m_bParticle:Boolean = false; //particleフラグ(setpixelを使用)
/*###############################################
* CALL : BubbleType()
* FUNC : 泡みたいな文字を作成
* PARAM :
* RETURN : -
* NOTE : stage参照のためステージに配置後に処理
* ##############################################
* UPDATE : -
*///############################################
public function BubbleType(tfText:TextField)
{
//表示テキスト保持
m_tfText = tfText;
//stage配置後に初期処理
addEventListener(Event.ADDED_TO_STAGE, createBubbleWord);
}
/*###############################################
* CALL : init()
* FUNC : 初期設定
* PARAM : -
* RETURN : -
* NOTE : 1.stageW
* 2.stageH
* 3.余白x
* 4.余白y(基本的に7の2倍を設定)
* 5.基本サイズ
* 6.カラー(文字)
* 7.カラー(背景)
* 8.移動距離Y
* 9.運動係数
* 10.サイズフラグ
* 11.カラーフラグ
* 12.運動フラグ
* 13.MouseOverフラグ
* 14.Particleフラグ
* ##############################################
* UPDATE : -
*///############################################
public function init(nStageW:Number = 0,
nStageH:Number = 0,
nAdjustX:Number = 0,
nAdjustY:Number = 0,
nSize:Number = 5,
uiColor:uint = 0xff009be2,
uiBackColor:uint = 0x00000000,
nMoveY:Number = 0,
nMoveCoef:Number = 0.1,
bSize:Boolean = false,
bColor:Boolean = false,
bBrownian:Boolean = false,
bTouch:Boolean = false,
bParticle:Boolean = false):void
{
if ( nStageW > 0) { m_nStageW = nStageW; } else { m_nStageW = m_tfText.textWidth * nSize + nAdjustX; }
if ( nStageH > 0) { m_nStageH = nStageH; } else { m_nStageH = m_tfText.textHeight * nSize + nAdjustY; }
m_nAdjustX = nAdjustX;
m_nAdjustY = nAdjustY;
m_nSize = nSize;
m_uiColor = uiColor;
m_uiBackColor = uiBackColor;
m_nMoveY = nMoveY;
m_nMoveCoef = nMoveCoef;
m_bSize = bSize;
m_bColor = bColor;
m_bBrownian = bBrownian;
m_bTouch = bTouch;
m_bParticle = bParticle;
}
/*###############################################
* CALL : createBubbleWord()
* FUNC : BubbleWord生成
* PARAM : -
* RETURN : -
* NOTE : -
* ##############################################
* UPDATE : -
*///############################################
private function createBubbleWord(e:Event):void
{
//表示用のcanvasを生成
m_bmdCanvas = new BitmapData( m_nStageW, m_nStageH, true, m_uiBackColor);
addChild(new Bitmap(m_bmdCanvas));
//テキストの位置情報を取得
m_vbPixel = getTextPixel(m_tfText);
//位置情報からParticleを取得
m_vprtParticle = getTextParticle(m_tfText, m_vbPixel, 0, 0);
//描画イベントセット
addEventListener( Event.ENTER_FRAME, updateCanvas );
addEventListener( Event.ENTER_FRAME, updatePosition );
removeEventListener(Event.ADDED_TO_STAGE, init);
}
/*###############################################
* CALL : updateCanvas()
* FUNC : 描画更新
* PARAM : -
* RETURN : -
* NOTE : bitmapの描画を更新
* ##############################################
* UPDATE : -
*///############################################
private function updateCanvas(e:Event):void
{
var oParticle:Particle;
//ロック
m_bmdCanvas.lock();
//キャンバスクリア
m_bmdCanvas.fillRect(m_bmdCanvas.rect, m_uiBackColor);
//描画
var iLength:int = m_vprtParticle.length;
if (m_bParticle)
{
for (var i:int = 0; i < iLength; i++ )
{
oParticle = m_vprtParticle[i] as Particle;
//m_bmdCanvas.setPixel32(oParticle.x, oParticle.y, oParticle.color * Math.random());
m_bmdCanvas.setPixel32(oParticle.x, oParticle.y, oParticle.color);
}
}else {
for (var j:int = 0; j < iLength; j++ )
{
oParticle = m_vprtParticle[j] as Particle;
m_recFill.x = oParticle.x - oParticle.radius / 2;
m_recFill.y = oParticle.y - oParticle.radius / 2;
m_recFill.width = oParticle.radius;
m_recFill.height = oParticle.radius;
//m_bmdCanvas.fillRect(m_recFill, oParticle.color * Math.random());
m_bmdCanvas.fillRect(m_recFill, oParticle.color * Math.random());
}
}
//ロック解除
m_bmdCanvas.unlock();
}
/*###############################################
* CALL : updatePosition()
* FUNC : 座標更新
* PARAM : -
* RETURN : -
* NOTE : particleの座標を更新
* ##############################################
* UPDATE : -
*///############################################
private function updatePosition(e:Event):void
{
var iLength:int, oParticle:Particle;
iLength = m_vprtParticle.length;
for( var i:int = 0; i < iLength; i++ )
{
oParticle = m_vprtParticle[i] as Particle;
motionRise(oParticle);
//上昇時の動き
if (m_bBrownian)
{
motionBrownian(oParticle);
}
}
}
/*###############################################
* CALL : getTextPixel()
* FUNC : textのpixelを取得
* PARAM : tx:TextField
* RETURN : Vector.<Boolean>
* NOTE : 白以外のpixelの位置を取得
* 対象の箇所はtrue
* ##############################################
* UPDATE : -
*///############################################
private function getTextPixel(tx:TextField):Vector.<Boolean>
{
var nX:Number = 0, nY:Number = 0, uiColor:uint = 0, uiTxtColor:uint = 0;
var bmd:BitmapData, vbPixel:Vector.<Boolean>;
//テキストをbitmapdata化
//bmd = new BitmapData(tx.textWidth, tx.height, true);
bmd = new BitmapData(tx.width, tx.height, true);
bmd.draw(tx);
//対象ピクセルの塗情報を保持
vbPixel = new Vector.<Boolean>();
uiTxtColor = tx.textColor;
for (var i:int = 0; i < bmd.width * bmd.height; i++)
{
nX = (i % tx.textWidth) >> 0;
nY = (i / tx.textWidth) >> 0;
uiColor = bmd.getPixel(nX, nY);
if (uiColor == uiTxtColor)
{
vbPixel.push(true);
}else {
vbPixel.push(false);
}
}
return vbPixel;
}
/*###############################################
* CALL : getTextParticle()
* FUNC : pixelの位置情報からparticleを生成
* PARAM : tx:TextField
* vbPixel:Vector.<Boolean>
* nAdjustX:Number = 0/座標X
* nAdjustY:Number = 0/座標Y
* RETURN : Vector.<Particle>
* NOTE : pixelの位置情報からparticleを生成
* ##############################################
* UPDATE : -
*///############################################
private function getTextParticle(tx:TextField,vbPixel:Vector.<Boolean>,nAdjustX:Number = 0,nAdjustY:Number = 0):Vector.<Particle>
{
//取得した位置情報を元にParticleを生成
var bFill:Boolean, nX:Number, nY:Number, nRandomSize:Number, vprtParticle:Vector.<Particle>;
vprtParticle = new Vector.<Particle>();
//Targetの座標がtrueならParticleを生成
for (var j:int = 0; j < tx.textWidth * tx.textHeight; j++)
{
nX = (j%tx.textWidth) >> 0;
nY = (j/tx.textWidth) >> 0;
bFill = m_vbPixel[j] as Boolean;
if (bFill == true)
{
var oParticle:Particle;
nRandomSize = Math.random() * m_nSize + m_nSize / 3;
oParticle = new Particle();
oParticle.x = nX * m_nSize + m_nAdjustX / 2;
oParticle.y = nY * m_nSize + m_nAdjustY / 2;
//サイズ
if (m_bSize)
{
oParticle.radius = m_nSize;
}else {
oParticle.radius = nRandomSize;
}
oParticle.defX = nX * m_nSize + m_nAdjustX/2;
oParticle.defY = nY * m_nSize + m_nAdjustY/2;
oParticle.defRadius = m_nSize;
//カラー
if (m_bColor)
{
oParticle.color = m_uiColor;
}else {
oParticle.color = 0xff << 24 | (m_uiColor << 8) * Math.random() | m_uiColor;
}
oParticle.buoyancy = getBuoyancy(nRandomSize);
oParticle.distanceY = m_nMoveY;
vprtParticle.push(oParticle);
}
}
return vprtParticle;
}
/*###############################################
* CALL : getBuoyancy()
* FUNC : 浮力を取得
* PARAM : -
* RETURN : nBuoyancy/Number:浮力
* NOTE : 大きさに比例する浮力を取得
* ##############################################
* UPDATE : -
*///############################################
private function getBuoyancy(nCoef:Number):Number
{
var nBuoyancy:Number = 0;
nBuoyancy = nCoef * BUOY_COEF;
return nBuoyancy;
}
/*###############################################
* CALL : motionRise()
* FUNC : 上昇運動
* PARAM : oPaticle/particle
* NOTE : -
* ##############################################
* UPDATE : -
*///############################################
private function motionRise(oParticle:Particle):void
{
if (oParticle.distanceY > 0)
{
oParticle.y -= oParticle.buoyancy;
oParticle.distanceY -= oParticle.buoyancy;
}
}
/*###############################################
* CALL : motionBrownian()
* FUNC : ブラウン運動
* PARAM : oPaticle/particle
* NOTE : -
* ##############################################
* UPDATE : -
*///############################################
private function motionBrownian(oPaticle:Particle):void
{
var nMoveLenge:Number = m_nMoveCoef;
//目標点に達したら動きを変更
if (oPaticle.distanceY <= 0)
{
//signwave
motionSignWave(oPaticle);
return;
}
oPaticle.vx += Math.random() * m_nMoveCoef * 2 - m_nMoveCoef;
oPaticle.vx *= FRIC_COEF;
oPaticle.x += oPaticle.vx;
}
/*###############################################
* CALL : motionSignWave()
* FUNC : signwave
* PARAM : oPaticle/particle
* NOTE : 回転の更新の際の計算では係数1がベスト
* ##############################################
* UPDATE : -
*///############################################
private function motionSignWave(oPaticle:Particle):void
{
oPaticle.radian += oPaticle.radius;
var nWave:Number = Math.sin(oPaticle.radian * PI / 180);
nWave *= m_nMoveCoef * 10;
oPaticle.y += nWave;
}
}
class Particle
{
private var m_nX:Number =0; // x
private var m_nY:Number =0; // y
private var m_nVx:Number =0; // 速度x
private var m_nVy:Number = 0; // 速度y
private var m_nAx:Number =0; // 加速度x
private var m_nAy:Number = 0; // 加速度y
private var m_nRadius:Number = 0; // 半径
private var m_nDefX:Number =0; // x(Def)
private var m_nDefY:Number =0; // y(Def)
private var m_nDefRadius:Number = 0; // 半径(Def)
private var m_nMass:Number = 0; // 質量
private var m_nBuoyancy:Number = 0; // 浮力
private var m_nDistanceY:Number = 0; // 目標地点までの距離
private var m_uiColor:uint = 0; // カラー
private var m_nRadian:uint = 0; // 回転
private var m_nNo:uint = 0; // No
private var m_bComplete:Boolean = false; // 動作完了フラグ
public function Particle( x:Number = 0, y:Number = 0, radius:Number = 1 ,color:uint = 0x000000)
{
this.m_nX = x;
this.m_nY = y;
this.m_nRadius = radius;
this.m_nDefX = x;
this.m_nDefY = y;
this.m_nDefRadius = radius;
this.m_uiColor = color;
}
/*######################################################
* property
*///####################################################
//setter
public function set x(nx:Number):void { m_nX = nx; }
public function set y(ny:Number):void { m_nY = ny; }
public function set vx(nVx:Number):void { m_nVx = nVx; }
public function set vy(nVy:Number):void { m_nVy = nVy; }
public function set ax(nAx:Number):void { m_nAx = nAx; }
public function set ay(nAy:Number):void { m_nAy = nAy; }
public function set mass(nMass:Number):void { m_nMass = nMass; }
public function set buoyancy(nBuoyancy:Number):void { m_nBuoyancy = nBuoyancy; }
public function set distanceY(nDistanceY:Number):void { m_nDistanceY = nDistanceY; }
public function set radius(nRadius:Number):void { m_nRadius = nRadius; }
public function set defX(nx:Number):void { m_nDefX = nx; }
public function set defY(ny:Number):void { m_nDefY = ny; }
public function set defRadius(nRadius:Number):void { m_nDefRadius = nRadius; }
public function set color(uiColor:uint):void { m_uiColor = uiColor; }
public function set radian(nRadian:uint):void { m_nRadian = nRadian; }
public function set no(nNo:Number):void { m_nNo = nNo; }
public function set complete(bComplete:Boolean):void { m_bComplete = bComplete; }
//getter
public function get x():Number { return m_nX; }
public function get y():Number { return m_nY; }
public function get vx():Number { return m_nVx; }
public function get vy():Number { return m_nVy; }
public function get ax():Number { return m_nAx; }
public function get ay():Number { return m_nAy; }
public function get mass():Number { return m_nMass; }
public function get buoyancy():Number { return m_nBuoyancy; }
public function get distanceY():Number { return m_nDistanceY; }
public function get radius():Number { return m_nRadius; }
public function get defX():Number { return m_nDefX; }
public function get defY():Number { return m_nDefY; }
public function get defRadius():Number { return m_nDefRadius; }
public function get color():uint { return m_uiColor; }
public function get radian():uint { return m_nRadian; }
public function get no():Number { return m_nNo; }
public function get complete():Boolean {return m_bComplete; }
}