POPSブログ

逆渦曲線で分解した文字を動かす

95

  Category:  as32012/04/25 pops 

逆渦曲線で分解した文字を動かすテストです、ばらばらのようで規則性のある動きです。完全な完成形ではありません。


逆渦曲線で分解した文字を動かす

直線で動かすのは、容易ですがサイン曲線でも無いような動きがほしいので、逆渦曲線を使用して見ました。大変にぎやかです。
これは以下の記事のコードをを引用しました。但しTimer形式のコードでしたので、onEnterFrame形式にして大幅に書き換えてはいます。INのものだけです。


【参考.引用】wonderfl記事: 渦を描いてみる

下記「逆渦を描いてみる」の記事URLが不明ですので、ASファイルを表示します。当方の控えで書き込みあり。

【参考.引用】wonderfl記事: 逆渦を描いてみる(ASファイル)



注意、テスト的なものですので完全では在りません。ご了承ください。螺旋状のアニメの場合少々早くなるようには工夫しています。限りなく近づくが完全にはいつまでたっても合致することが無い処理ですから、いい加減なところで打ち切ります。
中の文字も回転可能ですが、回転させないほうが良いような気がします。


AS3

FlashTest192b.as


//動く文字表示テスト
//Spiral渦巻
//FlashTest192b

package
{

	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.geom.*;
	import flash.system.*;
	import flash.utils.*;
	import flash.text.*;
	
	//TweenLite
	import com.greensock.*; 
	import com.greensock.easing.*;
	
	//虹色用
	import frocessing.color.ColorHSV;
	
	[SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]

	public class FlashTest192b extends Sprite {
		
		//layer container
		private var container:Sprite;
		//TEXT
		private var tf:TextField;
		private var tf2:TextField;
		//BTN
		private var btn_1:Sprite;
		private var btn_2:Sprite;
		//BIG-MOVE-TEXT-1
		private var mvlinetext1:String;
		private var txline1:int;
		//格納容器1
		private var sps1:Array = [];//要素Sprite格納容器
		private var cxs1:Array = [];//X位置格納容器
		private var cys1:Array = [];//Y位置格納容器
		
		//グローバルカウント
		private var gl_count:int = 0;
		
		//巻数Num
		private var angleNum:uint = 6;// 1以下にすると直線になるので 1以上
		//巻形の係数Facter
		private var radianNum:Number = 1.02;// 1にすると円になる/いまは1.01-1.02の間
		//最大半径//渦サイズ固定 200-400
		private var spiralRadiusMax:Number = 300;
		//渦の初期サイズを設定
		private var spiralRadius:Number;
		//spiral_ball格納容器
		private var spiral_balls:Array = [];
		//螺旋回転数/Number of revolutions
		private var revolution:Number = 2;
		//文字の回転/大体3で1回転 0 3 -3
		private var rot_v:Number = 0;
		
		public function FlashTest192b():void
		{
			//goto-init
			init();
		}
		
		// INIT
		private function init():void {	
			
			//ステージ
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.HIGH;
			
			//BASE/黒背景
			var square:Sprite = new Sprite();
			square.graphics.beginFill(0x000000);//0x000000
			square.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			square.graphics.endFill();
			addChild(square);
							
			//text
			tf = createTextField(10, 5, stage.stageWidth - 20, 20);
			tf.textColor = 0xFFFFFF;
			tf.text = "";
			addChild(tf);
			//text2
			tf2 = createTextField(10, 445, stage.stageWidth - 20, 20);
			tf2.textColor = 0xFF0000;
			tf2.text = "螺旋は時間がかかります(最後が長い)、簡易もどきは時間がかかりません";
			addChild(tf2);
						
			//特殊用途container
			container=createSquare(0, 0, stage.stageWidth, 10, 0x000000, 0);
			addChild(container);
			container.x = 20;
			container.y = 200;
			
			//BTN-1/アニメIN実行
			btn_1 = createRoundBTN("簡易アニメ", 13, 0x000000, 60, 20, 0xFF69B4, 1, 5);
			btn_1.x = 420;
			btn_1.y = 25;//40
			addChild(btn_1);
			//btn_1にListenerを設定
			btn_1.addEventListener( MouseEvent.CLICK, animate2 );
			
			//BTN-1/アニメIN実行
			btn_2 = createRoundBTN("螺旋アニメ", 13, 0x000000, 60, 20, 0xFF9E8C, 1, 5);
			btn_2.x = 350;
			btn_2.y = 25;//40
			addChild(btn_2);
			//btn_2にListenerを設定
			btn_2.addEventListener( MouseEvent.CLICK, animate );
			
			//テキスト作成に進む
			make_MaskText();
			
		}

		//グラデマスクテキスト MASK-TEXT
		private function make_MaskText():void {
			
			tf.text = "文字表示、ボタンを押してください";
			//表示文字列
			mvlinetext1 = "SlideShow";
			//tf.text = "[ _sansでも使用できるように改造 文字の渦運動テスト]";
			mvlinetext1 = "Popsweb.SlideShow";//wonderfl.SlideShow
			//textColor
			var mvtextColor:uint = 0xFFFFFF;
			//length
			txline1 = mvlinetext1.length;
			
			//classで文字を作る
			var box1_v:MakeTextLine = new MakeTextLine(
					mvlinetext1,			// String 全ての文字
					mvtextColor,			// uint 0xFFFFFF 文字色自由
					50,						// Number 60 文字サイズ自由
					'rainbow',				// String normal random rainbow 色指定
					'none',					// String mask none グラデーションマスク
					'_sans',				// String Embed-fontName font _sans arial _ゴシック
					-4,						// Number Space -4は引いてあるので差を入力
					false					// embedFonts true false embed文字使用の場合true
			);
				
			//class配列を取り込む
			sps1 = box1_v.txsBoxArrays;//Sprite
			cxs1 = box1_v.cxsArrays;//x位置
			cys1 = box1_v.cysArrays;//y位置
			
			var i:int = 0;
			for (i = 0; i < txline1; i++) {
				
				//文字列位置確定
				sps1[i].x = cxs1[i];//stage.stageWidth
				sps1[i].y = cys1[i];
				//zの指定/embed文字使用の場合は何も書かないこと
				//_sansを使用するためzの指定
				sps1[i].z = 0;
				
				//SpiralBallクラス生成
				var ball:SpiralBall = new SpiralBall();
				spiral_balls[i] = ball;
				
				//containerに入れた
				ball.addChild(sps1[i]);
				container.addChild(ball);
				
			}
		}
		
		//animate1/正式な螺旋曲線/遅いので使い難い
		private function animate( e:MouseEvent = null ):void {
			
			tf.text = "Spiral曲線 アニメ実行中です";
			
			//ボタン非表示/アニメ途中おされるとくるう
			btn_1.visible = false;
			btn_2.visible = false;
			
			//delay番号ランダム値
			var delay_no:int = Math.floor(Math.random()*4);
			//delay計算
			var delay_total:Number = txline1 * 0.3;
			var txline_mv:Number = (txline1 - 1) / 2;//中央値
			//中外の場合加算する数値
			var d_chg_v:Number = Math.floor(Math.random() * 4 ) * 0.25;
			//
			gl_count = 0;//グローバルカウント
			
			var i:int = 0;
			for (i = 0; i < txline1; i++) {
				//中の文字位置を00にセットする位置情報は外のspiral_ballsに設定した
				sps1[i].x = 0;
				sps1[i].y = 0;
				//容器位置の条件をセットする
				spiralMake();
				
				//delay/delay値の変化/中外4種類
				var delay_v:Number = i * 0.3;//左
				if (delay_no == 1) { delay_v = delay_total - i * 0.3; }//右
				if (delay_no == 2) { delay_v = Math.abs((i + d_chg_v) - txline_mv)*0.3; }//中
				if (delay_no == 3) { delay_v = (delay_total / 2) - Math.abs((i + d_chg_v) - txline_mv) * 0.3; }//外
				
				//遅延させるTweenMax/delayだけが目的
				var myTween:TweenLite = new TweenLite(spiral_balls[i],0,{delay:delay_v, onComplete:st_onComplete,onCompleteParams:[i]});
				//
			}
		}

		//animate2/簡易螺旋もどき、正式な螺旋ではないが早い
		private function animate2( e:MouseEvent = null ):void {
			
			tf.text = "簡易Spiral曲線 アニメ実行中です";
			
			//ボタン非表示/アニメ途中おされるとくるう
			btn_1.visible = false;
			btn_2.visible = false;
			
			//delay番号ランダム値
			var delay_no:int = Math.floor(Math.random()*4);
			//delay計算
			var delay_total:Number = txline1 * 0.3;
			var txline_mv:Number = (txline1 - 1) / 2;//中央値
			//中外の場合加算する数値
			var d_chg_v:Number = Math.floor(Math.random() * 4 ) * 0.25;
			//
			gl_count = 0;//グローバルカウント
			
			var i:int = 0;
			for (i = 0; i < txline1; i++) {
				//中の文字位置を00にセットする位置情報は外のspiral_ballsに設定した
				sps1[i].x = 0;
				sps1[i].y = 0;
				//容器位置の条件をセットする
				spiralMake();
				
				//delay/delay値の変化/中外4種類
				var delay_v:Number = i * 0.3;//左
				if (delay_no == 1) { delay_v = delay_total - i * 0.3; }//右
				if (delay_no == 2) { delay_v = Math.abs((i + d_chg_v) - txline_mv)*0.3; }//中
				if (delay_no == 3) { delay_v = (delay_total / 2) - Math.abs((i + d_chg_v) - txline_mv) * 0.3; }//外
				
				//遅延させるTweenMax/delayだけが目的
				var myTween:TweenLite = new TweenLite(spiral_balls[i],0,{delay:delay_v, onComplete:sp_onComplete,onCompleteParams:[i]});
				//
			}
		}
		//渦巻きを描く処理
		public function spiralMake():void {
			
			//渦の初期サイズを設定/中に向かうのでspiralRadiusMaxと同じ
			spiralRadius = spiralRadiusMax;
			
			var i:int = 0;
			for (i = 0; i < txline1; i++) {
				
				//渦の係数(渦の回数)1以上であること、1以下は直線になる 1-2
				//大体の巻く数である、途中止めないと無限にちかずくだけ
				angleNum = 2;//1-2
				var angle:Number = int(Math.random() * 36)*10;//ランダムな角度の位置から
				var radian:Number = 0;
				//文字の位置を代入
				var pointX:Number = cxs1[i];//mouseX;
				var pointY:Number = cys1[i];//mouseY;
				//回転方向 0=左 1=右
				var direction:int = int(Math.random() * 2);
				//逆転係数、通常は使用しない
				var chgFlag:Number = 1;
				//chgFlagを使用する場合は-1を与える、directionを使用しない
				if (!direction) { chgFlag = -1; }
				
				//spiral_ballsに変数をセットする
				//番号
				spiral_balls[i].ball_no = i;
				//大きさ
				spiral_balls[i].spiralRadiusMax = spiralRadiusMax;
				spiral_balls[i].spiralRadius = spiralRadiusMax;
				spiral_balls[i].angleNum = angleNum;
				//pointXをMCの配置位置にすれば、そこにそろうことになる
				spiral_balls[i].pointX = pointX;
				spiral_balls[i].pointY = pointY;
				spiral_balls[i].angle = angle;
				spiral_balls[i].radian = radian;
				spiral_balls[i].radianNum = radianNum;
				spiral_balls[i].direction = direction;
				//逆転フラグ、通常は使用しない
				spiral_balls[i].chgFlag = chgFlag;
				
				//遠くにあったほうが見た目よし
				spiral_balls[i].x = 0;
				spiral_balls[i].y = -500;
				
			}
		}
		
		//TweenLite-onComplete IN 1
		private function st_onComplete(param1:int):void {
			//delayの順にonEnterFrame処理
			spiral_balls[param1].addEventListener(Event.ENTER_FRAME, onEnterFrame_st);
		}
		//TweenLite-onComplete IN 2
		private function sp_onComplete(param1:int):void {
			//delayの順にonEnterFrame処理
			spiral_balls[param1].addEventListener(Event.ENTER_FRAME, onEnterFrame_spiral2);
		}
		
		//ball onEnterFrame In 1
		private function onEnterFrame_st(e:Event):void {
			//
			//as SpiralBallで問題なくコンパイル
			var mv_ball:SpiralBall = e.currentTarget as SpiralBall;
			//ボール回転大体の値
			sps1[mv_ball.ball_no].rotation += rot_v;
			
			if (0 < mv_ball.spiralRadius) {
				//ラジアンに変換/回転数revolutionを乗算した
				mv_ball.radian = revolution * Math.PI * mv_ball.angle / 180;//かならずここで処理
				//次のポイントをめざす
				mv_ball.x = mv_ball.pointX + mv_ball.spiralRadius * Math.cos(mv_ball.radian);//*1.5
				mv_ball.y = mv_ball.pointY + mv_ball.spiralRadius * Math.sin(mv_ball.radian);//*1.5
				//角度をマイナスする/角度をプラスする
				if (!mv_ball.direction) {mv_ball.angle -= mv_ball.angleNum;}
				else {mv_ball.angle += mv_ball.angleNum;}
				//新しい半径を求める/いつまでも処理がつづくからきっちりするよう整数化
				mv_ball.spiralRadius /= mv_ball.radianNum;//最後まで0にはならない
				mv_ball.spiralRadius = Math.floor(mv_ball.spiralRadius);
			}
			//終了
			//半径が1になったら処理停止/いつまでも処理がつづくから強制的に終了させる 1-5
			if (mv_ball.spiralRadius <= 1) {
				//グローバルカウント/反転するとカウントが正確でないのでこちらで判定
				gl_count ++;
				sps1[mv_ball.ball_no].rotation = 0;
				//処理終了
				mv_ball.spiralRadius = 0;
				//pointXYに強制移動
				mv_ball.x = mv_ball.pointX;
				mv_ball.y = mv_ball.pointY;
				//removeEventListener
				mv_ball.removeEventListener(Event.ENTER_FRAME, onEnterFrame_st);
				if (gl_count == txline1) { show_end(); }
			}
				
		}

		//ball onEnterFrame IN 2
		private function onEnterFrame_spiral2(e:Event):void {
			
			//通常より20%くらい早く終了する
			//上下運動が主/後半渦の性質
			var mv_ball:SpiralBall = e.currentTarget as SpiralBall;
			//ボール回転大体の値/1.2で修正
			sps1[mv_ball.ball_no].rotation += rot_v * 1.2;
			//
			mv_ball.x = mv_ball.pointX + mv_ball.spiralRadius * Math.sin(mv_ball.radian / 2);//X幅は半分になる
			//mv_ball.y = mv_ball.pointY + mv_ball.spiralRadius * Math.cos(mv_ball.radian/2);Y幅は半分になる
			//yはこちらのほうが動きがあって面白い
			mv_ball.y = mv_ball.pointY + mv_ball.spiralRadius * Math.cos(mv_ball.radian);
			mv_ball.radian = Math.PI * mv_ball.angle / 180;
			mv_ball.angle -= 4 * mv_ball.chgFlag;
			//定数で距離を減算
			mv_ball.spiralRadius -= 3;
			
			//終了
			if (mv_ball.spiralRadius <= 1) {
				//中回転を戻す
				sps1[mv_ball.ball_no].rotation = 0;
				//グローバルカウント/反転するとカウントが正確でないのでこちらで判定
				gl_count ++;
				//処理終了
				//pointXYに強制移動
				mv_ball.x = mv_ball.pointX;
				mv_ball.y = mv_ball.pointY;
				//removeEventListener
				mv_ball.removeEventListener(Event.ENTER_FRAME, onEnterFrame_spiral2);
				if (gl_count == txline1) { show_end(); }
			}
		}

		//Finish終了処理
		private function show_end():void {
			//
			gl_count = 0;
			//ボタン表示
			btn_1.visible = true;
			btn_2.visible = true;
			
			tf.text = "Spiral曲線 アニメ ボタンを押してください";
		}
		
		//-------------------------------------------------------
		//create-box
		private function createSquare(x:Number, y:Number, width:Number, height:Number, color:Number, alpha:Number):Sprite {
			var s:Sprite = new Sprite();
			s.graphics.beginFill(color, alpha);
			s.graphics.drawRect(x, y, width, height);
			s.graphics.endFill();
			//addChild(s);
			return s;
		}
		//create-text
		private function createTextField(x:Number, y:Number, width:Number, height:Number):TextField {
			var result:TextField = new TextField();
			result.x = x;
			result.y = y;
			result.width = width;
			result.height = height;
			//addChild(result);
			return result;
		}
		//create-RoundBTN/原点中央ボタンモードなど訂正
		private function createRoundBTN(text:String, t_size:int, t_color:uint, width:Number, height:Number, color:uint, alpha:Number, round:Number):Sprite {
			var rsbt:Sprite = new Sprite();
			rsbt.graphics.beginFill(color, alpha);
			rsbt.graphics.drawRoundRect(-width/2, -height/2, width, height, round);
			rsbt.graphics.endFill();
			addChild(rsbt);
			var r:TextField = new TextField();
			var fmt:TextFormat = new TextFormat('_ゴシック', t_size, null, null, null, null, null, null, TextFormatAlign.CENTER );
			r.defaultTextFormat = fmt;
			r.textColor = t_color;
			r.selectable = false;
			//r.autoSize = TextFieldAutoSize.LEFT;
			r.text = text;
			r.width = width;
			r.height = height;
			r.x = -width / 2;
			r.y = -height / 2 + 2;
			r.mouseEnabled = false;
			//buttonMode
			rsbt.buttonMode = true;
			rsbt.addChild(r);
			return rsbt;
		}	
	}

}

//複数文字の グラデーションマスク クラス
import flash.display.*;
import flash.geom.*;
import flash.text.*;
import flash.system.*;
import flash.utils.*;
//虹色用
import frocessing.color.ColorHSV;

class MakeTextLine extends Sprite {
	//受け渡し配列変数
	public var txsBoxArrays:Array;
	public var cxsArrays:Array;
	public var cysArrays:Array;
	//変数
	private var tx:String;
	private var txs:String;
	private var color:uint;
	private var color_type:String;
	private var mask_type:String;
	private var font_name:String;
	private var font_size:Number;
	private var embed:Boolean;
	private var space:Number;
	private var space_v:Number = -4;
	private var len:Number;
	private var sps:Array;//要素Sprite格納容器
	
	public function MakeTextLine(_txs:String, _color:uint, _font_size:Number, _color_type:String, _mask_type:String, _font_name:String, _space:Number, _embed:Boolean = false):void {
		//変数の代入
		txs = _txs;
		color = _color;
		color_type = _color_type;
		mask_type = _mask_type;
		font_name = _font_name;
		font_size = _font_size;
		embed = _embed;
		space = _space;
		
		//受け渡し配列変数クリア
		txsBoxArrays = [];
		cxsArrays = [];
		cysArrays = [];
		sps = [];
		//作成
		maskText();
	}
	private function maskText():void {
		
			var mvlinetext:String = txs;
			var txline:int;
			var mvtext_pX:Number = 0;//先頭文字位置調整用
			var mvtext_pY:Number = 0;//先頭文字位置調整用
			var mvtext_len:Number = 0;//字位置調整用
			var cx:Number = 0;
			var cy:Number = 0;
			var cxs:Array = [];
			var cys:Array = [];
			var spase_t:Number = space_v + space;//文字間のスペース
			//length
			txline = mvlinetext.length;
			//1=虹色にそめる 0=指定色 2=ランダム色にそめるrandom rainbow 
			var rainbow_colored:int = 0;
			if (color_type == 'rainbow') {rainbow_colored = 1;}
			if (color_type == 'random') {rainbow_colored = 2;}
			//基本textColor
			var mvtextColor:uint = color;
			//虹色にそめる変数
			var nAngle:Number = Math.PI * 2 / txline;
			var cAngle:Number = 0;
			
			for (var i:int = 0; i < txline; i++) {
				//虹色にそめる
				if (rainbow_colored == 1) {
					//frocessingで虹色を求める
					var hsv:ColorHSV = new ColorHSV(0, 1, 1, 1);
					hsv.h = cAngle / Math.PI * 180;
					//虹色を取得受け渡す
					mvtextColor = hsv.value;
					cAngle += nAngle;
				}
				//ランダム色に染める/問題あるときはランダム色
				if (rainbow_colored > 1) {
					//ランダム色
					mvtextColor = 0xFFFFFF * Math.random();//random
				}
				//文字を作る
				var mvtext_sp:Sprite = maskBox(mvlinetext.charAt(i), mvtextColor, font_size, mask_type, font_name, embed);
				//表示位置決定のため半分の間隔をプラスする、中心補正
				mvtext_len += mvtext_sp.width / 2;//文字間補正1
				//位置確定
				cxs[i] = cx = mvtext_pX + mvtext_len;//
				cys[i] = cy = 0;
				//出来上がった文字BOX、mvtext_spを保存
				sps[i] = mvtext_sp;
				//次の文字位置のため、最後に現在文字の半分の間隔をプラスする
				mvtext_len += (mvtext_sp.width / 2) + spase_t;
			}
			
			//配列を受け渡し配列に代入
			txsBoxArrays = sps;
			cxsArrays = cxs;
			cysArrays = cys;

	}
	private function maskBox(tx:String, color:uint, font_size:Number, mask_type:String, font_name:String, embed:Boolean):Sprite {
		//maskBox
		var result:TextField = new TextField();
		var fmt:TextFormat = new TextFormat();
		//CENTERにするとスペースがなくなる
		fmt.size = font_size;//60
		fmt.font = font_name;
		fmt.rightMargin = 0;
		fmt.leftMargin = 0;
		result.defaultTextFormat = fmt;
		result.text = tx;
		result.autoSize = TextFieldAutoSize.LEFT;//LEFT autoSizeでなければならない
		result.textColor = color;
		result.background = false;
		result.embedFonts = embed;
		//result.condenseWhite = false;//HTMLの場合有効
		result.selectable = false;
		//中心補正
		result.x = -result.width / 2;
		result.y = -result.height / 2;
		//基盤Spriteを作る
		var _text_sp:Sprite = new Sprite();
		
		//マスク処理
		if (mask_type=='mask') {
			//MASK/ShapeでもSpriteでもどちらでもOKのようだ
			var text_mask:Shape = new Shape();	
			//MASK,マスク透過グラデを作る
			var mtx:Matrix = new Matrix();
			mtx.createGradientBox(result.width, result.height, 0, 0, 0);
			//ずらした
			text_mask.graphics.beginGradientFill(
				GradientType.LINEAR,
				[0x00, 0x00],
				[1, 0],
				[50, 240],//[0, 255]
				mtx
			);
			text_mask.graphics.drawRect(0, 0, result.width, result.height);
			
			//マスク中心補正
			text_mask.x = -result.width / 2;
			text_mask.y = -result.height / 2;
			//マスクChildは必要
			_text_sp.addChild(text_mask);
			//グラデマスク実行 TextFieldに直接実行してもOK
			result.mask = text_mask;
			//cacheAs
			result.cacheAsBitmap = true;
			text_mask.cacheAsBitmap = true;
		}
		//Child
		_text_sp.addChild(result);
		//重要
		addChild(_text_sp);
		return _text_sp;
	}
}

//SpiralBall巻形運動クラス
import flash.display.Sprite;
class SpiralBall extends Sprite {
	//番号カウント
	public var ball_no:int;
	public var count_no:int;
	//巻形
	public var angleNum:uint;
	//巻形の係数
	public var radianNum:Number;
	public var spiralRadiusMax:Number;
	//渦の初期サイズを設定
	public var spiralRadius:Number;
	//渦線の太さを設定
	public var spiralLineSize:Number;
	//radian/位置
	public var radian:Number;
	public var pointX:Number;
	public var pointY:Number;
	public var angle:Number;
	//回転方向 0=左 1=右
	public var direction:int;
	//逆転係数
	public var chgFlag:Number = 1;

	public function SpiralBall() {
		var b:Sprite = new Sprite();
		//xy
		b.x = 0;
		b.y = 0;
		addChild(b);
	}
}


以上のように、大変長いものになります。面倒すぎる、よって個人的には使いたくない。


以上です。



[ この記事のURL ]


タグ:flash , ActionScript , as3

 

ブログ記事一覧

年別アーカイブ一覧



[1]