メニューを閉じる

テクノデジタルグループ

メニューを開く

2017.08.01

プログラミング

javascriptでADV風文字表示 その2

こんにちは、新卒のshiroです。
前回の最後に「あとは整形や装飾をしたり、デモの様に改行もできるようにしたりするとより良いものになると思います。」と書いたので、今回はそれらを作っていこうと思います。

具体的に
表示速度の変更
文字の装飾
を行っていきます。
(リンクからそれぞれの内容に飛べます)

まずは前回のコードを確認しましょう。
……と言いたいところなのですが、前回から若干コードが変わっています。

新しくなったコードは以下の通りです。

前回書いたbodyの先頭に1文追加します。

開始

以下はjavascript部分のみですが少々長いので、コメントは省略しています。

var source = "吾輩は猫である。名前はまだ無い。...",
	chars = [],
	charNum = 0,
	outputChars = [],
	textBlock = "";

	var clearText = function() {
		chars = [];
		outputChars = [];
		charNum = 0;
		textBlock = source;
		textArea.innerHTML = "";
		splitText();
	}

	var splitText = function() {
		chars = textBlock.split("");
		setOutput();
	}

  var setOutput = function(){
		for(let num = 0; num < chars.length; num++) {
			outputChars.push(chars[num]);
		}
		printText();
	}

	var printText = function(){
		let timer = setTimeout(printText,150);
		if(!(typeof outputChars[charNum] === "undefined")) {
			textArea.innerHTML += outputChars[charNum];
			charNum++;
		} else {
			clearTimeout(timer);
		}
	}

	var printAllText = function(){
		if(charNum <= outputChars.length) {
			charNum = outputChars.length + 1;
			textArea.innerHTML = textBlock;
		}
	}

	window.addEventListener("DOMContentLoaded", function() {
		textArea = document.querySelector("#text");
		textArea.addEventListener("click",printAllText,false);
	},false
);

やっていることは基本的に前回とあまり変わりません。
ですが、これで開始をクリックする度に文章が初期化されます。

では、本題に入ります。

表示速度の変更

こちらはさほど複雑ではありません。
aタグの隣あたりに


を追加します。

そしてwindow.addEventListenerのtextAreaの下に

textSpeed = document.querySelector("#speed");

を追加してからprintTextのtimerを

setTimeout(printText,textSpeed.value);

に変更します。

これで終わりです。
実際にブラウザでバーを左右に動かすと速度が変わるのがわかると思います。

文字の装飾

装飾は文中にタグを埋め込むことで作成することにします。
タグの記述方法は”[命令]”(””は未記入)とします。

まずsourceにタグを埋め込んでみましょう。
また、それに合わせて数か所変更します。

変数

var source = "吾輩は[font-weight:bold; color:#ff0000;]猫[end]である。名前は[color:rgb(255,0,0);]まだ[end]無い。[br]どこで生れたかとんと[font-weight:bold;]見当[end]がつかぬ。何でも[color:#f00;]薄暗い[end]じめじめした所で[font-style:oblique;]ニャーニャー[end]泣いていた事だけは[color:rgba(255,0,0,0.3)]記憶[end]している。吾輩はここで始めて人間というものを見た。...",
chars = [],
//タグ用の配列を追加
tags = [],
charNum = 0,
outputChars = [],
textBlock = "";

clearText

var clearText = function() {
		chars = [];
		tags = [];
		outputChars = [];
		charNum = 0;
		textBlock = source;
		textArea.innerHTML = "";
		splitText();
	}

先ほどのsourceに入っているタグの説明をします。
これらは改行を除き、どこにどのcss(css3準拠)を当てるのかを示すことが主な目的です。
そのため、下表以外のタグも作成可能です。

タグ 説明 備考
[br] 改行 endタグ不要。同一タグ内に他内容の記載不可。
[font-weight:bold;] フォントを太字にする
[color:#ff0000;] フォントの色を変える #xxxxxxは#xxxやrgb(www,xxx,yyy)、rgba(www,xxx,yyy,z.z)と書ける。
[font-style:oblique;] フォントを斜体にする アルファベットの場合はitalicにした方がいい。
[end] 装飾の終端

次にsplitTextを書き換えます。

var splitText = function() {
		//タグを配列で取得
		tags = textBlock.match(/(\[.+?\])/g);
		//タグの個所を"_"(アンダーバー)で置換
		textBlock = textBlock.replace(/\[.+?\]/g,"_");
		//文字単位で分割
		chars = textBlock.split("");
		replaceTags();
	}

3行目の”/(\[.+?\])/g”は正規表現で、[命令]に該当する全てを取得する命令です。
“.+?”は”.”で任意の1文字が、”+”で1文字以上ある、”?”最小範囲を取得する命令です。
前後に[]があるため、[]内の範囲が該当します。
[]はそのままでは文字と認識されないため、それぞれの前に”\”(バックスラッシュ)が必要です。
これを()でくくり、範囲を明示します。
5行目では()がなくなっていますが、こちらでも可能です。

末尾のgがついていない場合、最初の1回処理がで終了してしまいます。

表示する文字を決定するsetOutputに行く前に、処理を二つ追加します。

//タグの囲いを[]から<>に変換形式に変換
var replaceTags = function() {
		let num = 0;
		for(let tag of tags) {
			if(tag == "[br]" || tag == "[end]") {
					//タグの中身がbrまたはendのとき
					tags[num] = tag.replace(/\[(.+?)\]/g,"<$1>");
			} else {
					//cssを適用するものはspan要素に変更
					tags[num] = tag.replace(/\[(.+?)\]/g,"<span style='$1'>");
			}
			num++;
		}
		replaceText();
	}

ここでは置換先の文字に$1というものが出てきました。
これは()内に合致した文字列を置くことを表しています。

ちなみに(?:正規表現)と書くと、合致する箇所を探しつつキャプチャしないということが可能です。
これを使えば、必要ない部分を除くこともできます。

//タグを先ほど置換したアンダーバーと置き換える
var replaceText = function() {
		let replaceCharNum = 0,
		tagsNum = 0;
		for(let char of chars) {
			if (char == "_") {
				chars[replaceCharNum] = char.replace(/_/g,tags[tagsNum]);
				textBlock = textBlock.replace(/_/,tags[tagsNum]);
				tagsNum++;
			}
			replaceCharNum++;
		}
		//一括表示用の文章も置換
		textBlock = textBlock.replace(/\<end\>/g,"</span>");
		setOutput();
	}

 

setOutputで最終的な出力内容を決定します。

//出力する文字列を決定
var setOutput = function(){
		for(let num = 0; num < chars.length; num++) {
			if (chars[num] == "<br>"){
				chars[num + 1] = chars[num] + chars[num + 1];
			} else if (chars[num] == "<end>") {
				//<end>は出力しない
				continue;
			} else if (chars[num].match(/^\<.+?\>.+\<.+?\>$/)) {
				//<span 装飾>文字</span>の場合
				outputChars.push(chars[num]);
			} else if (chars[num].match(/^\<.+?\>$/)) {
				//<span 装飾>の場合、<end>の前まで各文字に装飾を付ける
				let fontEnd = 1;
				while(chars[num + fontEnd] != "<end>") {
					//javascriptでは自動で閉じタグを補完してくれるが、ここでは明示的につけている
					chars[num + fontEnd] = chars[num] + chars[num + fontEnd] + "</span>";
					fontEnd++;
				}
			} else {
				outputChars.push(chars[num]);
			}
		}
		printText();
	}

 

これで装飾部分が終了です。

今回は正規表現の勉強もかねて少々面倒な記述を行いましたが、テキスト内にHTMLタグを埋め込めば処理が楽になるでしょう。

EOF.


【記事への感想募集中!】

記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!
  • こんな記事が読んでみたい、こんなことが知りたい、調べてほしい!という意見も募集中!
  • いただいた感想は今後の記事に活かしたいと思います!

感想フォームはこちら


【テクノデジタルではエンジニア/デザイナーを積極採用中です!】

下記項目に1つでも当てはまる方は是非、詳細ページへ!
  • 自分でアプリを作ってみたい
  • ITで世の中にワクワクを生み出したい
  • 使いやすさ、デザインにこだわったWebサイトを開発したい

採用情報の詳細はこちら


Qangaroo(カンガルー)

  • 徹底した見やすさと優れた操作性で、テストの「見える化」を実現。
  • テストの進捗が見える。開発がスマートに進む。
  • クラウド型テスト管理ツール『Qangaroo(カンガルー)』

【テクノデジタルのインフラサービス】

当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。

https://www.tcdigital.jp/infrastructure/

最近の記事