ひな形スクリプト講座2

 

[ひな形スクリプト講座1][ひな形スクリプト講座2][ひな形スクリプト講座3][ひな形スクリプト講座4][ひな形スクリプト講座5][ひな形スクリプト講座6][ひな形スクリプト講座7][ひな形スクリプト講座8][ひな形スクリプト講座9][ひな形スクリプト講座10][ひな形スクリプト講座11][ひな形スクリプト講座12][ひな形スクリプト講座13][ひな形スクリプト講座14][ひな形スクリプト講座15][ひな形スクリプト講座16][ひな形スクリプト講座17][ひな形スクリプト講座18][ひな形スクリプト講座19][ひな形スクリプト講座20][ひな形スクリプト講座21][ひな形スクリプト講座22][ひな形スクリプト講座23][ひな形スクリプト講座24][ひな形スクリプト講座25][ひな形スクリプト講座26][ひな形スクリプト講座27][ひな形スクリプト講座28][ひな形スクリプト講座29][ひな形スクリプト講座30][参考資料索引]

 

第一回での右端に移動は理解できましたでしょうか?今回は移動する速さを変えた場合のスクリプトに問題はないのか、また変数を使ってみようと思います。

第一回では移動する距離は1ピクセルずつでした。また繰り返し関数を実行するためのタイマーであるsetTimeout()のタイマー時間は0.1秒(100ミリ秒)でした。移動する速度を速くするには、移動する距離をもっと大きくするか、繰り返しさせるタイマーを小さくすることが考えられます。人で言えば足を交互に出す速さは変えないで、歩幅を大きくするか、交互に出す速さを速めるか、ということですね。歩幅は同じでも歩く時と走る時では移動速度が変わります。

では、まずタイマーを最速である0秒にしてみましょう。足を素早く動かす感じですね。

<html>
<head>
<title></title>
</head>
<body style="margin:0px; overflow:hidden">
<img id="img1" src="akiakane.gif" style="position:absolute; left:0px; top:100px">
<script>

function lidou(){
if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
img1.style.pixelLeft=img1.style.pixelLeft+1
status=img1.style.pixelLeft

setTimeout("lidou()",0)
}
}
lidou()
</script>
</body>
</html>

タイマー0秒

速くなりました。しかしこれ以上はタイマー時間を小さくできませんので、この方法ではこれ以上速くできないことになりますね。

それでは移動距離を1ピクセルから41ピクセルにしてみましょう。歩幅を変えるということになります。leftの増加量を+1から+41にすればいいので、以下のようになりますね。

<html>
<head>
<title></title>
</head>
<body style="margin:0px; overflow:hidden">
<img id="img1" src="akiakane.gif" style="position:absolute; left:0px; top:100px">
<script>

function lidou(){
if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
img1.style.pixelLeft=img1.style.pixelLeft+41
status=img1.style.pixelLeft

setTimeout("lidou()",0)
}
}
lidou()
</script>
</body>
</html>

増加量41ピクセル

ずいぶん速くなりました。これで右端で停止しているのでしょうか?右端ぴったりで停止しているように見える方は何度かウィンドウサイズを変えて表示してみてください。右端より右へずれて一部が隠れるようになっていませんか?

これはif条件分岐処理の条件式に問題があるからです。1ピクセルの場合は停止するのはimg1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthと等しくなった時です。img1.style.pixelLeftは1ピクセルずつ増加するので、img1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthよりも1小さい時にも処理が実行され、結果img1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthと等しくなります。するとこの時点で次に条件式img1.style.pixelLeft<document.body.clientWidth-img1.clientWidthがfalseになりますので、停止するわけですね。

41ピクセル増加の場合は、例えばimg1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthよりも10小さい場合でも処理が実行されますね。
ということはmg1.style.pixelLeftはdocument.body.clientWidth-img1.clientWidth-10+41になります。つまりmg1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidth+31ということですから、31ピクセル右にずれて表示されますね。

これをどのように処理するかを考えなければならなくなりました。

方法としてはいくつか考えられますが、document.body.clientWidth-img1.clientWidthとimg1.style.pixelLeftの差が41よりも小さい時は、41増加させるのではなくて、img1.style.pixelLeftをdocument.body.clientWidth-img1.clientWidthと等しくしてしまう。但し、img1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthと等しくなった時には処理を中止する。」という方法でいけそうな気がしますが、やってみましょう。

まず等しい時にはですが、JavaScriptではaとbが等しいという条件判断式はa==bと記述します。a=bではないので注意してくださいね。

ということで処理をしない条件式はif(img1.style.pixelLeft==document.body.clientWidth-img1.clientWidth)return

<script>
function lidou(){
if(img1.style.pixelLeft==document.body.clientWidth-img1.clientWidth)return

img1.style.pixelLeft=img1.style.pixelLeft+41
status=img1.style.pixelLeft

setTimeout("lidou()",0)
}
lidou()
</script>

更にdocument.body.clientWidth-img1.clientWidthとimg1.style.pixelLeftの差が41よりも小さい時は、img1.style.pixelLeftをdocument.body.clientWidth-img1.clientWidthと等しくする。という処理が必要ですから、そのままif条件分岐処理で記述しましょう。次のように考えられますね。
if(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<41){img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth}

<script>
function lidou(){
if(img1.style.pixelLeft==document.body.clientWidth-img1.clientWidth)return
if(
document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<41){img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth}
img1.style.pixelLeft=img1.style.pixelLeft+41
status=img1.style.pixelLeft

setTimeout("lidou()",0)
}
lidou()
</script>

さあこれでいいのでしょうか?試しに表示させてみましょう。

テスト表示・・・あれれ?まだおかしいようですね。右端からずれて隠れる部分があります。それどころかウィンドウサイズを変更するとそれに合わせてあきあかねのleftは変わります。スクリプトが動き続けているようです。

そもそもif(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<41){img1.style.pixelLeft=document.body.clientWidth-img1.clientWidthによって確かに一旦はimg1.style.pixelLeftがdocument.b]dy.clientWidth-img1.clientWidth}と等しくなりますが、次のimg1.style.pixelLeft=img1.style.pixelLeft+41もまだ有効ですぐにこの処理によってimg1.style.pixelLeftはdocument.body.clientWidth-img1.clientWidth+41という値になってしまいます。

更に処理を中止するimg1.style.pixelLeft==document.body.clientWidth-img1.clientWidthにも当てはまらなくなり、処理の中止が行われなくなります。あきあかね動いてはいないけどスクリプトはずっと動き続けているのです。
※処理中止するにはimg1.style.pixelLeft>=document.body.clientWidth-img1.clientWidthという条件式にすればいいのですが、ここでは敢えてmg1.style.pixelLeft==document.body.clientWidth-img1.clientWidthとして対処してみます。

結論ですが、「もしdocument.body.clientWidth-img1.clientWidthとmg1.style.pixelLeftの差が41よりも小さい時は、41増加させるのではなくて、img1.style.pixelLeftをdocument.body.clientWidth-img1.clientWidthと等しくしてしまう。」の41増加させるのではなくての部分が欠けているのですね。

ここでif〜条件分岐構文の新しい形式登場です。次々と新しいことが出てきて面白いですね。

もし条件式がtrueならば処理1を実行する。もし条件式がfalseならば処理2を実行する。
if(条件式){
処理1
}
else{
処理2
}

この構文はこんな構造です。
if(条件式)
{処理1}
else
{処理2}
elseはそうでなければと覚えましょう。

この構文に当てはめて考えてみましょう。もしdocument.body.clientWidth-img1.clientWidthとmg1.style.pixelLeftの差が41よりも小さい時はimg1.style.pixelLeftをdocument.body.clientWidth-img1.clientWidthと等しくする。そうではない時は41増加させる。このように考えられますね。

if(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<41){
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}
else{
img1.style.pixelLeft=img1.style.pixelLeft+41
}

これでテストしてみましょう。

<html>
<head>
<title></title>
</head>
<body style="margin:0px; overflow:hidden">
<img id="img1" src="akiakane.gif" style="position:absolute; left:0px; top:100px">
<script>

function lidou(){
if(img1.style.pixelLeft==document.body.clientWidth-img1.clientWidth)return
if(
document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<41){
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}
else{
img1.style.pixelLeft=img1.style.pixelLeft+41
}

status=img1.style.pixelLeft

setTimeout("lidou()",0)
}
lidou()
</script>
</body>
</html>

完成かな?・・・みたいですね。ウィンドウサイズを変更してテストしても右端で停止しますね。


今までは直接移動ピクセル数分を書いていましたね。1ピクセル増加+1や41ピクセル増加+41などです。では53ピクセル増加させる場合はどうしましょう?41のところを53に書き換えればいいわけですね。

<script>
function lidou(){
if(img1.style.pixelLeft==document.body.clientWidth-img1.clientWidth)return
if(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<53){
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}else{
img1.style.pixelLeft=img1.style.pixelLeft+53
}
status=img1.style.pixelLeft
setTimeout("lidou()",0)
}
lidou()
</script>

上記の場合は二箇所ありますから書き換えるのは面倒ではありませんが、もっとたくさんある場合は面倒ですね。一箇所書き換えるだけでいいように作り直してみましょう。

変数・・・変数とは値やオブジェクトなどなにかを入れる箱です。この箱はいつでも中身を入れ替えたり取り出したりできるようになっています。入れることができる内容は数値だけではなく、文字列や真偽値(trueやfalse)・式なども保管できます。スクリプト内でいつでも再利用できますので、利用することでソースが見やすくなったりすることもあります。

var 変数名=値・・・変数は基本的にはvarで宣言して使用しますが、varは省略することもできます。=値は変数に初期値を入れておきたい場合に使用します。代入演算子ですね。必ずしも初期値を入れておく必要はありません。変数名は関数名と同様に半角英数字を使用しますが、数字は先頭に使用してはいけません。尚、varはスクリプトで定義されているキーワードのひとつです。変数名や関数名にキーワードとまったく同じ名前を用いることもできません。
尚このようなJavaScriptで予め定義されている単語を予約語といいます。

さて、増加ピクセル数を変数に入れてソースを書き換えてみましょう。変数名は何でもいいですがここではixとしてみます(idouXの意味で)。

<script>
var ix=53
function lidou(){
if(img1.style.pixelLeft==document.body.clientWidth-img1.clientWidth)return
if(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<ix){
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}else{
img1.style.pixelLeft=img1.style.pixelLeft+ix
}
status=img1.style.pixelLeft
setTimeout("lidou()",0)
}
lidou()
</script>

ixには53という数値(文字の53ではなく)が入っていますので53という数値のところはixと書き換えることができますね。
これで増加数を変更したい時にはvar ix=53のところを書き換えるだけでよくなりました。


アプローチ2

今まではreturnを使用してもしimg1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthと等しい時は処理停止するという方法を使用しました。
第一回にもありましたようにもしimg1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthよりも小さい時には処理を実行するに変更してみましょう。この時やはり但しdocument.body.clientWidth-img1.clientWidthとmg1.style.pixelLeftの差がixよりも小さい時は、img1.style.pixelLeftをdocument.body.clientWidth-img1.clientWidthと等しくし、そうではない時にはixだけimg1.style.pixelLeftを増加するとしなければなりません。

構造は
もしimg1.style.pixelLeftがdocument.body.clientWidth-img1.clientWidthよりも小さい時には
処理を行う。
この処理内容は
{
もしdocument.body.clientWidth-img1.clientWidthとmg1.style.pixelLeftの差がixよりも小さい時は
img1.style.pixelLeftをdocument.body.clientWidth-img1.clientWidthと等しくする
そうではない時には
ixだけimg1.style.pixelLeftを増加する

}

<script>
var ix=53
function lidou(){
if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
if(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<ix){
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}
else{
img1.style.pixelLeft=img1.style.pixelLeft+ix
}

status=img1.style.pixelLeft
setTimeout("lidou()",0)
}
}
lidou()
</script>

中括弧のつけ方や位置・過不足に注意してくださいね。

アプローチ解答


コメント八スクリプトの動作に影響を与えるものではなく、変数の内容や処理の動作説明を入れるなど、ソースを見やすくし、説明文を入れるものです。スクリプトが実行される時にはコメント文は無視されるので、動作に関わりません。

一行コメントは//(スラッシュ二文字)で表します。行中にある//以降はコメントとして解釈されます
複数行に渡るコメントは/*(コメント開始)と*/(コメント終了)とで囲みます。

スクリプトを知らない人がソースを見るとixが変更可能で、増加ピクセル数であることはわかりませんね。また関数の動作もわかりません。コメントを入れて少しわかりやすくしましょう。

 <script>
/*
img1を右に動かすスクリプトです
画像が右端で停止します
*/

var ix=53//一度に動くピクセル数
function lidou(){//右移動する関数
if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
if(document.body.clientWidth-img1.clientWidth-img1.style.pixelLeft<ix){
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}else{
img1.style.pixelLeft=img1.style.pixelLeft+ix
}
status=img1.style.pixelLeft
setTimeout("lidou()",0)
}
}
lidou()//移動関数スタート
</script>


さてこんな簡単な右移動でもスクリプトの組み方は一通りではありません。もう解答はないのでしょうか?

条件式を整理し、別の解答を考えてみますね。

まず現在のleftの位置に増加ピクセル数だけ足した場合、この値が右端の停止予定位置をオーバーした場合について考えます。
オーバーするのは増加前のleftの位置が既に停止予定位置をオーバーしている場合か、オーバーしてはいないけれど増加ピクセル数だけ足すとオーバーしてしまう場合ですね。オーバーするという表現はここでは等しい場合も含めるとします。

ということはimg1.style.pixelLeftにixだけ足した値が停止予定位置document.body.clientWidth-img1.clientWidth以上になった場合、そうではない場合という条件分岐も考えられます。

if(img1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidth){処理1}else{処理2}
オーバーした場合処理1を実行し、オーバーしていない時は処理2を実行するとなります。

処理2の方はもう簡単でしょう。オーバーしない限りはixを足せばいいのですから。第一回に出てきたようにaの値にbを足してaに代入するにはa=a+bまたはa+=bですから、a+=bを使って簡潔にしましょう。

if(img1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidth){処理1}else{img1.style.pixelLeft+=ix}

オーバーした場合は二つに分けられますね。増加前のleftの位置が停止位置に達していない場合と既に到達している場合です。
達していない場合はleftを停止予定位置と等しくしますね。達している場合は停止させなければなりません。なにもしないで関数を抜けるのは・・・returnでしたね。

if(img1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidth){
   
if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth)
   {img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
   }
else{
   return
   }

}
else{
img1.style.pixelLeft+=ix
}

ということでスクリプトソースは次のようになります。

<script>
/*
img1を右に動かすスクリプトです
画像が右端で停止します
*/
var ix=53//一度に動くピクセル数
function lidou(){//右移動する関数
if(img1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidth){
   if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
       img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
   }else{
       return
   }
}else{
   img1.style.pixelLeft+=ix
}
status=img1.style.pixelLeft
setTimeout("lidou()",0)
}
lidou()//移動関数スタート
</script>

ではこれでうまくいくか試してみてください。

アプローチ3

 第三回は右端ではね返り、左移動させ、左端で停止させてみましょう。 


[ひな形スクリプト講座1][ひな形スクリプト講座2][ひな形スクリプト講座3][ひな形スクリプト講座4][ひな形スクリプト講座5][ひな形スクリプト講座6][ひな形スクリプト講座7][ひな形スクリプト講座8][ひな形スクリプト講座9][ひな形スクリプト講座10][ひな形スクリプト講座11][ひな形スクリプト講座12][ひな形スクリプト講座13][ひな形スクリプト講座14][ひな形スクリプト講座15][ひな形スクリプト講座16][ひな形スクリプト講座17][ひな形スクリプト講座18][ひな形スクリプト講座19][ひな形スクリプト講座20][ひな形スクリプト講座21][ひな形スクリプト講座22][ひな形スクリプト講座23][ひな形スクリプト講座24][ひな形スクリプト講座25][ひな形スクリプト講座26][ひな形スクリプト講座27][ひな形スクリプト講座28][ひな形スクリプト講座29][ひな形スクリプト講座30][参考資料索引]