POPSブログ

CreateJS Canvasエレメント描画OUTLINEテキストを補正しアニメーション

313

  Category:  javascript2014/07/20 pops 

CreateJS Textクラスで作ったOUTLINEテキストにCanvasエレメント描画の画像などで、テキストを装飾しますが、OUTLINEの幅が大きいと文字が壊れるので修正する。
また、CanvasエレメントをBitmap()で表示する場合、Chromeで陰影がつかないのも構造を変えて補正する。
easeljs-0.7.1 でのテストです。

 

CreateJS Canvasエレメント描画OUTLINEテキストを補正しアニメーション テスト

テキストの中心補正を textBaseline middleで、Canvasエレメントを使用して画像をテキストに描画します。前ページでの不具合を構造を変えて補正します。


 

 

DEMO


CreateJS Canvasエレメント描画OUTLINEテキストアニメーションのデモ、(createJS097.js)

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


1. 画像埋め込みテキストの表示のデモ


2. 画像埋め込みテキストのシミュレーション


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


 

HTML JS CSS


使用するライブラリ

easeljs preloadjs tweenjs

配布元 : CreateJS createjs.com


ライブラリの読み込み

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


<script type="text/javascript" src="js/easeljs-0.7.1.min.js"></script>
<script type="text/javascript" src="js/preloadjs-0.4.1.min.js"></script>
<script type="text/javascript" src="js/tweenjs-0.5.1.min.js"></script>

重要、バージョン違いでは動かない場合が有りますので必ず合わせて下さい。


HTML (HTML5)


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

JS

createJS097.js、JS名は任意に変更可。注意、easeljs-0.7.1用です。


//日本語
//createJS097.js
//デモ用Canvasエレメント描画OUTLINEテキストアニメーション修正タイプ
//easeljs-0.7.1用

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

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

//prologue表示時間
var prologue_time=12000;

//メインテキスト
var mainstring="ViVa POPS WEB KOUBOU";
//メインテキスト表示位置
var mtcontainer_x=100;//中央補正しない場合
var mtcontainer_y=55;//暫定

//ロゴテキスト
var logostring="WELCOME";

//画像manifestリスト
var manifest=[
{src:"/main/images/textback01.jpg",id:"PHOTO1"},
{src:"/main/images/textback02.jpg",id:"PHOTO2"},
{src:"/main/images/textback03.jpg",id:"PHOTO3"},
{src:"/main/images/textback04.jpg",id:"PHOTO4"},
{src:"/main/images/textback05.jpg",id:"PHOTO5"},
{src:"/main/images/textback06.jpg",id:"PHOTO6"},
{src:"/main/images/textback07.jpg",id:"PHOTO7"},
{src:"/main/images/textback08.jpg",id:"PHOTO8"},
{src:"/main/images/textback09.jpg",id:"PHOTO9"},
{src:"/main/images/textback10.png",id:"PHOT10"},
{src:"/main/images/textback11.png",id:"PHOT11"},
{src:"/main/images/textback12.png",id:"PHOT12"},
{src:"/main/images/textback13.png",id:"PHOT13"},
{src:"/main/images/textback14.jpg",id:"PHOT14"},
{src:"/main/images/textback15.png",id:"PHOT15"}
];

//------------------------------------------------------
//変数、未使用もあり

//ステージ
var stage;
//コンテナなど
var backrect;
var container;
var btncontainer;
//TEXT
var viewtext;

//MAIN-TEXT
var maintextcontainer;
var maintext;
//MOVE-TEXT
var textChip=[];
var textPosx=[];
var textPosy=[];

//LOGO-TEXT
var logotextcontainer;
var logotext;
//MOVE-TEXT2
var textChip2=[];
var textPosx2=[];
var textPosy2=[];

//読み込み画像URL保存容器
var assets=[];
var loader;
var image_max;
//------------------------------------------------------
//shadowフィルター
var shadow=new createjs.Shadow("#000000",0,0,4);

//click-btn
var myhitBtn;

//var textlen=0;
//var textcount=0;
var backchg_no=0;
var backcolors=["#000000","#FFFFFF","#BC8F8F","#4682B4","#6B8E23","#888888","#333333"];

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

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

	//STAGE
	stage=new createjs.Stage('mainCanvas');
	//MouseOver重要
	stage.enableMouseOver(20);

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

	//クリック
	backrect.addEventListener("click",backchg);
	stage.addChild(backrect);

	//簡易TEXT
	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);
	set_text("LOADING NOW!");

	//LOGO-TEXT
	logotextcontainer=new createjs.Container();
	//表示位置
	logotextcontainer.x=150;
	logotextcontainer.y=80;
	stage.addChild(logotextcontainer);

	//MAIN-TEXT
	maintextcontainer=new createjs.Container();
	//表示位置
	maintextcontainer.x=mtcontainer_x;
	maintextcontainer.y=mtcontainer_y;
	stage.addChild(maintextcontainer);

	//btncontainer
	btncontainer=new createjs.Container();
	btncontainer.y=270;
	stage.addChild(btncontainer);
	set_btn();
	myhitBtn.visible=false;

	stage.update();

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

	//調整
	setTimeout(function() {

		//画像一括ロードに進む
		bulkload();

	},1000);

}

//bulk-load、画像一括ロード
function bulkload() {

	//Loader
	loader=new createjs.LoadQueue(false);

	//loader EventListener設定、この部分修正
	loader.addEventListener("fileload",fileload);
	loader.addEventListener("complete",complete);
	//error関数を追加
	loader.addEventListener("error",loaderror);

	//Manifestを使用、manifest読み込み開始
	loader.loadManifest(manifest);

}
//各画像読み込み完了
function fileload (eventObject) {

	//エラー無しの画像をassets容器に保存
	assets.push(eventObject.result);

}
//全ての画像読み込み完了
function complete (event) {

	set_text("LOADING END!");
	//画像数確認、再計算
	image_max=assets.length;

	//loader Listener削除 こちら使用に修正
	loader.removeEventListener("fileload",fileload);
	loader.removeEventListener("complete",complete);
	//追加error関数を削除
	loader.removeEventListener("error",loaderror);

	//画像があれば
	if (image_max) {
		setTimeout(function() {

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

		},2000);
	}

}
//エラー処理
function loaderror(eventObject) {

	//エラーの場合代替画像を作りassets容器に格納
	//var img=createColorCanvas (canvasWidth,canvasHeight,"#FFFFFF");//ベタ
 	var img=createLineGradBox (canvasWidth,canvasHeight,"#FFFFFF",d_color[assets.length],"#FFFFFF","y",2);//登録色グラデーション
	assets.push(img);
}

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

	//MAINテキストアニメ
	set_mainanime();
	//LOGOテキストアニメ
	set_logoanime();

	//調整
	setTimeout(function() {

		//案内
		set_text("テキストアニメーションが終了したら「ボタン」を押してください。");
		//ボタン表示
		myhitBtn.visible=true;
		//自動
		//reset_text();

	},prologue_time);

}

//背景色変更
function backchg() {
	backchg_no ++;
	if (backchg_no > backcolors.length-1) {backchg_no=0;}
	var color=backcolors[backchg_no];
	backrect.graphics.beginFill(color).drawRect(0,0,canvasWidth,canvasHeight);
}

//MAINアウトラインテキストアニメ/現在使用
function set_mainanime() {

	//MAINテキストアニメーション
	var maintext_W=0;
	var text_spc=0;//テキストスペース
	var center=true;
	var tcount=0;
	var outline_w=2;//アウトライン幅

	var img=assets[2];
	var img_alpha=1;

	//インスタンス配列取得
	//CanvasW,H,サイズ,フォント,色,アウトライン幅,虹色,スペース,陰影色,陰影,画像,画像透明度,文字,base表示
	textChip=createMoveOutlineTextCanvas_C(50,50,"40px","Arial","#FFFFFF",outline_w,true,text_spc,"#000000",true,img,img_alpha,mainstring,false);
	var textlen=mainstring.length;

	//ランダム配置のため全幅の計算を先に
	for (var i=0; i < textlen; i++) {
		maintext_W +=textChip[i].width;
		if(i < textlen) {maintext_W +=text_spc;}
	}
	//コンテナ中央ランダムのため速く決めた
	if (center) {maintextcontainer.x=(canvasWidth-maintext_W)/2;}

	//移動
	var delay_st=[];
	//パターン番号
	var pattern_no=Math.floor(Math.random()*6);
	//多目的判定用フラグ
	var chgxyflag=Math.floor(Math.random()*5);
	//多目的用2
	var chgflag=Math.floor(Math.random()*3);
	var chgflag2=Math.floor(Math.random()*3);
	//逆転フラグ
	var chg_v=Math.floor(Math.random()*2);
	if (chg_v < 1) {chg_v=-1;}

	//回転
	var rotate_no=chgflag*chg_v;
	//スケール
	var sclsdata=[1,1,1,.5,4,8];
	var scls=sclsdata[Math.floor(Math.random()*sclsdata.length)];
	//delay番号
	var delay_no=Math.floor(Math.random()*3);

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

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

		//addChild
		maintextcontainer.addChild(textChip[i]);
		//ポジション取得
		textPosx[i]=textChip[i].x;
		textPosy[i]=textChip[i].y;

		//全幅計算は上で行っている
		//maintext_W +=textChip[i].width;
		//if(i < textlen) {maintext_W +=text_spc;}

		//移動左右1、X方向のみ
		if (pattern_no == 0) {
			textChip[i].x=canvasWidth*chg_v;
			textChip[i].y=textPosy[i];
		}
		//移動左右2、Y方向ズレ
		if (pattern_no == 1) {
			textChip[i].x=canvasWidth/2*chg_v;
			textChip[i].y +=100*flag*chg_v*(chgflag2-1);
		}
		//移動上下
		if (pattern_no == 2) {
			textChip[i].x=textPosx[i];//その場
			textChip[i].y=canvasHeight/2*chg_v*(chgflag+1);
			if (chgflag == 1) {
				textChip[i].y *=flag;//上下交互
			}
		}
		//ランダム
		if (pattern_no == 3) {
			//globalToLocal
			var point=maintextcontainer.globalToLocal(Math.random()*canvasWidth,Math.random()*canvasHeight);
			textChip[i].x=point.x;
			textChip[i].y=point.y;
		}
		//文字列の中心から
		if (pattern_no == 4) {
			textChip[i].x=maintext_W/2;
			textChip[i].y=textPosy[i];//その場
		}
		//その場所から
		if (pattern_no == 5) {
			textChip[i].x=textPosx[i]+20*(chgflag-1);//その場少しずらす
			textChip[i].y=textPosy[i];//その場
		}

		textChip[i].rotation=rotate_no*180*(chgflag2-1);
		textChip[i].alpha=0;
		textChip[i].scaleX=scls;
		textChip[i].scaleY=scls;

		//delay
		delay_st[i]=100*i;//標準
		if (delay_no == 1) {delay_st[i]=20*i*i;}
		if (delay_no > 1) {delay_st[i]=Math.abs(i-sh/2)*150;}//150-200

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

		k ++;
		flag *=-1;
	}
	//delay逆転
	if (chgflag == 0) {
		delay_st.reverse();
	}

	//コンテナ中央補正は上で行っている
	//if (center) {maintextcontainer.x=(canvasWidth-maintext_W)/2;}

	//Tween
	for (var i=0; i < textlen; i++) {
		//Tween
		var twn=createjs.Tween.get(textChip[i])
		.wait(delay_st[i])
		.to({x:textPosx[i],y:textPosy[i],scaleX:1,scaleY:1,alpha:1,rotation:0},1000)
		.wait(100).to({scaleX:2,scaleY:2},50)
		.wait(100).to({scaleX:1,scaleY:1},200)
		.wait(500).call(textshadow)
		.call(finshmove);//現在何もしない
	}

}

//MOVE-画像修飾Outlineテキストインスタンスを作る1
//reg原点中央補正コンテナ収容
//CanvasW,H,サイズ,フォント,色,アウトライン幅,虹色,スペース,陰影色,陰影,画像,画像透明度,文字,base表示
function createMoveOutlineTextCanvas_C(CanvasW,CanvasH,size,font,color,outline_w,rainbow,space,scolor,shadow,img,imgalpha,str,base) {

	var fontdata=size + " " + font;

	var chip=[];
	var len=str.length;
	var tpos_x=0;
	var tpos_y=0;

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

		//1文字
		var text=str.charAt(i);

		//コンテナ
		var contna=new createjs.Container();

		//ダミー文字インスタンスを作る
		var t=new createjs.Text("",fontdata,"#FFFFFF");
		t.outline=outline_w;
		//1文字入れる
		t.text=text;
		//幅高さ
		var w=t.getMeasuredWidth();
		var h=t.getMeasuredHeight();

		//位置
		tpos_x +=w/2;//half
		contna.x=tpos_x;
		contna.y=tpos_y;//0

		//虹色
		if (rainbow) {
			color=createjs.Graphics.getHSL(i/len*360,100,50);//直接
		}

		//base
		var canvas=document.createElement("canvas");
		canvas.width=CanvasW;
		canvas.height=CanvasH;
		var ctx=canvas.getContext("2d");
		ctx.strokeStyle=color;

		ctx.font=fontdata;
		ctx.textAlign="center";
		ctx.textBaseline="middle";
		ctx.lineJoin="miter";
		ctx.miterLimit=outline_w/2;

		if (shadow) {set_shadow (ctx,scolor);}//陰影
		//stroke
		ctx.lineWidth=outline_w;
		ctx.strokeText(text,CanvasW/2,CanvasH/2);
		var shadow_txt=new createjs.Bitmap(canvas);
		shadow_txt.name="base";
		//原点中央
		shadow_txt.regX=CanvasW/2;
		shadow_txt.regY=CanvasH/2;
		//base表示
		if(!base) {shadow_txt.visible=false;}

		//画像
		var canvas=document.createElement("canvas");
		canvas.width=CanvasW;
		canvas.height=CanvasH;
		var ctx=canvas.getContext("2d");

		//トリミング画像、X、Y、幅、高さ、
		var trimming_img=imageTrimmingCanvas(img,tpos_x,0,CanvasW,CanvasH,0,0,CanvasW,CanvasH);//X位置をずらした画像を得る
		var pattern=ctx.createPattern(trimming_img,"repeat");
		ctx.strokeStyle=pattern;
		ctx.font=fontdata;
		ctx.textAlign="center";
		ctx.textBaseline="middle";
		ctx.lineJoin="miter";
		ctx.miterLimit=outline_w/2;
		ctx.globalAlpha=imgalpha;
		//stroke
		ctx.lineWidth=outline_w;
		ctx.strokeText(text,CanvasW/2,CanvasH/2);
		var img_txt=new createjs.Bitmap(canvas);
		//原点中央
		img_txt.regX=CanvasW/2;
		img_txt.regY=CanvasH/2;

		//位置加算
		tpos_x +=(w/2+space);//half+space

		contna.width=w;
		contna.height=h;
		contna.addChild(shadow_txt,img_txt);

		//コンテナ
		chip[i]=contna;
	}
	//戻り配列
	return chip;
}

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

//LOGOアウトラインテキストアニメ
function set_logoanime() {

	//LOGOテキストアニメーション
	var logotext_W=0;
	var text_spc=0;//テキストスペース
	var center=true;
	var tcount=0;
	var outline_w=2;//アウトライン幅

	//ベース表示,アウトライン表示,陰影
	var base=true;//ベース表示
	var line=true;//アウトライン表示
	var lcolor="#FFFFFF";//アウトライン色
	var shadow=true;//陰影
	var scolor="#000000";//陰影色
	var imgshadow=false;//画像陰影

	//色替え
	var colorChg=false;
	var colortype="rainbow";//rainbow rondam #FF0000

	//画像
	var img=assets[14];//アルファチャンネル画像
	var img_alpha=1;
	var fcolors=["#708090","#BBC8E6","#D2B4BC","#FDDEA5","#20B2AA","#CC7EB1","#F4B3C2","#FF69B4"];
	var fcolor=fcolors[Math.floor(Math.random()*fcolors.length)];

	//インスタンス配列取得
	//CanvasW,H,サイズ,フォント,文字色,ライン色,アウトライン幅,虹色,スペース,陰影色,陰影,画像,画像透明度,文字,base表示,line表示
	textChip2=createMoveOutlineTextCanvas_D(100,100,"80px","Impact",fcolor,lcolor,outline_w,true,text_spc,scolor,true,img,img_alpha,imgshadow,logostring,base,line);

	var textlen=logostring.length;

	//ランダム配置のため全幅の計算を先に
	for (var i=0; i < textlen; i++) {
		logotext_W +=textChip2[i].width;
		if(i < textlen) {logotext_W +=text_spc;}
	}
	//コンテナ中央ランダムのため速く決めた
	if (center) {logotextcontainer.x=(canvasWidth-logotext_W)/2;}

	//逆転フラグ
	var chg_v=Math.floor(Math.random()*2);
	if (chg_v < 1) {chg_v=-1;}

	//パターン番号
	var pattern_no=Math.floor(Math.random()*3);
	var alpha_no=1;
	var scale_no=1;
	var rotate_no=Math.floor(Math.random()*3)*chg_v;

	//移動
	var k=0;
	var flag=-1;

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

		//addChild
		logotextcontainer.addChild(textChip2[i]);
		//ポジション取得
		textPosx2[i]=textChip2[i].x;
		textPosy2[i]=textChip2[i].y;

		//全幅計算は上で行っている
		//logotext_W +=textChip2[i].width;
		//if(i < textlen) {logotext_W +=text_spc;}

		//移動
		//左右
		if (pattern_no == 0) {
			textChip2[i].x=canvasWidth*flag;
			textChip2[i].y=textPosy2[i];//その場
			alpha_no=1;
			scale_no=1;
		}
		//ランダム
		if (pattern_no == 1) {
			//globalToLocal
			var point=logotextcontainer.globalToLocal(Math.random()*canvasWidth,Math.random()*canvasHeight);
			textChip2[i].x=point.x;
			textChip2[i].y=point.y;
			alpha_no=0;
			scale_no=Math.floor(Math.random()*3)+1;//1-3
		}
		//その場
		if (pattern_no == 2) {
			textChip2[i].x=textPosx2[i];
			textChip2[i].y=textPosy2[i];
			alpha_no=0;
			scale_no=3;
		}

		//rotation
		textChip2[i].rotation=rotate_no*180;
		//alpha scale
		textChip2[i].alpha=alpha_no;
		textChip2[i].scaleX=scale_no;
		textChip2[i].scaleY=scale_no;

		k ++;
		flag *=-1;
	}

	//コンテナ中央
	if (center) {logotextcontainer.x=(canvasWidth-logotext_W)/2;}
	logotextcontainer.y=130;

	//Tween
	for (var i=0; i < textlen; i++) {
		//Tween
		var twn2=createjs.Tween.get(textChip2[i])
		.wait(200*i+1000)
		.to({x:textPosx2[i],y:textPosy2[i],scaleX:0.8,scaleY:0.8,alpha:1,rotation:0},1000)
		.wait(400).to({scaleX:1,scaleY:1},500);
		if(colorChg) {twn2.wait(500).call(color_chg,[colortype]);}
		twn2.wait(500).call(textshadow2)
		.call(finshmove2);//現在何もしない
	}

}

//MOVE-画像修飾Outlineテキストインスタンスを作る2
//reg原点中央補正コンテナ収容
//CanvasW,H,サイズ,フォント,文字色,ライン色,アウトライン幅,虹色,スペース,陰影色,陰影,画像,画像透明度,文字,base表示,line表示
function createMoveOutlineTextCanvas_D(CanvasW,CanvasH,size,font,fcolor,lcolor,outline_w,rainbow,space,scolor,shadow,img,imgalpha,imgshadow,str,base,line) {

	var fontdata=size + " " + font;

	var chip=[];
	var len=str.length;
	var tpos_x=0;
	var tpos_y=0;

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

		//1文字
		var text=str.charAt(i);

		//コンテナ
		var contna=new createjs.Container();

		//虹色
		if (rainbow) {
			fcolor=createjs.Graphics.getHSL(i/len*360,100,50);//直接
		}

		//文字インスタンスを作る
		var t=new createjs.Text("",fontdata,fcolor);
		//1文字入れる
		t.text=text;
		t.name="base";
		t.colorno=""+parseInt(i/len*360);//虹色番号文字
		//幅高さ
		var w=t.getMeasuredWidth();
		var h=t.getMeasuredHeight();

		//base原点中央
		t.textAlign="center";
		t.textBaseline="middle";
		if (shadow) {t.shadow=new createjs.Shadow(scolor,0,0,4);}//陰影

		//base表示
		if(!base) {t.visible=false;}

		//位置
		tpos_x +=w/2;//half
		contna.x=tpos_x;
		contna.y=tpos_y;//0

		//fill画像
		var canvas=document.createElement("canvas");
		canvas.width=CanvasW;
		canvas.height=CanvasH;
		var ctx=canvas.getContext("2d");

		//トリミング画像、X、Y、幅、高さ、
		var trimming_img=imageTrimmingCanvas(img,tpos_x,0,CanvasW,CanvasH,0,0,CanvasW,CanvasH);//X位置をずらした画像を得る
		var pattern=ctx.createPattern(trimming_img,"repeat");
		ctx.fillStyle=pattern;
		ctx.font=fontdata;
		ctx.textAlign="center";
		ctx.textBaseline="middle";
		ctx.globalAlpha=imgalpha;

		if (imgshadow) {set_shadow (ctx,scolor);}//陰影
		//fill
		ctx.lineWidth=outline_w;
		ctx.fillText(text,CanvasW/2,CanvasH/2);
		var img_txt=new createjs.Bitmap(canvas);
		img_txt.name="image";
		//原点中央
		img_txt.regX=CanvasW/2;
		img_txt.regY=CanvasH/2;

		//line
		var canvas=document.createElement("canvas");
		canvas.width=CanvasW;
		canvas.height=CanvasH;
		var ctx=canvas.getContext("2d");
		ctx.strokeStyle=lcolor;
		ctx.font=fontdata;
		ctx.textAlign="center";
		ctx.textBaseline="middle";
		ctx.lineJoin="miter";
		ctx.miterLimit=outline_w/2;

		if (shadow) {set_shadow (ctx,scolor);}//陰影
		//stroke
		ctx.lineWidth=outline_w;
		ctx.strokeText(text,CanvasW/2,CanvasH/2);
		var line_txt=new createjs.Bitmap(canvas);
		line_txt.name="line";
		//原点中央
		line_txt.regX=CanvasW/2;
		line_txt.regY=CanvasH/2;
		//base表示
		if(!line) {line_txt.visible=false;}

		//位置加算
		tpos_x +=(w/2+space);//half+space

		contna.width=w;
		contna.height=h;
		//contna.addChild(base_txt,img_txt,line_txt);
		contna.addChild(t,img_txt,line_txt);

		//コンテナ
		chip[i]=contna;
	}
	//戻り配列
	return chip;
}

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

//TEXT陰影処理1
function textshadow() {
	//base表示
	this.getChildByName("base").visible=true;

}
//TEXT陰影処理2
function textshadow2() {
	//
}

//色替
function color_chg(colortype) {

	if(!colortype) {return}//指定なし
	//保存虹色番号
	var no=this.getChildByName("base").colorno*1;
	if(colortype == 'rainbow'){this.getChildByName("base").color=createjs.Graphics.getHSL(no,100,50);
	} else if(colortype == 'random'){this.getChildByName("base").color=createjs.Graphics.getHSL(Math.floor(Math.random()*360),100,50);
	} else {this.getChildByName("base").color=colortype;}//指定色
}

//終了
function finshmove () {
	//
}
//終了2
function finshmove2 () {
	//
}

//reset_text
function reset_text() {

	set_text("クリア");
	myhitBtn.visible=false;

	//コンテナの中を削除
	maintextcontainer.removeAllChildren();
	logotextcontainer.removeAllChildren();

	//調整
	setTimeout(function() {
		set_text("ランダムアニメ実行中");
		set_prologue();
	},1000);

}

//tickステージ
function tick() {
	stage.update();
}
//VIEWTEXT
function set_text(t) {
	viewtext.text=t;
}

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

//create-text未使用
function create_text(size,font,color,string) {

	var fontdata=size + " " + font;
	var t=new createjs.Text("",fontdata,color);
	t.text=string;
	var w=t.getMeasuredWidth();
	var h=t.getMeasuredHeight();
	//大きさ設定、受け渡しに重要
	t.width=w;
	t.height=h;
	//原点中央
	t.regX=w/2;
	t.regY=h/2;
	return t;

}
//Create-Bottunボタンを作る
function set_btn() {

	//ラベル文字生成
	var label="CLICK";
	//x,y,w,h,r,c,label,lc,overc,outc
	myhitBtn=createbtn (0,0,60,20,5,"#FFFFFF",label,"#FF0000","#48D1CC","#FFFFFF");
	myhitBtn.cursor="pointer";
	myhitBtn.x=(canvasWidth-60)/2;
	myhitBtn.y=0;
	//クリック
	myhitBtn.addEventListener("click",reset_text);
	//addChild
	btncontainer.addChild(myhitBtn);

}

//create-bottunベタ塗り
function createbtn (x,y,w,h,r,c,label,lc,overc,outc) {

	//BTNコンテナ
	var btn=new createjs.Container();
	btn.x=x;
	btn.y=y;
	var s=new createjs.Shape();
	//角丸
	s.graphics.s(0).beginFill(outc).drawRoundRect(x,y,w,h,r);
	btn.addChild(s);
	//myBtn shadow onMouseOverでupdate()すると濃くなる
	//テキスト以外で使用は注意
	btn.shadow=shadow;
	var tx=new createjs.Text(label,"12px Arial",lc);
	tx.x=w/2;
	tx.y=3;
	tx.maxWidth=w;
	//tx.lineWidth=w;
	tx.textAlign="center";
	tx.shadow=shadow;//テキストは濃くなら無い
	tx.name="btntext";//name挿入
	btn.addChild(tx);
	//文字の食み出し防止mask
	tx.mask=s;

	//rollover
	btn.addEventListener("rollover",function () {
		s.graphics.clear();
		//角丸
		s.graphics.s(0).beginFill(overc).drawRoundRect(x,y,w,h,r);
		stage.update();
	});
	//rollout
	btn.addEventListener("rollout",function () {
		s.graphics.clear();
		//角丸
		s.graphics.s(0).beginFill(outc).drawRoundRect(x,y,w,h,r);
		stage.update();
	});
	return btn;
}

//RGB数値を#000000形式に変換/下と同じ
function getHexString(r,g,b) {
	var color="#"+("0"+parseInt(r).toString(16)).slice(-2)+("0"+parseInt(g).toString(16)).slice(-2)+("0"+parseInt(b).toString(16)).slice(-2);
	return color;
}

//RGB数値を#000000形式に変換
function getHexStringX(r,g,b) {

	var data=[r,g,b];
	var color="#";
	for (var i=0; i < 3; i++) {
		color +=hexstr(data[i]);
	}
	return color;

	function hexstr(v) {
		var txt=v.toString(16);
		txt="00"+txt;
		var str=txt.substring(txt.length-2);
		return str;
	}

}

//Textに陰影Blur4
function set_shadow (ctx,color) {

	//RGB変換
	rgbArr=toRgb(color);

	//Textに陰影
	//影の色オフセット距離ぼかし量
	//ctx.shadowColor="rgb(0,0,0)";

	//Graphics.getRGB利用した
	ctx.shadowColor=createjs.Graphics.getRGB(rgbArr[0],rgbArr[1],rgbArr[2]);//OK
	ctx.shadowOffsetX=0;
	ctx.shadowOffsetY=0;
	ctx.shadowBlur=4;//3-5
}

//変換は配列で返す
function toRgb(bc) {
	bc=bc.replace("#","");
	var rgbArr=[];
	rgbArr[0]=parseInt(bc.slice(0,2),16);
	rgbArr[1]=parseInt(bc.slice(2,4),16);
	rgbArr[2]=parseInt(bc.slice(4,6),16);
	return rgbArr;
}

//--------------------------------------------------------------------------------------
//LinearGradientBox
//幅、高さ、色1、色2、色3、方向(x.y)、タイプ(2.3)
function createLineGradBox (w,h,color1,color2,color3,direction,type) {

	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");

	//LinearGradient
	var gradient;
	if(direction == 'x') {
		gradient=ctx.createLinearGradient(0,h,w,h);
	}
	if(direction == 'y') {
		gradient=ctx.createLinearGradient(w,0,w,h);
	}
	if(direction == 'xy') {
		gradient=ctx.createLinearGradient(0,0,w,h);
	}
	if(type == 2) {
    		gradient.addColorStop(0,color1);
    		gradient.addColorStop(1,color2);
	}
	if(type == 3) {
    		gradient.addColorStop(0,color1);
		gradient.addColorStop(0.5,color2);
    		gradient.addColorStop(1,color3);
	}
	ctx.fillStyle=gradient;
	//FILL
	ctx.fillRect(0,0,w,h);

	return canvas;
}
//--------------------------------------------------------------------------------------
//画像埋め込みTEXTcanvasを作る
//幅、高さ、文字種、サイズ、パタン画像、透明度、ストリング
function createImageTextCanvas (w,h,font,fsize,patternimg,alpha,text) {

	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");

	var font_v=fsize +" "+ font;

	if(patternimg) {
		var pattern=ctx.createPattern(patternimg,"repeat");
		ctx.fillStyle=pattern;
	} else {
		ctx.fillStyle="#000000";
	}

	ctx.font=font_v;
	ctx.textAlign="center";
	ctx.textBaseline="middle";
	ctx.globalAlpha=alpha;
	ctx.fillText(text,w/2,h/2);

	return canvas;
}

//トリミング画像、X、Y、幅、高さ、
function imageTrimmingCanvas(patternimg,sx,sy,sw,sh,dx,dy,dw,dh) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=sw;
	canvas.height=sh;
	var ctx=canvas.getContext("2d");
	ctx.drawImage(patternimg,sx,sy,sw,sh,dx,dy,dw,dh);

	return canvas;
}

//幅、高さ、画像
function createImgCanvas(w,h,patternimg) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.drawImage(patternimg,0,0,w,h);

	return canvas;
}

//色背景つき画像
//全幅、全高さ、背景色、画像幅、画像高さ、画像
function createColorImgCanvas(w,h,c,imgw,imgh,img) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=c;
	ctx.fillRect(0,0,w,h);
	ctx.drawImage(img,0,0,imgw,imgh);

	return canvas;
}

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

//START
init();

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


CSS

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


/*日本語 createJS097.css*/

#demo-wrap {
position:relative;
width:auto;
height:320px;
text-align:center;
}

#image-box {
/*position:absolute;*/
position:relative;
top:0;left:0;
width:640px;
height:300px;
padding:0;
margin:0 auto;
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:#000000;
}

#image-box #mainCanvas {
border-radius:10px;
}
#btn-box {
width:640px;
height:50px;
margin:10px auto;
padding:0;
}

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

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


 

簡単な説明


[説明図]

上から、サンプル1、サンプル2、共に画像装飾テキストをアニメーションさせています。


 

CreateJS Canvasエレメント描画のOUTLINEテキスト


Canvasエレメント描画の問題

Canvasエレメントで直接描画すると、結構自由な装飾が可能ですから、テキストを画像で塗りこむことも可能です。
CanvasエレメントをBitmap()で表示する場合、Chrome(とChromeエンジンのOpera)で陰影がつかない、などの問題が出ますが「Chrome」は多く利用されているのでどうしても補正したいものです。


1. CanvasエレメントをBitmap()で表示する場合、Chrome(ChromeエンジンのOpera)で陰影がつかない。
CreateJS Shadowクラスを利用しないで、構造をかえて直接Canvas処理で陰影処理をする。
2. OUTLINEの幅が大きいと文字が壊れるので修正する。
Canvasエレメント描画のアウトラインテキストは lineJoin で簡単に修正処理できる。

 

この、画像装飾OutlineテキストLOGOのアニメ、シミュレーションを実行できます。

 

構造と陰影処理を替える

画像装飾、Canvasエレメント構成TEXTの構造になります。
コンテナラップの中の要素を個別に制御できるようにしています。


 

MAIN-TEXT (サンプル1)

図の様に、Chrome(ChromeエンジンのOpera)で陰影がつかないため、アウトライン1つを2つのCanvasエレメントで構成して、下のCanvasエレメントに陰影をつけ、表示非表示の切り替えで陰影を処理するのが特徴。
上のCanvasエレメントには画像をcreatePattern()でパターン化して塗りこみます。
陰影処理にCreateJS Shadowクラスを利用していません。どんな用途に使用しても構いません。


LOGO-TEXT (サンプル2)

3層構造で、上がCanvasエレメント描画アウトライン1つ、下2層は通常のテキストですが、一番下はCreateJS Textクラスで構成しています。アウトラインは通常の着色です。(改造すれば画像塗りこみ可能)
アウトラインが壊れないように、lineJoin で修正処理できる様にしたものです。


LOGO-TEXTは次の様に設定して、デザイン形態を替えることが可能です。(シミュレーション参照)


	//LOGOテキストアニメーション
	var text_spc=0;//テキストスペース
	var outline_w=2;//アウトライン幅

	//ベース表示,アウトライン表示,陰影
	var base=true;//ベース表示
	var line=true;//アウトライン表示
	var lcolor="#FFFFFF";//アウトライン色
	var shadow=true;//陰影
	var scolor="#000000";//陰影色
	var imgshadow=false;//画像陰影

OUTLINEの幅が大きいと文字が壊れるのを修正

文字によりけりではあるが、上図の様に、OUTLINEの幅が大きいと文字が壊れるが、修正は lineJoin で簡単である。
但し、「Textクラス」でOUTLINE文字を描画した場合はまだ修正できないので、「Canvasエレメント描画アウトライン文字」にする。(将来は修正できるであろう?)


鋭角部分の描画を途中で止める、MAIN-TEXTの例。


ctx.lineJoin="miter";
ctx.miterLimit=outline_w/2;

数値は状況に応じ変更ください。


Canvasエレメントの大きさ

下図はCanvasエレメントの大きさと、描画される画像の関係図である。(ここでの画像サイズは、640x100)


 

Canvasエレメントよりはみ出す描画はカットされるので、Canvasエレメントの大きさは陰影などを考慮した大きさにしなければならない。但し塗りこむ画像の原点は、Canvasエレメントの左上になるのでこの点も考慮する。
この例では簡単に 50x50 の大きさにした。文字の大きさに応じて個別に計算してCanvasエレメントの大きさを決定しても構わない(文字の大きさを先に計算しなければならないので2重手間になる)。


描画用の画像は、少し大きめのほうが良い。使用する位置の調整は可能です。 画像が小さい場合は文字が欠けたり、表示されませんので注意ください(Safariではエラーになる)。


Canvasエレメントの大きさをより大きくしても、塗りこむ画像位置は異なるが、動作などは余り変化は無いようです。



var canvas=document.createElement("canvas");
canvas.width=幅;
canvas.height=高さ;
var ctx=canvas.getContext("2d");

処理を書く

Elementの大きさは最初に決定する。途中で変更は出来ないので注意ください。


● 異なる大きさの「Canvasエレメント」を重ねる。
陰影を描画する「Canvasエレメント」を大きくして、画像塗りこみの「Canvasエレメント」を小さくして重ねても、文字の中心が同じであれば問題は無い。つまり、画像塗りこみの位置あわせが楽になるかも知れない。


● 同じパターンの画像塗りこみ。
各文字に対して同じパターンの画像塗りこみをする場合は、画像は「Canvasエレメント」の大きさがあれば良い。
画像トリミングを省略できる、また画像をつくれば「画像読み込み」が不要のメリットがある(上図参照)。
// 現在の処理



//トリミング画像、X、Y、幅、高さ、
var trimming_img=imageTrimmingCanvas(img,tpos_x,0,CanvasW,CanvasH,0,0,CanvasW,CanvasH);//X位置をずらした画像を得る
var pattern=ctx.createPattern(trimming_img,"repeat");
ctx.strokeStyle=pattern;

// 処理変更


createLineGradBox関数で、受け渡しグラデーションパターン画像を作る
var img=createLineGradBox(50,50,"#FFFFFF","#C71585","#FFFFFF","y",2);

//CanvasW,H,サイズ,フォント,色,アウトライン幅,虹色,スペース,陰影色,陰影,画像,画像透明度,文字,base表示
textChip=createMoveOutlineTextCanvas_C(50,50,"40px","Arial",......,img,...);

-----------------------------------------------------------------------

//画像を受け取る
var pattern=ctx.createPattern(img,"repeat");
ctx.strokeStyle=pattern;

グラデーション画像は手軽に作れるし、目的に応じて作り変えればよい。この辺は自由です。


Canvasエレメントの表示

「Canvasエレメント」を CreateJS で表示する場合は Bitmap() に取り込むと表示できるので便利ですが....


1. Chrome(ChromeエンジンのOpera)で、Shadowクラス陰影がつかない(shadowフィルター)。
2. 描画を替えるときは「Canvasエレメント」そのものを描画し直さなければならない。


上記のデモJSでは、陰影のついた「Canvasエレメント」を下層に配置して表示非表示の切り替えで制御できるようにした。描画を替える事も可能だが、ここでの必要性はないので止めておく。



Tween

.wait(500).call(textshadow)

----------------------------------------------------------------

//TEXT陰影処理1
function textshadow() {
	//base表示
	this.getChildByName("base").visible=true;

}

アニメ終了後の色変更

Logoテキストの例ですが、一番下のテキスト層の色を変更しますので、画像に透明度設定をしているか、あるいは透過画像(アルファチャンネル画像など)である事が条件です。

この辺は各自のアイデアなどで作りかえればよい。



//色替え
var colorChg=false;
var colortype="rainbow";//rainbow rondam #FF0000

----------------------------------------------------------------

//色替
function color_chg(colortype) {

	if(!colortype) {return}//指定なし
	//保存虹色番号
	var no=this.getChildByName("base").colorno*1;
	if(colortype == 'rainbow'){this.getChildByName("base").color=createjs.Graphics.getHSL(no,100,50);
	} else if(colortype == 'random'){this.getChildByName("base").color=createjs.Graphics.getHSL(Math.floor(Math.random()*360),100,50);
	} else {this.getChildByName("base").color=colortype;}//指定色
}

描画用の画像を「Canvasエレメント」で作る

原則、描画用の画像をLoadして使用するようにしていますが、グラデーション画像などは「Canvasエレメント」で作ったほうが簡単です。この辺の関数は工夫しておくと以外に便利です。
以下、createLineGradBox()関数での作例を示す....



//グラデーション画像
img=createLineGradBox(640,100,"#FFFFFF","#C71585","#FFFFFF","y",2);
img=createLineGradBox(640,100,"#FFD700","#2E8B57","#FFD700","y",2);
img=createLineGradBox(640,100,"#00CED1","#FFFFFF","#00CED1","y",3);

//透過グラデーション画像
img=createLineGradBox(640,100,"rgba(255,255,255,0)","rgba(0,0,0,1)","rgba(255,255,255,0)","y",2);
img=createLineGradBox(640,100,"rgba(0,0,0,0)","rgba(255,255,255,1)","rgba(0,0,0,0)","y",2);
img=createLineGradBox(640,100,"rgba(0,0,0,1)","rgba(255,255,255,0)","rgba(0,0,0,1)","y",3);

円形グラデーション用

簡単な円形グラデーションの場合は次のように作れますので、参考のために掲載します。
ここでは高さ 100 にしていますが 200-300 位が良いかも知れない、食み出し部分はカットされますので問題はありません。(テキスト装飾は上の線形が主で、円形は余り使わないでしょう)
使用例


//幅、高さ、色1、色2、タイプ、0中心、4隅1-4
img=createRadialGradBox (640,100,"#DB7093","#555555",0);


//RadialGradientBoxGradient
//幅、高さ、色1、色2、タイプ(0-4)
function createRadialGradBox (w,h,color1,color2,type) {

	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//タイプ修正
	if(!type){type=0;}
	if(type > 4){type=0;}

	//RadialGradient
	var px=[w/2,0,w,w,0];
	var py=[h/2,0,0,h,h];
	var x=px[type];
	var y=py[type];
	var r=w*0.5;
	if(type > 0) {r=w;}
	var gradient;
	gradient=ctx.createRadialGradient(x,y,20,x,y,r);

    	gradient.addColorStop(0,color1);
	gradient.addColorStop(1,color2);

	ctx.fillStyle=gradient;
	//FILL
	ctx.fillRect(0,0,w,h);

	return canvas;
}

Textクラスの将来

現在はほとんど簡単な処理のみで複雑な処理は出来ない。将来は機能がふえると思いますが、詳細は不明である。
一応、上記例のごとく「Canvasエレメント」の操作によりテキストなどを装飾しているが、スコブル面倒である。


使用画像

原則、画像は使用者が用意します。640x100 使用画像はデモページにあります。


当方の参照記事など

「前ページ」画像装飾OUTLINEテキストアニメーションですが、見た目では違いは余り判らないと思います。

【参照】当方の記事: CreateJS Canvasエレメント描画のOUTLINEテキストアニメーション



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

CreateJSは結構「仕様」が変わりますので特に注意が必要です。


スコブル面倒、テキストアニメーションをする人はAS3でもほとんど居ないのが現状で、興味を持つのはアタマがエラーしているからです。(ワタシのアタマはとっくの昔にエラー状態!、何とかなりません?)
以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]