
文字列抽出をひな形に応用してみます。
文字列はオブジェクトです。DHTMLによりHTMLドキュメント上のほぼ全てのものがオブジェクトとして操作できるようになっています。これをDOM(ドキュメントオブジェクトモデル)といいます。DHTMLからはDOMのプロパティやメソッドを使用することができます。DOMのプロパティを設定することにより、DHTML で HTML ページの外観を制御できます。
実際にsStrings=new String()でストリングオブジェクトを作成することができます。ここではややこしくなるのでこれ以上はやめておきましょう。ひな形で使用することも余りないでしょう。
文字列は共通のメンバとしていくつかのプロパティやメソッドを持っています。前回のsplit()もメソッドです。その内
文字列オブジェクトの持つプロパティとメソッド
constructor プロパティ | length プロパティ | prototype プロパティ
anchor メソッド | big メソッド | blink メソッド | bold メソッド | charAt メソッド | charCodeAt メソッド | concat メソッド | fixed メソッド | fontcolor メソッド | fontsize メソッド | fromCharCode メソッド | indexOf メソッド | italics メソッド | lastIndexOf メソッド | link メソッド | match メソッド | replace メソッド | search メソッド | slice メソッド | small メソッド | split メソッド | strike メソッド | sub メソッド | substr メソッド | substring メソッド | sup メソッド | toLowerCase メソッド | toUpperCase メソッド | toString メソッド | valueOf メソッド
今回はcharAt()メソッドを使用します。
sStrings.charAt(n)・・・nは取り出す文字の 0 から数えたインデックス番号を指定します。指定できる値の範囲は、0 から文字列の長さより 1 小さい値までの範囲です。有効ではない範囲の値を指定した場合、空の文字列を返します。sStringsは取り出し元となる文字列です。
例)
"こんにちは".charAt(2)・・・"に"という文字列を返り値にします。
前回の歌詞表示で更に改造をしましょう。色の変化をする部分はとりあえず置いて、文字列から一文字だけ抽出するcharAt()メソッドの利用です。今回は先に完成ひな形をお目にかけましょう。
ソースに解説を付けておきます。
【ソース】
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<head>
<meta
http-equiv="content-type" content="text/html; charset=shift_jis">
<META
http-equiv="Content-Style-Type" content="text/css">
<title></title>
</head>
<body
style="margin:0px; padding:0px;">
<!--
今回は歌詞表示ステージエレメントであるkasistageは少し変えています。ドロップシャドウで文字に影を落とします。背景色は設定しないように。-->
<div
id="kasistage" style="padding:10px; position:absolute; z-index:2;
left:20px; top:0px; color:white; font-size:14pt; font-style:italic; width:800px;
height:300px; filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=2,OffY=2,Color=#888888,Positive=true)"></div>
<input
type="button" name="b1" value="演奏開始" onclick="bgmstart()"
style="position:absolute; left:400px; top:10px; z-index:3">
<bgsound
id="bgs" src="kazetatinu_gs.mid" volume="-200"
loop="1">
<script>
var sound=bgs.src
bgs.src=""
var
kasi=new Array()
//kasi[0]とkasi[1]も少し追加しました。
kasi[0]="0,10,14,22,30,37,52,66,74,89,103,110,118,125,132,140,143,162,177,191,199,206,213,221,228,234,241,248,256,264,267,287".split(",")
kasi[1]="松田聖子「風立ちぬ」,
,風立ちぬ 今は秋,今日から私は 心の旅人, ,涙顔見せたくなくて スミレひまわりフリージア,高原のテラスで手紙
風のインクでしたためています,SAYONARA SAYONARA SAYONARA・・・,振り向けば色づく草原
一人で生きてゆけそうね,首に巻く赤いバンダナ もう泣くなよとあなたがくれた,SAYONARA
SAYONARA SAYONARA・・・,風立ちぬ 今は秋,帰りたい帰れない あなたの胸に,風立ちぬ
今は秋,今日から私は 心の旅人,【間奏】, ,性格は明るいはずよ スミレひまわりフリージア,心配はしないでほしい
別れはひとつの旅立ちだから,SAYONARA SAYONARA SAYONARA・・・,草の葉に くちづけて,忘れたい忘れない
あなたの笑顔,想い出に目を伏せて,夏から秋への 不思議な旅です, ,風立ちぬ 今は秋,帰りたい帰れない
あなたの胸に,風立ちぬ 今は秋,今日から私は 心の旅人,【End】, ,stop".split(",")
var
fl=0
var sTime,mTime//sTimeとsmTime変数を確保
function bgmstart(){
if(fl!=0)return
fl=1
bgs.src=sound
kasistage.innerHTML=""
kpoint=0
mTime=(sTIme=new
Date()).getTime()
nowgetTime()
kasiView()
}
var
gTime,nTime
function nowgetTime(){
if(fl==0)return
nTime=(gTime=new
Date()).getTime()
//繰り返し時間を短めにしています
setTimeout("nowgetTime()",200)
}
//次のmObjはinnerHTMLで追加したspanエレメントを配列オブジェクトに格納するために設けています。配列にすることでmObj[インデックス番号]のような形式でエレメントを扱うことができるからです。
var
mObj=new Array()
var bcs=1//微調整用(秒)整数。これは歌詞表示の時間を調整するためのものです。
function
kasiView(){
if(Math.floor((nTime-mTime)/1000)>=kasi[0][kpoint]-bcs){
if(kpoint==0){//kpointが0の時のみ太字にするために
kasistage.innerHTML+='<span
id="sp'+kpoint+'" style="font-weight:bold;
color:rgb(255,255,0)"></span><br>'
}else{
kasistage.innerHTML+='<span
id="sp'+kpoint+'" style="color:rgb(255,0,0)"></span><br>'
}
//次の式で配列要素として追加したspanエレメントを代入しています。当然mObj[kpoint]は[object]になります。
mObj[kpoint]=eval("sp"+kpoint)
mf[kpoint]=0//これは文字抽出の位置を示すポインタとなります。最初はインデックス番号1からなので0です。
//次の式は文字を一文字ずつ追加して表示する際のsetTimeoutの時間を計算しています。
mjs[kpoint]=Math.floor(700*(kasi[0][kpoint+1]-kasi[0][kpoint])/kasi[1][kpoint].length)
//mojinはspanエレメントのinnerHTMLとして表示させる文字列を入れるものです。最初は空白にしておきます。
mojin[kpoint]=""
moji(kpoint)//文字を一文字ずつ追加して表示させる関数moji()を実行させます。kpointは引数に渡す値になります。
mcolor[kpoint]=0//これは文字色を変化させる値です。これが0〜255まで変化します。
mcolorChange(kpoint)//文字色変化関数実行です。kpointは引数に渡す値
kpoint++
if(kpoint==kasi[1].length){
kpoint=0
fl=0
return
}
}
setTimeout("kasiView()",200)//少し繰り返し時間を短くしました。
}
var
mf=new Array()//文字抽出位置ポインタ用
var
mjs=new Array()//moji関数繰り返し時間用
var
mojin=new Array()//spanエレメントのコンテンツとして表示させる歌詞の文字列を入れるもの
function
moji(n){//文字を一文字ずつ追加して表示させる関数
//歌詞番号nがkasi[1].lengthと同じになると歌詞はもうありません。また一行の歌詞の文字数と抽出する位置ポインタが同じになると文字はもうありません。returnで抜けます。
if(n==kasi[1].length||mf[n]==kasi[1][n].length)return
//mojin[歌詞番号]に歌詞文字列から指定位置の文字をひとつだけ抽出して連結します
mojin[n]+=kasi[1][n].charAt(mf[n])
mObj[n].innerHTML=mojin[n]//spanエレメントにinnerHTMLで歌詞をセットします(表示)
mf[n]++//抽出位置ポインタをひとつ大きくします
//繰り返し処理します。mjs[n]はkasiView()関数で予め計算された繰り返しタイマー時間です
setTimeout("moji("+n+")",mjs[n])
}
//以下は色変わり部分ですので説明省略します。
var
mcolor=new Array()
function mcolorChange(n){
if(n==0)return
if(n==kasi[1].length-1||fl==0||mcolor[n]>=252){
mObj[n].style.color="rgb(255,255,255)"
return
}
if(mcolor[n]>=255)return
mcolor[n]+=255/((kasi[0][n+1]-kasi[0][n])*20)
if(mcolor[n]>255)mcolor=255
if(n<5){
mObj[n].style.color="rgb(255,255,"+Math.round(mcolor[n])+")"
setTimeout("mcolorChange("+n+")",40)
return
}
if(n<17){
mObj[n].style.color="rgb(255,"+Math.round(mcolor[n])+","+Math.round(mcolor[n])+")"
setTimeout("mcolorChange("+n+")",40)
return
}
if(n<24){
mObj[n].style.color="rgb("+Math.round(mcolor[n])+",255,"+Math.round(mcolor[n])+")"
setTimeout("mcolorChange("+n+")",40)
return
}
mObj[n].style.color="rgb("+Math.round(mcolor[n])+","+Math.round(mcolor[n])+",255)"
setTimeout("mcolorChange("+n+")",40)
}
</script>
</body>
</html>
上の歌詞表示は少し難しいかな?ということでタイプライタ風のメッセージで色変わりするひな形を作成したいと思います。
文字列操作のメソッド(文字列オブジェクトのメソッド)をいくつか説明しておきますね。★マークは文字列あるいはStringオブジェクトを示します。
・★.substr(開始位置,取り出す文字数)・・・開始位置は一番目の文字が0のインデックス番号です。取り出す文字数を指定したいときに便利です。取り出す文字数を省略すると最後の文字まで取出しが行われます。取り出す文字数に 0 または負の値を指定すると、長さ 0 の文字列 ("") が返されます。
例)
"スクリプト講座".substr(3,2)・・・先頭文字(ス)を0とするので、インデックスが3の文字は"プ"ですね。その"プ"から2文字を抜き出すので、"プト"となります。
・★.substring(start,end)・・・開始位置及び終了位置はインデックス番号です。文字列内の指定された位置にある文字列を返します。substring メソッドの戻り値は、start から end の前の文字までを含む文字列です。substring メソッドでは、引数 start と引数 end のうち値の小さい方が取得する文字列の先頭位置になります。たとえば strvar.substring(0, 3) メソッドと ★.substring(3, 0) メソッドは同じ文字列を返します。引数 start または end のいずれかが NaN または負である場合は、0 に置き換えられます。取得した文字列の長さは、2 つの引数の差の絶対値になります。たとえば、★.substring(0, 3) メソッドと ★.substring(3, 0) メソッドで返される文字列の長さは 3 になります。startとendは共に省略できません。
NaNは数値ではないという特殊な値です(非数値)。
例)
"スクリプト講座",substring(3,5)・・・インデックス3からインデックス5までの文字列である"プト講"を返します。
・★.slice(start,end)・・・開始位置及び終了位置はインデックス番号です。文字列内の指定された位置にある文字列を返します。slice メソッドは、★で指定した文字列内の指定した部分が格納された String オブジェクトを返します。slice メソッドは、引数 end で指定した要素の 1 つ前の要素までをコピーします。引数 start に負の値を指定した場合、length + start として処理されます。length は文字列の長さです。引数 end に負の値を指定した場合、length + end として処理されます。length は文字列の長さです。省略した場合は、★で指定した文字列の最後までが取り出されます。end が start の前で発生した場合、文字は新しい文字列にコピーされません。
sliceとsubstringの違いは、sliceがendに負の数値を指定すると後ろからインデックスを指定できることです。一番最後の文字は後ろからの場合0になります。後ろから二番目は-1となります。
例)
"スクリプト講座面白い".slice(5,-1)・・・インデックス番号5の文字は"講"ですね。endが-1の位置にある文字は後ろからのインデックス番号が1である"白"です。従って"講座面白"という文字列を返すことになります。
それからこのひな形では16進数で表される文字列を10進数に変換する必要が出てくるので、説明しておきます。parseInt()はGlovalオブジェクトのメソッドですが、Global オブジェクトは、直接使用されることはなく、new 演算子を使って作成することもできないオブジェクトです。このオブジェクトは、スクリプト エンジンが初期化されるときに作成され、そのメソッドとプロパティはその時点からすぐに使用可能になります。メソッドはobject.メソッド()という形式をとらずにメソッドを直接呼び出して使用します。
・parseInt(numString, radix)・・・numStringは数値変換する前の文字列です。radixは変換前の文字列の基数である進数値を指定します。numStringは省略できません。radixは2 〜 36 の範囲の値を指定します。省略した場合、先頭に "0x" または"0X"が付いている文字列は 16 進数、"0" が付いている文字列は 8 進数と見なされます。これ以外の文字列は、10 進数と見なされます。parseInt メソッドは、引数 numString に含まれる数値と等しい整数を返します。引数 numString の先頭に整数がない場合は、NaN (not a number) を返します。
例)
parseInt("ff66",16)・・・"ff66"を16進数とみなして数値変換します。返される値は10進数となります。・・・65382
parseInt("ff66#33",16)・・・65382
parseInt("#ff66",16)・・・NaN(数値ではない)
parseInt("0xff66")・・・65382
status=parseInt("0xff66",2)・・・先頭の0のみが評価されてしまうので、0になる。
尚、文字列には検索メソッドであるindexOf()やlastIndexOf()がありますが、ここでは使用しません。またの機会に説明したいと思います。
前置きはここまで。基本ソースを示しますね。
<html>
<head>
<title></title>
<style></style>
</head>
<body
style="margin:0px; overflow:hidden">
<textarea id="f1"
rows="7" cols="101" style="position:absolute; visibility:hidden;
z-index:2">ここにメッセージを書いてください。,行区切りはカンマを使います。,,OE編集画面ではこのテキストフィールドが表示され、書き換えが可能ですが、,プレビュー画面では見えなくなります。,rgb1・・・文字色初期値,rgb2・・・文字色終了値,cinc・・・色変わりの変化量,rTime・・・タイプライタの速度(ミリ秒),cTime・・・色変わりの速度(ミリ秒),,,end</textarea>
<div
id="div1" style="padding:10px; background-color:#444444;
width:700px; height:500px; position:absolute; left:20px; top:10px; z-index:1;overflow:auto;
color:white"></div>
<script>
var rgb1="#ff66ff"//最初の文字色
var
rgb2="#99eecc"//色変わり最後の文字色
</script>
</body>
</html>
複数行テキスト入力ボックスとしてtextareaエレメントを作成します。idはf1としています。CGIなどで何かするわけではありませんのでname属性は付けていません。このテキストエリアはOutlookExpressの編集画面でメッセージ書き換えができるようにするためにz-indexをタイプライタ表示ボックスであるdiv1エレメントのz-indexよりも大きくしています。プレビュー画面ではテキストエリアを表示する必要はないので、visibility:hiddenにしています。visibility:hiddenは編集画面では無効になりますので、編集画面でテキストエリアが消えることはありません。
スクリプト部分ですが、とりあえず使用する側がソース画面で文字色設定ができるようにコメント説明入りで変数に代入する用意をしています。rgb1とrgb2はHTMLカラーコード(#つきの16進数6桁)でなければなりません。
rgb1とrgb2のカラーコードから赤(R)・緑(G)・青(B)の値を10進数に変換するプログラムを組みます。これは色変化に使用します。
まずrgb1とrgb2共に#が付いているので#を除きます。substr()メソッドで一番最初の文字を除いた残りの文字列をrgb1とregb2に代入しなおします。
rgb1=rgb1.substr(1)
rgb2=rgb2.substr(1)
substrで取り出す文字数を省略していますから第一引数である1つまりはインデックス番号1の文字から最後までを得ることができます。インデックス番号1は二番目の文字ですね。二番目の文字から最後までの文字列を取り出してます。
rgb1とrgb2には6桁の16進数表記の文字列が入っていることになりますね。その内容は二桁ずつの赤・緑・青各色の16進数コードになっています。そこで二文字ずつ取り出して数値に変換します。
var sr=parseInt(rgb1.substr(0,2),16)
rgb1.substr(0,2)・・・先頭文字(インデックス0)から2文字だけ抜き出しますね。その抜き出した文字列は"ff"などの二桁16進数になる文字列です。これを数値変換します。抜き出した文字列は16進数なので基数は16です。parseInt()メソッドで16進数として数値変換します。srには10進数の値が入ります(スクリプトでは16進数の場合0xが付いていなければならないので、付いていないということは10進数扱い)。
同様に
var sg=parseInt(rgb1.substr(2,2),16)
var sb=parseInt(rgb1.substr(4,2),16)
var
er=parseInt(rgb2.substr(0,2),16)
var eg=parseInt(rgb2.substr(2,2),16)
var
eb=parseInt(rgb2.substr(4,2),16)
これらももうわかりますね。ゆっくり考えてください。
次に行うのはテキストエリアの内容(内部コンテンツであるtext)から、カンマ区切りでメッセージを取り出します。カンマで区切ったのは文字列分割して表示したいためです。
var tx=f1.innerHTML.split(",")
txは配列になることになります。split()は区切り文字で分割された配列文字列を返すからですね。txはインデックスが0からtx.length-1までの要素としての文字列を持つことになります。下のような形で文字列が入っていることになります。
tx[0]・・・"ここにメッセージを書いてください。"
tx[1]・・・"行区切りはカンマを使います。"
tx[2]・・・""
tx[3]・・・""
・・・
tx[tx.length-1]・・・end
txの要素数はtx.lengthですね。
次はdiv1エレメントに文字列を改行を加えながら表示するための汎用エレメントを追加します。汎用エレメントですがdivではなくspanを使用します。spanはdivと違い、ブロック要素ではないので、改行を伴いません。divを使用してもいいのですが、ここではspanを使用して改行のために<br>エレメントも追加します。
div1.innerHTML=""
for(i=0;i<tx.length;i++){
div1.innerHTML+='<span
style="font-weight:bold; font-family:'+"'MS 明朝'"+'line-height:18pt;
font-size:12pt; color:rgb('+sr+','+sg+','+sb+')"></span><br>'
}
for〜文でtxの要素数分(インデックス0からスタートすることに注意!!)spanとbrエレメントをdiv1エレメントのinnerHTMLプロパティで設定します。インデックスの最後はtx.length-1なので、i<tx.lengthとなります。i<=tx.length-1でもOKです。
spanエレメントにはidをつける必要がありません。このことは後の説明でわかります。spanエレメントはfontに関するスタイルシートなど書いておきました。こぉr
'〜〜color:rgb('+sr+','+sg+','+sb+')〜〜<br>'のところ注意くださいね。いつもの文字列と変数の内容の連結です。最後に<br>が付いています。
これで文字列数分のspanエレメントが作成できました。このspanエレメントに対しインデックス番号で簡単にアクセスできるよう、配列オブジェクトにspanエレメントを入れます。
var tObj=div1.all.tags("span")
allはオブジェクト(ここではdiv1エレメント)のサブエレメントのコレクションですね。その内tag名が"span"であるものだけをtObjの配列に入れます。
object.Tags(tagName)・・・タグ名がtagNameのエレメントを参照する。
これで一番最初のspanエレメントはtObj[0]になりますし、一番最後のspanエレメントはtObj[tObj.length-1]となります。tObj.lengthはtx.lengthと同じですから、最後のspanエレメントはtObj[tx.length-1]でも同じです。
tObj[0]・・・tx[0]の内容を表示するためのspanエレメント
tObj[1]・・・tx[1]の内容を表示させるためのspanエレメント
tObj[2]・・・tx[2]の内容を表示させるためのspanエレメント
・・・
tObj[tx.length-1]・・・tx[tx.length-1]の内容を表示させるためのspanエレメント。
次はタイプライタ用に表示させる文字列を入れる器mt[n]と文字列抽出する位置を記憶させるmpoint[n]を確保します。
var mt=new Array()
var mpoint=new Array()
わからないでしょう。mtはタイプライタのように表示させるために文字を一文字ずつ追加しながらspanエレメントのinnerHTMLとして表示させるものです。文字列の総数に対応させるために配列にしています。
mpointも配列です。インデックスn番の文字列tx[n]から抜き出す位置を記憶させるためのものです。
ここまででタイプライタの準備は整いました。タイプライタは最初にtxのインデックス番号0からスタートですね。スタート関数を作成しましょう。引数tgでこれにスタート時の番号0を渡して実行させます。setTimeoutを使用すれば時間をおいて実行が可能になります。クリックスタートならsetTimeoutの代わりにonclick="mtstart(0)"ですが、二重実行防止処置をしてくださいね。イベントで実行させる時は常にイベントが何度も引き起こることを考慮しておきましょう。
function mtstart(tg){
}
setTimeout("mtstart(0)",2000)
mtstart(tg)はtgに文字列インデックス(txのインデックス)を渡してその番号にあたるspanエレメントにメッセージを表示させるものです。tgがとる最大値は?
そう最後の番号はtx.length-1ですね。ということはもしtgがtx.length-1よりも大きくなったらこのmtstart(tg)関数は抜ける必要があります。tgがtx.length-1より大きくなるのはtgがtx.lengthに等しくなる時なのでif(tg==tx.length)return
function mtstart(tg){
if(tg==tx.length)return
}
これで一安心です。文字列tx[tg]から文字を一文字だけ取り出したいのですが、取り出す位置を示すmpoint[tg]の初期値は0になります。最初は一番先頭文字から抜き出しますから。また取り出した文字を入れる器であるmt[tg]は空白にしておきましょう。
function mtstart(tg){
if(tg==tx.length)return
mpoint[tg]=0
mt[tg]=""
}
さてこのスタート関数から実際にタイプライタ表示させる関数を実行します。関数を作りますが、やはりインデックス番号に対応した引数を持つ関数にします。この関数をmtstart()kン数から実行させます。インデックス番号を示すtgを引数として渡します。
タイプする関数をmsgtype()とし、引数をmnとしました。
function mtstart(tg){
if(tg==tx.length)return
mpoint[tg]=0
mt[tg]=""
msgtype(tg)
}
function
msgtype(mn){
}
さてtx[mn]から文字を抜き出すことが可能なのはどういった場合でしょうか?tx[mn]に入っている文字列の最後の文字のインデックス番号は?
そうtx[mn].length-1ですね。一文字抜き出す際の位置がこの値以下であれば抜き出すことが可能です。抜き出しできるときとできない時で処理をするために、if〜else〜を使用します。
function msgtype(mn){
if(mpoint[mn]<tx[mn].length){
}else{
}
}
抜き出すことができなくなった場合を考えます。抜き出せなくなったら次の文字列に処理を変えますね。つまり現在の文字列インデックス番号を一つ増やしてから、mtstart()関数にその値を引数に渡して実行させます。このときもsetTimeoutで時間をおいてあげましょう。使用者がこの時間を調整できるように変数にしました。
var rTime=200//次の文字列に移る時間(ミリ秒)
function
msgtype(mn){
if(mpoint[mn]<tx[mn].length){
}else{
setTimeout("mtstart("+(mn+1)+")",rTime)
}
}
さあ一番肝心の一文字抜き出してspanエレメントのコンテンツとしてテキスト表示させる処理です。
例えばtx[0]・・・"ここにメッセージを書いてください。"から一文字ずつ抜き出します。最初は先頭文字から抜き出すので、mpoint[0]は0になっていなければなりませんね。この時tx[0].charAt(mpoint[0])は"ここにメッセージを書いてください。".charAt(0)ですから、"こ"が抜き出されます。これをmt[0]に加算連結します。mt[0]は最初に""状態ですから(""はNULL・文字数0の文字列)、mt[0]+=tx[0].charAt(mpoint[0])・・・これでmt[0]は"こ"になります。
このmt[0]の内容をtObj[0]のinnerhTMLプロパティでHTMLテキストコンテンツとして設定しますと、表示されるわけです。
この後mpoint[0]++で文字抽出位置ポインタmpoint[0]は1になります。tx[0].charAt(mpoint[0])は"ここにメッセージを書いてください。".charAt(1)となり、mt[0]は"こ"+"こ"になります。このようにしてtx[0]の三頭から順番に一文字だけを抜き出していきながらそれを連結していけばタイプライタのようになります。
一般化して考えましょう。
tx[mn]から一文字だけ抜き出します。抜き出す位置はmpoint[mn]が示しています。抜き出した文字は表示に使用する文字列を入れるmt[mn]に追加します。追加なので+=を使用しましょう。
function msgtype(mn){
if(mpoint[mn]<tx[mn].length){
mt[mn]+=tx[mn].charAt(mpoint[mn])
}else{
setTimeout("mtstart("+(mn+1)+")",rTime)
}
}
mt[mn]には表示させる文字列が入っています。これをspanエレメントにinnerHTMLで設定します。spanエレメントはtObj[mn]でよかったですね。またこの処理が終わったらmpoint[mn]は次の文字を抜き出すためにインクリメントさせましょう。一文字取り出して表示し、また一文字取り出して表示・・・の繰り返しですからsetTimeoutでこのmsgtype()関数を繰り返させます。繰り返し時間は先ほどのrTimeを利用しましょうか。そうするとコメントもわかりやすく変えたほうがいいですね。
var rTime=200//次の文字列に移る時間、タイプ速度(ミリ秒)
function
msgtype(mn){
if(mpoint[mn]<tx[mn].length){
mt[mn]+=tx[mn].charAt(mpoint[mn])
tObj[mn].innerHTML=mt[mn]
mpoint[mn]++
setTimeout("msgtype("+mn+")",rTime)
}else{
setTimeout("mtstart("+(mn+1)+")",rTime)
}
}
タイプライタは一応完成です。まだ色変化がありますが、とりあえずここまでのサンプルを見てみましょう。
では色変化プログラムを追加していきましょう。
var sr=parseInt(rgb1.substr(0,2),16)
var sg=parseInt(rgb1.substr(2,2),16)
var
sb=parseInt(rgb1.substr(4,2),16)
var er=parseInt(rgb2.substr(0,2),16)
var
eg=parseInt(rgb2.substr(2,2),16)
var eb=parseInt(rgb2.substr(4,2),16)
上のスクリプトによりsr,sg,sbには初期文字色が赤・緑・青に分けて入っており、er,eg,ebには変化終了時の色がやはり赤・緑・青に分けて入っています。
ここで赤に対して考えてみます。もしsrが100でerが255であったとします。この場合赤はsrからerへと数値が増えて行くようにします。逆にsrが200でerが50であった場合は、srからerへと数値が減っていきますね。
色変化量をvar cinc=2//色の変化量(正の整数で、余り大きくしないで)として設定できるようにしてみます.。赤の変化量をrsetとすると・・・
もしsr<erならばrset=cincとし、そうでなければrset=-cincとします。これで加算になるか減算になるか設定できますね。
他の色も同様です。この部分を部分処理として関数にしました。同じ処理を行う部分的な処理はメインのプログラムから独立させて、別の流れにすると流れが見やすくなり、プログラムが簡潔になりやすくなります。このようなメインのプログラムに対し、メインプログラムからその時々で呼び出して処理するプログラムの塊をサブルーチンといい、メインの流れの処理部分をメインルーチンといいます。サブルーチンはほとんどが関数になっています。cset()関数は引数であるscとecの大きさを比較して、戻り値をcincか-cincかどちらかにします。
function cset(sc,ec){
if(sc<ec){
return
cinc
}else{
return
-cinc
}
}
呼び出し元は次のようになります。
var rset=cset(sr,er)
var gset=cset(sg,eg)
var
bset=cset(sb,eb)
各行は関数cset()にそれぞれ色の初期値と最終地を引数として渡して処理させます。関数の戻り値がrset,gset,bsetに入ります。
これで各色は加算するのか減算するのかの値rset,gset,bsetとしてセットできました。
色を変化させる関数をmcChange()とします。これもやはりspanエレメントそれぞれに対応させますから(spanエレメントのstyle.colorプロパティを変えます)、インデックス値を引数にさせます。引数をtcとしすると、mcChange(tc)という関数ができますね。この関数はどこから実行させるかを考えます。
色変化が始まるのはそのspanエレメントでのタイプライタが終わった時にしましょう。更にインデックスに対し、それぞれの色を保存する配列を確保します。確保した配列ですが、最初の状態は各色の初期値です。sr,sg,sbを初期値にします。タイプライタが終わった時とは次のspanエレメントにタイプライタ処理が移る時です。setTimeout("mtstart("+(mn+1)+")",rTime)の直前でいいでしょう。
var mrc=new Array()
var mgc=new Array()
var mbc=new
Array()
function msgtype(mn){
if(mpoint[mn]<tx[mn].length){
mt[mn]+=tx[mn].charAt(mpoint[mn])
tObj[mn].innerHTML=mt[mn]
mpoint[mn]++
setTimeout("msgtype("+mn+")",rTime)
}else{
mrc[mn]=sr
mgc[mn]=sg
mbc[mn]=sb
mcChange(mn)
setTimeout("mtstart("+(mn+1)+")",rTime)
}
}
色変化はどういった処理になるかを赤にのみ絞って考えます。
まずmcChange(tc)で渡される値tcはspanエレメントの番号であることです。この番号はspanエレメントのインデックスであり、また色の保存をする配列のインデックスでもあります。
mrc[tc]はrsetだけ加算されます。rsetがマイナスなら結果減算になるわけですね。
mrc[tc]+=rset
rsetはcincか-cincであり、+なら加算され、-なら減算されます。
rsetが0以上ならば、sr<=erですから、mrc[tc]はいずれer以上になります。erが最終値である必要がありますね。ということは・・・
もしrset>=0ならば、mrc[tc]がer以上になったらmrc[tc]はerにしなければならない。
またrsetが0より小さい時はsr>erですから、mrc[tc]はいずれer未満になります。やはりerが最終値である必要があるので・・・・
もしrset>=0でないならば、mrc[tc]がerより小さくなったらmrc[tc]はerにしなければならない。
これを式にしましょう。
if(rset>0){
if(mrc[tc]>=er)mrc[tc]=er
}else{
if(mrc[tc]<=er)mrc[tc]=er
}
これは各色とも同様です。
mrc[tc]+=rset
mgc[tc]+=gset
mbc[tc]+=bset
if(rset>0){
if(mrc[tc]>=er)mrc[tc]=er
}else{
if(mrc[tc]<=er)mrc[tc]=er
}
if(gset>0){
if(mgc[tc]>=eg)mgc[tc]=eg
}else{
if(mgc[tc]<=eg)mgc[tc]=eg
}
if(bset>0){
if(mbc[tc]>=eb)mbc[tc]=eb
}else{
if(mbc[tc]<=eb)mbc[tc]=eb
}
さあこれで色の値は計算できました。後はspanエレメントのstyle.colorプロパティとして色をセットしましょう。
tObj[tc].style.color="rgb("+mrc[tc]+","+mgc[tc]+","+mbc[tc]+")"
色の変化を終了するのはどういうときかも必要ですね。各色の保存値mrc[tc],mgc[tc],mbc[tc]全てがそれぞれer,eg,ebと等しくなった時ですね。mrc[tc]==er且つmgc[tc]==eg且つmbc[tc]==ebの時です。且つというのは論理積です。&&論理演算子を使用します。
if(a&&b&&c)・・・a,b,c全てがtrueの時
if(mrc[tc]==er&&mgc[tc]==eg&&mbc[tc]==eb)return
色変化は上の条件式に当てはまらない場合、引き続き繰り返し処理しなければなりません。上の式に当てはまればreturnで抜けるのですから、当てはまらない場合は次のステートメントに処理が移ります。従って上の処理の後ろに繰り返し処理を入れればOKでしょう。繰り返し時間も使用者が設定しやすくします。cTimeという変数に設定できるようにしました。
var cTime=300//色変化速度(ミリ秒)
setTimeout("mcChange("+tc+")",cTime)
ではまとめます。
【ソース】
<html>
<head>
<title></title>
<style></style>
</head>
<body
style="margin:0px; overflow:hidden">
<textarea id="f1"
rows="7" cols="101" style="position:absolute; visibility:hidden;
z-index:2">ここにメッセージを書いてください。,行区切りはカンマを使います。,,OE編集画面ではこのテキストフィールドが表示され、書き換えが可能ですが、,プレビュー画面では見えなくなります。,rgb1・・・文字色初期値,rgb2・・・文字色終了値,cinc・・・色変わりの変化量,rTime・・・タイプライタの速度(ミリ秒),cTime・・・色変わりの速度(ミリ秒),,,end</textarea>
<div
id="div1" style="padding:10px; background-color:#444444; width:700px;
height:500px; position:absolute; left:20px; top:10px; z-index:1;overflow:auto;
color:white"></div>
<script>
var rgb1="#ff66ff"//最初の文字色。#に続く16進数6桁カラーコード。
var
rgb2="#99eecc"//色変わり最後の文字色。#に続く16進数6桁カラーコード。
var
cinc=2//色の変化量(正の整数で、余り大きくしないで)
var rTime=200//次の文字列に移る時間、タイプ速度(ミリ秒)
var
cTime=300//色変化速度(ミリ秒)
rgb1=rgb1.substr(1)
rgb2=rgb2.substr(1)
var
sr=parseInt(rgb1.substr(0,2),16)
var sg=parseInt(rgb1.substr(2,2),16)
var
sb=parseInt(rgb1.substr(4,2),16)
var er=parseInt(rgb2.substr(0,2),16)
var
eg=parseInt(rgb2.substr(2,2),16)
var eb=parseInt(rgb2.substr(4,2),16)
var
tx=f1.innerHTML.split(",")
function cset(sc,ec){
if(sc<ec){
return
cinc
}else{
return -cinc
}
}
var rset=cset(sr,er)
var
gset=cset(sg,eg)
var bset=cset(sb,eb)
div1.innerHTML=""
for(i=0;i<tx.length;i++){
div1.innerHTML+='<span
style="font-weight:bold; font-family:'+"'MS 明朝'"+'line-height:18pt;
font-size:12pt; color:rgb('+sr+','+sg+','+sb+')"></span><br>'
}
var
tObj=div1.all.tags("span")
var mt=new Array()
var mpoint=new
Array()
var mrc=new Array()
var mgc=new Array()
var mbc=new Array()
function
mtstart(tg){
if(tg==tx.length)return
mpoint[tg]=0
mt[tg]=""
msgtype(tg)
}
function
msgtype(mn){
if(mpoint[mn]<tx[mn].length){
mt[mn]+=tx[mn].charAt(mpoint[mn])
tObj[mn].innerHTML=mt[mn]
mpoint[mn]++
setTimeout("msgtype("+mn+")",rTime)
}else{
mrc[mn]=sr
mgc[mn]=sg
mbc[mn]=sb
mcChange(mn)
setTimeout("mtstart("+(mn+1)+")",rTime)
}
}
function
mcChange(tc){
mrc[tc]+=rset
mgc[tc]+=gset
mbc[tc]+=bset
if(rset>0){
if(mrc[tc]>=er)mrc[tc]=er
}else{
if(mrc[tc]<=er)mrc[tc]=er
}
if(gset>0){
if(mgc[tc]>=eg)mgc[tc]=eg
}else{
if(mgc[tc]<=eg)mgc[tc]=eg
}
if(bset>0){
if(mbc[tc]>=eb)mbc[tc]=eb
}else{
if(mbc[tc]<=eb)mbc[tc]=eb
}
tObj[tc].style.color="rgb("+mrc[tc]+","+mgc[tc]+","+mbc[tc]+")"
status=tObj[tc].style.color
if(mrc[tc]==er&&mgc[tc]==eg&&mbc[tc]==eb)return
setTimeout("mcChange("+tc+")",cTime)
}
setTimeout("mtstart(0)",2000)
</script>
</body>
</html>
</script>
</body>
</html>
次回はこの色変わりスクリプトを改造したひな形をいくつか紹介します。