POPSブログ

CreateJS テキスト背景に図形を挿入して(MotionGuide Tween)テキストアニメーション

245

  Category:  javascript2013/09/05 pops 

テキスト背景にグラフィック図形を表示し、テキストを完全に中央位置に補正します。且つMotionGuidePluginを利用して複数の「ガイドパス登録」でテキストをMotionTweenさせます。途中でグラフィックを挿入(テキスト文字と入れ替え)して変化を演出します。
easeljs-0.7 でのテストです。

 

CreateJS テキスト背景に図形を挿入して(MotionGuide Tween)テキストアニメーションのテスト


2013/09/25/EaselJSなどバージョンUPされました(easeljs-0.7)。動作など確認してeaseljs-0.7用に更新しています。(2013/10/23)


前ページのものを改造しましたが、グラフィック図形の中心にテキストを配置しないとキレイになりませんので少々コツが必要です。また、ブラウザにより微妙にY位置が違うので修正の必要が有ります。漢字表示、英数字表示でもY位置が違って来る。前ページでは簡単に「背景の図形を入れて、、」などとは書きましたが、実際は「また難問」ですのでナントカ解決させます。


[説明図]

 

1. パスは6種類の中から選定出来ます。少々ですが動き(見た目)に違いが有ります。(デモ参照)
2. ガイドパスの、X軸、Y軸反転させていませんので簡単な作りです。
3. 正確なテキストの高さは取得出来ませんし、ブラウザにより表示位置(Y方向)もマチマチなので補正する必要がある。通常英数字、漢字でも表示位置の違いがあるのでこれも補正しなければなりません。
4. 漢字の使用も出来ますが、一応、文字の種類は Arial 専用です。
5. そこで色々とテストして、簡単で正確な補正方法を探りました。


DEMO


CreateJS テキスト背景に図形を挿入して(MotionGuide Tween)テキストアニメーション例 (createJS034.js)

このページはHTML5では有りませんので、デモページでご覧ください。「IE7.8」ではご覧いただけません。
/// 注意、ブラウザ、マシン性能により描画品質などに大きな差が有ります事了承下さい ///


Chrome Firefox Safari(Win) IE9、で動作確認済み。 Safari(Mac)、IE10、は未確認です。


 

HTML JS CSS


使用するライブラリ

easeljs preloadjs tweenjs

配布元 : CreateJS createjs.com


ライブラリの読み込み

ダウンロードしたJSを使用する場合。記述は一例です。(バージョン 0.7.0 使用)


<script type="text/javascript" src="js/easeljs-0.7.0.min.js"></script>
<script type="text/javascript" src="js/tweenjs-0.5.0.min.js"></script>

重要、バージョン違いでは動かない場合が有りますので必ず合わせて下さい。このデモでは preloadjs を使用していません。


HTML (HTML5)


<div id="demo-wrap">
	<div id="image-box" class="radius"><canvas id="mainCanvas" width="640" height="300"></canvas></div>
</div>

JS

createJS034.js、JS名は任意に変更可。easeljs-0.7用


//日本語
//createJS034.js
//スペース補正形TEXT MotionGuideアニメーション
//easeljs-0.7用
//rainbow-Color

//------------------------------------------------------
//Browser判定
var userAgent = window.navigator.userAgent.toLowerCase();
var safari=false,chrome=false,firefox=false,opera=false;
var ie=false;
var browser_v;
if (/*@cc_on!@*/false) {
	ie=true;
	if (navigator.userAgent.match(/MSIE (¥d¥.¥d+)/)) {browser_v = parseFloat(RegExp.$1);}//IE6.7.8.9.10
}
if (userAgent.indexOf("safari") > -1) {safari=true;}
if (userAgent.indexOf("chrome") > -1) {chrome=true;}
if (userAgent.indexOf("firefox") > -1) {firefox=true;}
if (userAgent.indexOf("opera") > -1) {opera=true;}
//------------------------------------------------------

//初期設定
//canvasの大きさ/全てこの値を使用
var canvasWidth=640;
var canvasHeight=300;

//英数漢字判別補正するArialで漢字を使う事
//var basestring="POPS WEB KOUBOU";
var basestring="龍角散も世界遺産にしよう!";
//var basestring="赤マムシ生タマゴを世界遺産に!";

//BASE-TEXT
//コンテナ高さ、幅中央に自動修正
var basecontna_H=150;
//rainbow虹色にする true false
var rainbowSet3=true;
//ベース指定色rainbowSet3がfalseの場合有効
var base_color="#FF1493";
//文字指定色
var basetext_color="#FFFFFF";//#FFFFFF

//出現間隔
var base_time3=400;
//交互遅延
var delayed_time3=1000;
//Tween速度 2000-3000
var speed3=2000;

//ガイド設定 ガイド幅高さ
var guide_w3=500;//原則文字の幅より大きい方が良い
var guide_h3=-150;//0 から -200位
var keepguide_w3=guide_w3;
var keepguide_h3=guide_h3;

//パスの種類指定 0-5
var pathdata3=0;
//上記6種をランダムに選ぶ true false
var pathRandom3=true;

//ポイント固定=0 移動=1 中央=2 画面ランダム=3 指定位置=4
var pointType3=0;
//上記5種をランダムに選ぶ true false
var patternRandom3=true;
//画面指定位置=4の場合のステージ内位置
var stagePoint_x3=320;
var stagePoint_y3=250;

//スケールデータ
var scaledata3=[0,0,0,0,.5,1,2,4];
var ball_num3=0;//未使用

//ランダムBallの指定色
var randomBall_color="#FFFFFF";


//左上方TEXTを有効にする true false
var textUse=true;

//------------------------------------------------------

//Plugin読み込み
createjs.MotionGuidePlugin.install();

//変数、未使用もあり
//ステージ
var stage;
//コンテナなど
var backrect;
var welcomecontainer;
var basetextcontainer;
//インスタンス
var welcomeImage;
var basetext;
//TEXT
var viewtext;

var textChip3=[];
//並び順のポジション保存
var textPosx3=[];
var textPosy3=[];
//MOVEポジション保存
var movePosx3=[];
var movePosy3=[];
//スケール保存
var keepScale3=0;
//回転保存
var keepRote3=0;
//alpha保存
var keepAlpha3=0;
//BASEテキスト用グローバル変数
var textmax3=0;
var textcount3=0;
//図形
var ballChip3=[];
var moveBallPosx3=[];
var moveBallPosy3=[];

//全て終了グローバル変数
var allcount=0;

//shadowフィルター
var shadow=new createjs.Shadow("#000000",0,0,4);
var shadow2=new createjs.Shadow("#FFFFFF",0,0,6);//影2

//------------------------------------------------------

//ステージ周りセット
function init() {

	//STAGE
	stage=new createjs.Stage('mainCanvas');
	//MouseOver設定/必要に応じ設定
	//stage.enableMouseOver(20);

	//バックRect/最下位色背景層、無くとも良い
	backrect=new createjs.Shape();
	backrect.graphics.beginFill("#555555").drawRect(0,0,canvasWidth,canvasHeight);
	stage.addChild(backrect);

	//BASE-TEXT
	basetextcontainer=new createjs.Container();
	//位置中央/あとで修正される
	basetextcontainer.x=canvasWidth/2;
	basetextcontainer.y=basecontna_H;
	stage.addChild(basetextcontainer);

	//簡易TEXT、Arialに変更
	viewtext=new createjs.Text("","12px Arial","#FFFFFF");
	viewtext.x=20;
	viewtext.y=15;
	viewtext.maxWidth=canvasWidth-40;
	viewtext.lineHeight=20;
	viewtext.textBaseline="bottom";
	viewtext.shadow=shadow;//SHADOW処理
	stage.addChild(viewtext);

	stage.update();

	createjs.Ticker.setFPS(30);
	createjs.Ticker.addEventListener('tick',tick);

	//調整
	setTimeout(function() {

		//プロローグ表示に進む
		set_prologue();

	},2000);

}

//プロローグ
function set_prologue() {

	set_text("START");

	//全て終了グローバル変数
	allcount=0;//クリア

	//調整
	setTimeout(function() {

		set_text("");
		//BASE-TEXT表示
		set_baseanime();

	},2000);

}

//BASEテキストアニメ
function set_baseanime() {

	textcount3=0;//カウント、グローバル

	textChip3=[];//クリア
	var basetext_W=0;//0
	var text_spc=4;//文字間隔
	var spc_width=10;//半角スペース幅
	var center=true;
	//図形の大きさ
	var base_width=30;
	var base_height=30;
	//文字サイズ
	var font_size="26px";//pxを付ける

	//スペース補正形コンテナ収容インスタンス配列取得 Arial専用
	//サイズ,フォント,ベース幅,ベース高さ,角丸半径,ベース色,虹色,文字間隔,半角スペース幅,文字色,文字
	textChip3=createMoveText3(font_size,"Arial",base_width,base_height,5,base_color,rainbowSet3,text_spc,spc_width,basetext_color,basestring);

	//スペースを除去した文字数
	var textlen3=textChip3.length;
	//テキスト用グローバル変数
	textmax3=textlen3;

	//全幅の計算を先に計算/文字間の距離プラス図形幅
	basetext_W =textChip3[textlen3-1].x-textChip3[0].x+base_width;

	//コンテナ中央補正
	if (center) {basetextcontainer.x=(canvasWidth-basetext_W)/2;}

	//BALL番号、ランダムのみ
	var ballno3=Math.floor(Math.random()*6);

	//ランダムBALLインスタンスを作る
	for (var i=0; i < textlen3; i++) {

		//ランダムBallインスタンス/色randomBall_color
		if (ballno3 == 0) {
			//(w,h,r,color,rainbow,len,no)/w,hは範囲 50x50-100x100
			ballChip3[i]=createRandomBall(80,80,2,randomBall_color,false,textlen3,i);
		}
		//ランダムRingインスタンス
		if (ballno3 == 1) {
			//(w,h,r,color,rainbow,len,no)/w,hは範囲 50x50-100x100
			ballChip3[i]=createRandomRing(80,80,3,randomBall_color,false,textlen3,i);
		}
		//ランダムRectインスタンス
		if (ballno3 == 2) {
			ballChip3[i]=createRandomRect(80,80,3,randomBall_color,false,textlen3,i);
		}
		//ランダムStar3インスタンス
		if (ballno3 == 3) {
			//(w,h,r,星の分割数,color,rainbow,len,no)/w,hは範囲 50x50-100x100
			ballChip3[i]=createRandomStars(80,80,4,3,randomBall_color,false,textlen3,i);
		}
		//ランダムStar4インスタンス
		if (ballno3 == 4) {
			ballChip3[i]=createRandomStars(80,80,4,4,randomBall_color,false,textlen3,i);
		}
		//ランダムStar5インスタンス
		if (ballno3 == 5) {
			ballChip3[i]=createRandomStars(80,80,4,5,randomBall_color,false,textlen3,i);
		}

		//ID
		ballChip3[i].id=i;

		//TEXTが半角スペースの場所はgraphics.clear()/非表示
		if(textChip3[i].text == ' ') {ballChip3[i].getChildAt(0).graphics.clear();}

		//陰影はつけていない
		//ballChip3[i].shadow=shadow2;
		//ランダム位置ポジション保存
		//globalToLocal
		var point=basetextcontainer.globalToLocal(Math.random()*canvasWidth,Math.random()*canvasHeight);
		moveBallPosx3[i]=point.x;
		moveBallPosy3[i]=point.y;

	}

	//パスのランダム選定/6種
	var path_no=Math.floor(Math.random()*6);
	if (pathRandom3) {
		pathdata3=path_no;
	}

	//パターン番号
	var pattern_no=Math.floor(Math.random()*5);
	//パターン番号 ポイント固定=0 移動=1 中央=2 画面ランダム=3 指定位置=4
	var pointtype_no=pointType3;
	if (patternRandom3) {
		//ランダム指定
		pointtype_no=pattern_no;
	}

	//遅延保存
	var delay_st=[];
	//多目的判定用フラグ/未使用もあり
	var chgxyflag=Math.floor(Math.random()*5);
	//多目的用2
	var chgflag=Math.floor(Math.random()*3);
	var chgflag2=Math.floor(Math.random()*3);
	var chgflag3=Math.floor(Math.random()*3);//ガイド用
	//逆転フラグ
	var chg_v=Math.floor(Math.random()*2);
	if (chg_v < 1) {chg_v=-1;}

	//delay番号
	var delay_no=Math.floor(Math.random()*4);

	//回転
	var rotate_no=(chgflag-1)*360;//正逆、なし
	//スケール
	var scls=scaledata3[Math.floor(Math.random()*scaledata3.length)];

	//alphaの調整
	var alpha_no=0;
	if (scls < 0.2) {alpha_no=1;}

	var sh=textlen3-1;
	var k=0;
	var flag=-1;

	for (var i=0; i < textlen3; i++) {

		//ID
		textChip3[i].id=i;
		//addChild
		basetextcontainer.addChild(textChip3[i]);

		//ポジション取得
		textPosx3[i]=textChip3[i].x;
		textPosy3[i]=textChip3[i].y;

		//ポイント固定
		if (pointtype_no == 0) {
			textChip3[i].x=guide_w3;
			textChip3[i].y=guide_h3;
			//1 ガイド高さ下方不変
			if (pathdata3 == 1) {textChip3[i].y =keepguide_h3*-1;}
		}
		//ポイント移動
		if (pointtype_no == 1) {
			textChip3[i].x=guide_w3+textPosx3[i];
			textChip3[i].y=guide_h3;
			//1 ガイド高さ下方不変
			if (pathdata3 == 1) {textChip3[i].y =keepguide_h3*-1;}
		}
		//強制中央に修正
		if (pointtype_no == 2) {
			textChip3[i].x=basetext_W/2;
			textChip3[i].y=0;
		}
		//画面ランダム
		if (pointtype_no == 3) {
			//globalToLocal
			var point=basetextcontainer.globalToLocal(Math.random()*canvasWidth,Math.random()*canvasHeight);
			textChip3[i].x=point.x;
			textChip3[i].y=point.y;
		}
		//ステージ内指定位置
		if (pointtype_no == 4) {
			//globalToLocal
			var point=basetextcontainer.globalToLocal(stagePoint_x3,stagePoint_y3);
			textChip3[i].x=point.x;
			textChip3[i].y=point.y;
		}

		//MOVEポジション保存
		movePosx3[i]=textChip3[i].x;
		movePosy3[i]=textChip3[i].y;

		//セット
		textChip3[i].rotation=rotate_no;
		textChip3[i].alpha=alpha_no;//調整
		textChip3[i].scaleX=scls;
		textChip3[i].scaleY=scls;
		//スケール保存
		keepScale3=scls;
		//回転保存逆転あり
		keepRote3=rotate_no*-1;//設定の逆転
		//alpha保存
		keepAlpha3=alpha_no;

		//delay計算/現在文字列順
		delay_st[i]=base_time3*i;

		if (delay_no == 0) {delay_st[i]=base_time3*(sh-i);}//逆順
		if (delay_no == 1) {delay_st[i]=Math.abs(i-sh/2)*base_time3;}//中から
		if (delay_no == 2) {delay_st[i]=Math.abs(Math.abs(i-sh/2)-textlen3/2)*base_time3;}//外から

		//交互遅延
		if (chgflag2 == 1) {
			if (flag == 1) {delay_st[i] +=delayed_time3;}
		}

		k ++;
		flag *=-1;
	}

	//TEXT
	//set_text("");

	//delayの最大値を求める
	var max_delay=Math.max.apply(null,delay_st);

	//速度補正
	var speed_v=speed3;
	//pathdata3.5番 速度1.5倍補正
	if (pathdata3 == 3 || pathdata3 == 5) {speed_v *=1.5;}

	var flag=-1;
	//Tween
	for (var i=0; i < textlen3; i++) {

		var pathdata_v;
		if (pathdata3 == 0) {pathdata_v=[textPosx3[i],textPosy3[i], 100+textPosx3[i],-150, 200+textPosx3[i],0, 300+textPosx3[i],150, movePosx3[i],movePosy3[i]];}//1
		if (pathdata3 == 1) {pathdata_v=[textPosx3[i],textPosy3[i], 50+textPosx3[i],-150, 250+textPosx3[i],-75, 400+textPosx3[i],0, movePosx3[i],movePosy3[i]];}//2
		if (pathdata3 == 2) {pathdata_v=[textPosx3[i],textPosy3[i], -50+textPosx3[i],100, -100+textPosx3[i],0, -150+textPosx3[i],-150, movePosx3[i],movePosy3[i]];}//3
		if (pathdata3 == 3) {pathdata_v=[textPosx3[i],textPosy3[i], 200+textPosx3[i],-150, 150+textPosx3[i],0, 100+textPosx3[i],100, 50+textPosx3[i],0, 0+textPosx3[i],-150, movePosx3[i],movePosy3[i]];}//4
		if (pathdata3 == 4) {pathdata_v=[textPosx3[i],textPosy3[i], 50+textPosx3[i],200, movePosx3[i],movePosy3[i]];}//5
		if (pathdata3 == 5) {pathdata_v=[textPosx3[i],textPosy3[i], 100+textPosx3[i],-135, -50+textPosx3[i],-70, -200+textPosx3[i],50, 50+textPosx3[i],70, 250+textPosx3[i],50, movePosx3[i],movePosy3[i]];}//6

		//Tween
		var twn3=createjs.Tween.get(textChip3[i]);
		twn3.wait(delay_st[i])
		.to({guide:{path:pathdata_v,orient:false,start:1,end:0},rotation:0,scaleX:1,scaleY:1,alpha:1},speed_v)//右用
		.to({x:textPosx3[i],y:textPosy3[i],rotation:0},50)

		.wait(50).to({x:textPosx3[i],y:textPosy3[i]},50)
		.wait(100).to({scaleX:2,scaleY:2},50)
		.wait(100).to({scaleX:1,scaleY:1},200);

		if (chgflag == 0) {
			twn3.wait(1000).to({y:-30*flag},400)
			.to({y:textPosy3[i]},100);
		}

		twn3.wait(max_delay-delay_st[i])//最大値利用時間差吸収
		.wait(8000)

		.wait(delay_st[i])
		.to({scaleX:.1,scaleY:.1},500)
		.to({x:moveBallPosx3[i],y:moveBallPosy3[i],scaleX:3,scaleY:3,rotation:360*chg_v,alpha:0},2000)
		.wait(max_delay)
		.to({x:textPosx3[i],y:textPosy3[i],scaleX:.1,scaleY:.1,rotation:0,alpha:1},1500)
		.wait(500)
		.to({scaleX:1.5,scaleY:1.5},800)
		.to({scaleX:1,scaleY:1},200)

		.wait(max_delay-delay_st[i])//最大値利用時間差吸収
		.wait(3000)
		.to({rotation:360*chg_v},1800)
		.to({rotation:0},1)
		.wait(3000)

		.wait(delay_st[i])
		.to({scaleX:0.1,scaleY:0.1},500)
		.call(chgballb)
		.wait(500)
		//.to({guide:{path:pathdata_v,orient:false,start:0,end:1},scaleX:keepScale3,scaleY:keepScale3,alpha:keepAlpha3,rotation:keepRote3},speed_v)
		.to({x:moveBallPosx3[i],y:moveBallPosy3[i],scaleX:3,scaleY:3,rotation:360*chg_v*flag,alpha:0},1000)
		.call(function(){
			//終了
			if (textcount3 == textmax3-1) {finshtextAll3();}
			textcount3 +=1;//グローバルの事
		});

		flag *=-1;

	}

}

//BASE-BALLグラフィック流し込み
function chgballb () {
	var no=this.id;
	this.getChildAt(2).visible=false;
	this.getChildAt(1).visible=false;
	//this.getChildAt(0).graphics.clear();
	this.getChildAt(0).graphics=ballChip3[no].graphics;
}
function chgballb2 () {
	var no=this.id;
	this.getChildAt(0).graphics.clear();
	this.getChildAt(1).visible=true;
	this.getChildAt(2).visible=true;
}

//MAINテキスト終了
function finshtextAll () {

	set_text("WELCOM");

	//welcome画像1 FadeIn
	welcomeImage.alpha=0;
	welcomeImage.visible=true;
	var twn5=createjs.Tween.get(welcomeImage)
	.to({y:0,alpha:1},600)//FadeIn
	.call(function(){
		//welcome画像非表示
		welcomeImage2.visible=false;
		//welcome画像2 FadeIn
		welcomeImage2.alpha=0;
		welcomeImage2.y=20;
		welcomeImage2.visible=true;
		var twn4=createjs.Tween.get(welcomeImage2)
		.wait(1000)
		.to({y:0,alpha:1},600)//FadeIn
		.wait(2000)
		.to({y:20,alpha:0},600)//FadeOut
		.call(function(){
			//welcome画像非表示
			welcomeImage2.visible=false;

			var twn6=createjs.Tween.get(welcomeImage)
			.wait(1000)
			.to({y:0,alpha:0},600)//FadeOUT
			.call(function(){
				//welcome画像非表示
				welcomeImage.visible=false;

				finshAll();
			});
		});
	});

}

//BASEテキスト終了
function finshtextAll3 () {

	reset_parts();
}


//reset_parts
function reset_parts() {

	set_text("CLEAR / RESET");

	//removeAllTweens バージョン4.2.1
	//createjs.Tween.removeAllTweens();

	//個別removeTweens
	for (var i=0; i < textmax3; i++) {
		//removeTween
		createjs.Tween.removeTweens(textChip3[i]);
	}

	//BASE-TEXTコンテナの中を削除
	basetextcontainer.removeAllChildren();

	//調整
	setTimeout(function() {

		//繰り返し
		set_prologue();

	},4000);

}

//tickステージ
function tick() {
	stage.update();
}

//背景付きコンテナ収容MOVEテキストインスタンスを作る
//サイズ,フォント,ベース幅,ベース高さ,角丸半径,ベース色,虹色,文字間隔,半角スペース幅,文字色,文字
function createMoveText3(size,font,bw,bh,br,basecolor,rainbow,space,space_w,strcolor,str) {

	var fontdata=size + " " + font;

	var chip=[];
	var len=str.length;
	var tpos_x=0;
	var tpos_y=0;
	var boxpos_x=0;
	var boxpos_y=0;
	var spcflag=false;
	var k=0;

	var eisuu=false;
	var regy_v=0;

	//半角スペースを除いた長さ
	var strings=str;
	//注意正規表現
	var nospclen=strings.replace(/ /g,'').length;
	var string_v="";

	for (var i=0; i < len; i++) {

		string_v=str.charAt(i);
		spcflag=false;
		//スペース判定、インスタンスを作らない
		if (string_v != ' ') {spcflag=true;}

		if (spcflag) {
			//コンテナ収容形
			var box=new createjs.Container();
			//Shape
			var s=new createjs.Shape();
			var s2=new createjs.Shape();//空Shape
			//文字インスタンスを作る文字指定色
			var t=new createjs.Text("",fontdata,strcolor);

			t.textBaseline="middle";
			//1文字入れる
			t.text=string_v;

			//英数字判別
			eisuu=isEisuu(string_v);

			//幅高さ取得
			var w=t.getMeasuredWidth();
			var h=t.getMeasuredHeight();

			//受け渡し用
			t.width=w;
			t.height=h;
			//原点中央テキストのみ重要
			t.regX=w/2;//X実行
			//t.regY=h/2;//補正後実行

			//textBaseline middleでの修正のほうが楽かも
			//firefox、2ピクセルほど上になる
			//漢字はoperafirefox、2ピクセルほど上になる

			regy_v=0;//補正なしは0

			//英数字の場合
			if (eisuu) {
				if (opera) {regy_v=0;}
				if (firefox) {regy_v=-1;}
			}
			//漢字の場合
			if (!eisuu) {
				if (opera) {regy_v=2;}
				if (firefox) {regy_v=-1;}
			}
			//regYの実行
			t.regY=regy_v;

			//shadow
			t.shadow=shadow;

			//コンテナ/受け渡し用重要未使用
			box.width=bw;
			box.height=bh;

			//図形RoundRect
			s=createRoundRect(-bw/2,-bh/2,bw,bh,br,basecolor,rainbow,nospclen-1,k);
			//図形Rectx,y,w,h,color,rainbow,len,no
			//s=createRect(0,0,bw,bh,basecolor,rainbow,nospclen-1,k);
			//Circle/文字は小さく
			//s=createBall(0,0,bw/2,basecolor,rainbow,nospclen-1,k);

			//X位置計算 文字間隔
			if(k == 0) {
				boxpos_x=bw/2;
			} else {
				boxpos_x +=(bw+space);
			}

			//コンテナを位置にあわせる
			box.x=boxpos_x;
			box.y=boxpos_y;//0
		
			//add s2,s,t
			box.addChild(s2,s,t);
			//配列に入れる/半角スペース除去のインスタンス
			chip.push(box);

			k +=1;

		}
		if (!spcflag) {
			//半角スペース幅加算
			boxpos_x +=space_w;
		}

	}
	//戻り配列
	return chip;
}

//Circleインスタンスを作る
function createBall(x,y,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//ベタ
	//s.graphics.s().beginFill(c).drawCircle(x,y,r);
	//グラデ、若干効果
	s.graphics.s().beginLinearGradientFill([c,"#FFFFFF"],[0,1],0,0,0,r).drawCircle(x,y,r);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//Starインスタンスを作る
function createStar(x,y,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	s.graphics.s().beginFill(c).drawPolyStar(0,0,r,5,.65,-90);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//Rectインスタンスを作る
function createRect(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	s.x=x;
	s.y=y;
	s.graphics.s().beginFill(c).drawRect(-w/2,-h/2,w,h);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//RoundRectインスタンスを作る
function createRoundRect(x,y,w,h,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	s.graphics.s().beginFill(c);
	operaRoundRect(s,x,y,w,h,r);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//Lineインスタンスを作る
function createLine(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	s.graphics.ss(w,"round").s(c).moveTo(0,-h/2).lineTo(0,h/2);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//Leafインスタンスを作る
function createLeaf(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	s.graphics.s().beginFill(c).moveTo(0,-h/2).quadraticCurveTo(w/2,0,0,h/2).quadraticCurveTo(-w/2,0,0,-h/2);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//Ellipseインスタンスを作る
function createEllipse(x,y,w,h,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	s.graphics.s().beginFill(c).drawEllipse(x,y,w,h);
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//ランダムBALLインスタンス
function createRandomBall(w,h,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//5-8個
	var k=Math.floor(Math.random()*4)+5;
	for (var i=0; i < k; i++) {
		var x_v=Math.floor(Math.random()*w)-w/2;
		var y_v=Math.floor(Math.random()*h)-h/2;
		s.graphics.s().beginFill(c).drawCircle(x_v,y_v,r);
	}
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//ランダムRINGインスタンス
function createRandomRing(w,h,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//5-8個
	var k=Math.floor(Math.random()*4)+5;
	for (var i=0; i < k; i++) {
		var x_v=Math.floor(Math.random()*w)-w/2;
		var y_v=Math.floor(Math.random()*h)-h/2;
		s.graphics.ss(1).s(c).beginFill().drawCircle(x_v,y_v,r);
	}
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//ランダムRectインスタンス
function createRandomRect(w,h,r,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//5-8個
	var k=Math.floor(Math.random()*4)+5;
	for (var i=0; i < k; i++) {
		var x_v=Math.floor(Math.random()*w)-w/2;
		var y_v=Math.floor(Math.random()*h)-h/2;
		s.graphics.s().beginFill(c).drawRect(x_v,y_v,r,r);
	}
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}
//ランダムSTARSインスタンス、star_vは角数
function createRandomStars(w,h,r,star_v,color,rainbow,len,no) {
	var c=color;
	if (rainbow) {
		c=createjs.Graphics.getHSL(no/len*360,100,50);//直接
	}
	var s=new createjs.Shape();
	//5-8個
	var k=Math.floor(Math.random()*4)+5;
	for (var i=0; i < k; i++) {
		var x_v=Math.floor(Math.random()*w)-w/2;
		var y_v=Math.floor(Math.random()*h)-h/2;
		//星は奇数
		s.graphics.s().beginFill(c).drawPolyStar(x_v,y_v,r,star_v,.8,30*i);
	}
	//原点
	s.regX=0;
	s.regY=0;
	return s;
}

//quadraticCurveTo、こちら使用
function operaRoundRect(s,x,y,w,h,r) {
	s.graphics.moveTo(x+r,y)
	.lineTo(x+w-r,y)
	.quadraticCurveTo(x+w,y,x+w,y+r)
	.lineTo(x+w,y+h-r)
	.quadraticCurveTo(x+w,y+h,x+w-r,y+h)
	.lineTo(x+r,y+h)
	.quadraticCurveTo(x,y+h,x,y+h-r)
	.lineTo(x,y+r)
	.quadraticCurveTo(x,y,x+r,y);
}

//rainbow-Color
var rainbowColor=function(v,cv,saturation,lightness) {
	var no=v/cv*360;
	var color=createjs.Graphics.getHSL(no,saturation,lightness);
	return color;
}

//VIEWTEXT
function set_text(t) {
	if (textUse) {
		viewtext.text=t;
	}
}
//英数字判別
function isEisuu(c){
	var unicode=c.charCodeAt(0);
	if (unicode < 256 || (unicode >= 0xff61 && unicode <= 0xff9f)){
	return true;
	} else {return false;}
}

//START
init();

注釈文を削除すれば、幾分早くなります。
(画像使用の場合は、登録画像パスは当方の記述ですから使用の際は環境に合わせてください)


CSS

createJS034.css、CSS名は任意に変更可


/*日本語 createJS034.css*/

#demo-wrap {
text-align:center;
}

#image-box {
position:relative;
top:0;left:0;
width:640px;
height:300px;
margin:0 auto;
padding:0;
box-shadow:0 0 10px #000;
-moz-box-shadow:0 0 10px #000;
-webkit-box-shadow:0 0 10px #000;
-o-box-shadow:0 0 10px #000;
-ms-box-shadow:0 0 10px #000;
background-color:#FFFFFF;
}

#image-box #mainCanvas {
border-radius:10px;
}
canvas {
border-style:none;
background-color:transparent;
}

.radius {
border-radius:10px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
-o-box-border-radius:10px;
-ms-border-radius:10px;
}

当方のサンプルの例です。


簡単な説明


多少の問題も有りますが前ページの、Shapeクラスを内包したテキスト要素を作る createMoveText関数 を改造して作ります。背景図形描写のShapeクラス層が1つ増えています。
説明が「難解」ですが、図と合わせて「テキトウ」に理解下さい。


グラフィック図形を内包したテキスト要素を作る時の問題点

色々な方法は有ろうかと思いますが、グラフィック図形の中心にテキスト要素を配置しなければ見栄えが悪くなります。


1. テキスト要素の横幅は正確に取得するが、高さは正確に取得出来ない(ブラウザによりマチマチだ、Canvas策定対応が完全ではない故、CreateJSは暫定的に計算しているのだろうと思う)
2. テキストのY方向の配置がブラウザによりマチマチである。
3. 英数字、漢字の時の配置位置がそれぞれ違う。
4. よってテキスト要素の中央配置は大変困難である。将来は改善されるだろうが不明です。(現在、テキスト周りの色々な対応がマチマチで、尚且つ、完全に策定されていない)


[説明図]

Shapeクラス、コンテナクラスを大きさのあるように描いてあるが、実際は点である。

 

グラフィック図形を内包したテキスト要素を作り中央配置に修正する

色々と思考して、テストして見ましたが皆面倒であります。一番簡単な方法はテキスト要素を textBaseline="middle" で縦方向のみ自動的に合わせる方法が良い様です。
ここでは、横方向は、従来通りregXで補正します。勿論 textAlign="center" は原則設定してはなりません


1. テキスト要素のX方向は、従来通りregXで補正
2. テキスト要素のY方向は、textBaseline="middle" で一旦、「中」に合わせてブラウザ毎に誤差を修正する
3. 英数字、漢字の時の配置位置の違いも出ますから、「文字を判別」してブラウザ毎に誤差を修正する
4. 「半角スペース」はスクリプトで除去して、その分「間隔」で補正します
5. 文字を読み易くするため、文字にshadowフイルター処理しました。全体のshadowフイルターは自由です(拡大、フエードで重くなるので注意、最近のマシンではそれほどでもない)。
6. 文字の種類は「Arial」に成ります。特に「MS ゴシック」など指定した場合は位置が違ってきますのでここでは対処しません。「Impact」を指定しても位置に問題は無いようだが、指定文字種をマシンが持っているとは限らないので「Arial」が一番無難と思います。
7. 英小文字の「y」などはベースラインより下方に下がりますので、原則、英字は「大文字」を使用下さい。
8. Safari(MAC)、IE10、では確認していません。特に Safari(MAC) はズレル場合があるかも知れません
9. 文字位置の多少のズレなど気にならない「性格」の人は補正など無しでも結構です。簡単になります。
10. 実際に作らないと理解し難いと思います。モット良い方法があれば、考えてください。


● 文字列の中の区切りには必ず 「半角スペース」 を使用下さい。英字は 「大文字」 推奨


var basestring="POPS WEB KOUBOU";
var basestring="赤マムシ 生タマゴ を世界遺産に!";

● createMoveText3()関数でインスタンス配列取得


//スペース補正形コンテナ収容インスタンス配列取得 Arial専用
//サイズ,フォント,ベース幅,ベース高さ,角丸半径,ベース色,虹色,文字間隔,半角スペース幅,文字色,文字
textChip3=createMoveText3(font_size,"Arial",base_width,base_height,5,base_color,rainbowSet3,text_spc,spc_width,basetext_color,basestring);

● JS先頭以外の設定

JS先頭以外の設定が、set_baseanime()の先頭に有ります。テキスト周りの設定変更が出来ます。


//BASEテキストアニメ
function set_baseanime() {

	textcount3=0;//カウント、グローバル

	textChip3=[];//クリア
	var basetext_W=0;//0
	var text_spc=4;//文字間隔
	var spc_width=10;//半角スペース幅
	var center=true;
	//図形の大きさ、通常縦横同じ数値
	var base_width=30;
	var base_height=30;
	//文字サイズ
	var font_size="26px";//pxを付ける

	以下略す
}

● 背景付きコンテナ収容MOVEテキストインスタンスを作る関数

漢字、英数字の判別をして、ブラウザ毎にズレを補正し、「半角スペース」を除去しているだけです。改造などが必要な場合は自由です。


//背景付きコンテナ収容MOVEテキストインスタンスを作る
//サイズ,フォント,ベース幅,ベース高さ,角丸半径,ベース色,虹色,文字間隔,半角スペース幅,文字色,文字
function createMoveText3(size,font,bw,bh,br,basecolor,rainbow,space,space_w,strcolor,str) {

	var fontdata=size + " " + font;

	var chip=[];
	var len=str.length;
	var tpos_x=0;
	var tpos_y=0;
	var boxpos_x=0;
	var boxpos_y=0;
	var spcflag=false;
	var k=0;

	var eisuu=false;
	var regy_v=0;

	//半角スペースを除いた長さ
	var strings=str;
	//注意正規表現
	var nospclen=strings.replace(/ /g,'').length;
	var string_v="";

	for (var i=0; i < len; i++) {

		string_v=str.charAt(i);
		spcflag=false;
		//スペース判定、インスタンスを作らない
		if (string_v != ' ') {spcflag=true;}

		if (spcflag) {
			//コンテナ収容形
			var box=new createjs.Container();
			//Shape
			var s=new createjs.Shape();
			var s2=new createjs.Shape();//空Shape
			//文字インスタンスを作る文字指定色
			var t=new createjs.Text("",fontdata,strcolor);
			t.textBaseline="middle";
			//1文字入れる
			t.text=string_v;

			//英数字判別
			eisuu=isEisuu(string_v);

			//幅高さ取得
			var w=t.getMeasuredWidth();
			var h=t.getMeasuredHeight();

			//受け渡し用
			t.width=w;
			t.height=h;
			//原点中央テキストのみ重要
			t.regX=w/2;//X実行
			//t.regY=h/2;//補正後実行

			//textBaseline middleでの修正のほうが楽かも
			//firefox、2ピクセルほど上になる
			//漢字はoperafirefox、2ピクセルほど上になる

			regy_v=0;//補正なしは0

			//英数字の場合
			if (eisuu) {
				if (opera) {regy_v=0;}
				if (firefox) {regy_v=-1;}
			}
			//漢字の場合
			if (!eisuu) {
				if (opera) {regy_v=2;}
				if (firefox) {regy_v=-1;}
			}
			//regYの実行
			t.regY=regy_v;

			//shadow
			t.shadow=shadow;

			//コンテナ/受け渡し用重要未使用
			box.width=bw;
			box.height=bh;

			//図形RoundRect
			s=createRoundRect(-bw/2,-bh/2,bw,bh,br,basecolor,rainbow,nospclen-1,k);
			//図形Rectx,y,w,h,color,rainbow,len,no
			//s=createRect(0,0,bw,bh,basecolor,rainbow,nospclen-1,k);
			//Circle/文字は小さく
			//s=createBall(0,0,bw/2,basecolor,rainbow,nospclen-1,k);

			//X位置計算 文字間隔
			if(k == 0) {
				boxpos_x=bw/2;
			} else {
				boxpos_x +=(bw+space);
			}

			//コンテナを位置にあわせる
			box.x=boxpos_x;
			box.y=boxpos_y;//0
		
			//add s2,s,t
			box.addChild(s2,s,t);
			//配列に入れる/半角スペース除去のインスタンス
			chip.push(box);

			k +=1;

		}
		if (!spcflag) {
			//半角スペース幅加算
			boxpos_x +=space_w;
		}

	}
	//戻り配列
	return chip;
}

● ブラウザ毎の「位置ズレ」修正をする

中央に表示するものは補正していません。ズレるものを目視で補正しましたので(ズレの根拠、正確なズレる値などはワタシは不明です)、文字の大きさなどによっては1ピクセルの誤差が出来ることが予測されます。但し、殆んど気付く事はないと思います。
補正は次ぎの様に行っていますから、フォントなどが違った場合は位置ズレが違う事もありますので状況によっては修正下さい。小文字の判定修正はしていません。修正値は、現在時点(2013/09)でのものです。


regy_v=0;//補正なしは0

//英数字の場合
if (eisuu) {
	if (opera) {regy_v=0;}
	if (firefox) {regy_v=-1;}
}
//漢字の場合
if (!eisuu) {
	if (opera) {regy_v=2;}
	if (firefox) {regy_v=-1;}
}
//regYの実行
t.regY=regy_v;

現時点でのCanvasに対する修正方法です。将来に渡り修正しなければ成らないかなどは全て不明です。また、ブラウザバージョンが変わればズレが違ったりも想定出来ますので修正の必要が有ります。


参考、textAlign:center を設定して作る場合 (このデモでは使用しません)

但し、設定出来る条件がある。必ずテキストの下にグラフイックなどが入る「ボタン」形式であること。1文字づつ分割するテキストの場合は文字の間隔が合わなくなる。
よってこのデモの様な「図形背景」を入れる形式では「textAlign:center設定」が出来るが、regX は実行しない。利点としては複数文字の挿入が可能なことです。


Safari(WIN)、で maxWidth が機能しない( Safari(MAC)は不明です )等の理由で、
このデモでは「textAlign:center設定」を使用しません


途中略す

//文字インスタンスを作る文字指定色
var t=new createjs.Text("",fontdata,strcolor);

t.textAlign="center";
t.maxWidth=bw;

t.textBaseline="middle";
//1文字入れる
t.text=string_v;

途中略す

//テキスト原点中央
//t.regX=w/2;//Xの実行はしないこと
//t.regY=h/2;//補正後実行

途中略す

● 角丸図形RoundRectのほかに「マル」「四角」にも出来ます。但し「マル」の場合はフォントサイズを小さくして下さい。

背景図形が有るために多くの文字数の表示は出来ませんので注意下さい。(2段に表示するなどは配置の計算を変えれば可能ですが、、、)


//図形RoundRect
s=createRoundRect(-bw/2,-bh/2,bw,bh,br,basecolor,rainbow,nospclen-1,k);
//図形Rectx,y,w,h,color,rainbow,len,no
//s=createRect(0,0,bw,bh,basecolor,rainbow,nospclen-1,k);
//Circle/文字は小さく
//s=createBall(0,0,bw/2,basecolor,rainbow,nospclen-1,k);

「マル」背景は回転した時の対策としてグラデーション塗りにしている。


IEでの虹色の不具合 (IE9で確認)

上記、nospclen-1 の部分 nospclen とした方がキレイな配色になるが、IE(IE9で確認)で途中の配色が壊れてしまうので、nospclen-1 にしています。IE10では未確認ですが、おそらく同じと思いますが。


● 虹色にするため、事前に半角スペースを除いた長さ(文字数)を算出しています。replaceの使用に注意下さい。


//半角スペースを除いた長さ
var strings=str;
//注意正規表現、replace(" ","")は最初の1つのみ処理だ
var nospclen=strings.replace(/ /g,"").length;

● ブラウザ判定は簡単に次ぎの様に行っています。
判定不能なブラウザの場合は文字がズレル時がありますので、事前に了承下さい。
例、IEで有れば ie=true、 browser_v にバージョン番号が入ります。


//Browser判定
var userAgent = window.navigator.userAgent.toLowerCase();
var safari=false,chrome=false,firefox=false,opera=false;
var ie=false;
var browser_v;
if (/*@cc_on!@*/false) {
	ie=true;
	if (navigator.userAgent.match(/MSIE (¥d¥.¥d+)/)) {browser_v = parseFloat(RegExp.$1);}//IE6.7.8.9.10
}
if (userAgent.indexOf("safari") > -1) {safari=true;}
if (userAgent.indexOf("chrome") > -1) {chrome=true;}
if (userAgent.indexOf("firefox") > -1) {firefox=true;}
if (userAgent.indexOf("opera") > -1) {opera=true;}

文字化けの可能性があるので画像を付けます。


ブラウザ判定は当方の下記記事のものを修正しています。但し、主要ブラウザ判定のみ、Androidの判定はなし。

【参照】当方の記事: jQueryによるブラウザ判定サポート終了


● 英数字判別は簡単に次ぎの様に行っています。


//英数字判別、こちらは使える
function isEisuu(c){
	var unicode=c.charCodeAt(0);
	if (unicode < 256 || (unicode >= 0xff61 && unicode <= 0xff9f)){
	return true;
	} else {return false;}
}

半角スペースの扱い

「半角スペース」を除外し「スペースの幅分」を修正しての処理をしましたので「透明人間」はツマミ出されました。「透明人間」がTweenでブンブン飛び回っている状態は改善され平和が戻ってきました。(面倒なので、消しゴムで消しました)


「透明人間」は、覗き趣味があったが、イイやつだった!

 

グラフイックを取り替える

文字要素コンテナの最下部に空のShapeを配置していますので、途中で挿入交換など出来ます。単なる図形交換はで面白みが無いので、適当なランダム配置の小さな図形を入れて見ました。(回転させないとバレバレのゴマカシだ!)
デモでは、Tweenの最後に取り替えています。


これは簡単な動作のサンプルです

このJSは、簡単な動作のサンプルですから未完成の形になります。本格的に利用するならば、目的に合わせて修正、加筆しなければなりません。


登録ガイドパス

下記の様なデータになっています。


ガイドパス及び関連設定などは、前ページのものと同じですからそちらを参照下さい

【参照】当方の記事: CreateJS MotionGuidePlugin利用、複数のガイドパス登録でテキストをMotionTweenさせる


MAIN-TEXT(通常のテキストアニメ)などと組み合わせる

通常のテキストアニメと組み合わせることが可能ですが少々重く成りますと共に賑やかに成ります(お祭りだ)。
MAIN-TEXTと形式はほぼ同じですので(変数などに 3 が付いている)、インスタンスを取り替えれば、MAIN-TEXTのスクリプトででも作動しますが次ぎの違いが有ります。

1. テキスト要素全体収容のコンテナ幅の計算が違う。
2. テキスト要素の中のテキスト、グラフイックの重ね順が違う。
3. 途中でグラフィックを挿入の番号指定が出来ず、設定がランダムになっている。グラフィックの形も違う。
4. スケールデータの拡大を大きくしない様に意識した。(大きくしても動くが重くなる)
5. 合計の文字数は半角スペースを除いた数になる。



//全幅の計算を先に計算/文字間の距離プラス図形幅
basetext_W =textChip3[textlen3-1].x-textChip3[0].x+base_width;

//add s2,s,t
box.addChild(s2,s,t);

//BALL番号、ランダムのみ
var ballno3=Math.floor(Math.random()*6);

//スケールデータ
var scaledata3=[0,0,0,0,.5,1,2,4];

//配列に入れる/半角スペース除去のインスタンス
chip.push(box);

改造などに注意。
尚、ランダム図形でない通常の図形を作る関数は残しています。(実際の使用は前ページ参照)


応用

Tweenなどしなくとも、同じ形式の背景図形を入れたテキスト(1文字限定)を作る場合に利用出来ます。多少修正などあるので面倒ですが、、。但し、複数文字挿入の「ボタン」などは作り方が違いますしズット簡単です。(ブラウザにより縦方向の多少のずれは発生しますが、、)


通常のテキストアニメも表示高さは狂っている

今まで「シランフリ」していましたが、当然、通常のテキストアニメも文字のY位置に、ブラウザにより多少のズレは有ります。一応は補正のメドは立ちましたが「補正の意思」は有りません。
(ズレに気が付く人は殆んどいないと思いますし、補正方法が面倒きわまりない故「シランフリ」が合理的だ)




一応、完動しますが全てテストです。効率化のため、予告無くJSなど修正する場合がありますので了承下さい。


ガイドパス及び関連設定などは、前ページのものと同じですからそちらを参照下さい

【参照】当方の記事: CreateJS テキストアニメーション、Tweenの途中でグラフィックを挿入する


こんなに面倒で使用する人はいるのでしょうか?疑問です(ワタシは当然面倒は嫌いだ)。
以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]