2025.08.29
Laravelで空判定にif文を使うとハマる理由
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つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
1
2025.08.29
Laravelで空判定にif文を使うとハマる理由
2

2025.08.29
Git SSH接続でfetch/pullができなくなった時の対処法
3

2025.08.28
【体験談】Amazon Linux 2でMySQLインストール時のOpenSSL・GPG key エラーにハマった話
4
2025.08.28
【AWS】SSMポートフォワーディングとInstance Connectを利用したプライベートEC2へのSSH接続手順
5
2025.07.24
Log::info()が使えない!?Laravel.logのPermission denied エラーを解決する(Docker環境)
タグ検索