
今回は少し難しい話から入ります。
前回の雪降りスクリプトですが、divエレメントの開始タグと終了タグの間にスクリプトを記述していました。document.write()はそのスクリプトがあるドキュメントの位置に書き出しします。そのためdivエレメントの子エレメントのコレクションにこのスクリプトエレメントも含まれてしまうことは説明済みです。
ところで、このdivエレメントは雪降り用のステージですから、場合によっては他のエレメントが入っているかもしれません。ステージ内に雪降りとは別の画像を配置したり、場合によってはメッセージを表示するためのエレメントを配置したいかもしれませんね。divエレメント内で雪降りを実現させましたが、勿論bodyに直接書き出して、bodyエレメント内で雪降りさせることもあるでしょう。そうすると子エレメントにはいろんなエレメントが含まれているかもしれませんね。
imgObj=stage.all
これはstageエレメントに含まれる全てのエレメントをコレクションとして配列オブジェクトに代入するものです。
<div id="stage" style="position:absolute;
left:10px; top: 10px; background-color:black; width:600px; height:500px; overflow:hidden">
<img
src="tree.gif" style="position:absolute; left:20px; bottom:10px;
z-index:200">
<script>
for(i=1;i<=20;i++){
document.write("<img
src='"+img1.src+"' style='position:absolute; left:-1000px; top:0px'>")
}
</script>
</div>
このようにdiv内に既にIMGエレメントが入っていたり、スクリプトエレメントがあるとimgObjの要素になってしまいます。このままですと、雪のエレメントを示すためのインデックス番号をいくつからにするかなど神経を使わなければなりません。そこで雪エレメントのみをimgObjに代入する方法を解説します。
stageエレメントの全てのエレメントはstage.all(n)で扱えます。nはコレクション番号です。このnは0から始まり、stageエレメントに含まれるエレメントの総数よりも1小さい値で終わります。含まれるエレメントが4つならば、0,1,2,3の4つの値になりますね。
含まれるエレメントの総数は?
allは含まれるエレメント全てを要素とするコレクションです。ということはエレメントの総数はこのコレクションの総数に同じであるはずです。コレクションの総数はlengthプロパティで表せることは以前にも説明しました。
含まれるエレメントの総数・・・stage.all.length
では一番最後のエレメントのインデックス番号は?
stage.all.length-1なんですね。
さてここでdocument.write("<img src='"+img1.src+"' style='position:absolute; left:-1000px; top:0px'>")を実行後を考えます。これは現在存在するサブエレメントよりも後ろの位置に記述されているのですから、書き出されたIMGエレメントはその時点で一番最後のエレメントになっています。
つまりimgObj[i]=stage.all[stage.all.length-1]をdocument.write("<img src='"+img1.src+"' style='position:absolute; left:-1000px; top:0px'>")の直後に実行されるとその時点での最後のエレメントがimgObje配列オブジェクトのコレクションに入ることになります。
これでimgObjには書き出したIMGエレメントのみを要素とすることができました。
実際に動くかどうか確認ください。
サンプル
・・・書き出すIMGエレメントにidをつけて、imgObj[1]〜imgObj[20]のidを読み出して表示させています。既にあるスクリプトエレメントやIMGエレメントはimgObjのコレクションにはなっていないのがわかります。imgObj[0]には何も入っていません(mgObj[0]=undefined)。エレメントが入っていればimgObj[n]は[object]と表示されます。
ちなみにエレメントのIDを調べるのはobject.idです。
idプロパティ
object.id・・・スクリプト内で使用するために、識別子は英文字で始まる英数字でなければならない。アンダーバー("_")を含む特殊文字も使用できる。読み出し専用である。※idを変更したり、付け加えるにはsetAttribute("属性名",設定値)メソッドで行います。
さあ雪降りスクリプトを完成させましょう。今度は奥にあるもの(小さなもの)ほど、暗く見えるようにします。暗く見えるといっても何のことはない、Alphaフィルタの不透明度を変更するだけです。
今回はAlpha()フィルタではなく、progid:DXImageTransform.Microsoft.Alpha()を使用してみましょう。
progid:DXImageTransform.Microsoft.Alpha()
このフィルタにはいくつかのパラメータがありますが、ここでは不透明度を示すopacityのみを扱います。詳しいことはMSDNやGoogleなどで検索してください。
まずフィルタを雪エレメントに付加しますが、フィルタの追加を兼ねて、スクリプトで後付けします。
object.style.filter="フィルタ名(パラメータ,・・・)"
objectにフィルタを付ける場合は上記のようにしますが、この場合は既存のフィルタは消えます。styleオブジェクトのfilterプロパティになっているから、フィルタプロパティの設定になります。既存のフィルタを消さずに追加するには次のようにします。
object.style.filter=object.style,filter+"フィルタ名(パラメータ,・・・)"
これはa=a+"文字列"と同じ連結式ですね。従ってa+=a+"文字列"とも書けますので、
object.style.filter+="フィルタ名(パラメータ,・・・)"
でも構いません。
スタート関数にimgObj[i].style.filter="progid:DXImageTransform.Microsoft.Alpha()"を記述すればとりあえずフィルタを付けることができますね。
サイズに比例して不透明度を変更する部分をどうするか考えましょう。今回はopacityが0以上100以下の整数でなければならない点に注意します。倍率はybmaxが最大値でybminが最小値です。最大値をとる時にopacityを100に、最小値でopacityを0にするという考えもありますが、0というのはまったく見えなくなりますね。ここはやはり最小値の時のopacityの値を設定した方がいいでしょう。opacity下限値を設定しましょう。
var yomin=30//不透明度最小値
倍率は、ybmax以下でybmin以上の値になります。この幅は(ybmax-ybmin)となります。
一方不透明度の幅は100-yominです。つまりこの二つの比率は(100-yomin)/(ybmax-ybmin)となります。今それぞれの倍率はyz[n]と計算されるようになっています。
この倍率と倍率の最小値の差に対し、不透明度の差を比率から求めますと、(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)となります。この値は差分ですから、実際の不透明度を算出するために不透明度最小値を加算すると、個々の倍率に対する個々の不透明度が計算できますね。
(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)+yominを不透明度にすればいいことになります。
フィルタの不透明度を設定するのはAlphaフィルタで出てきましたように、filtersコレクションの"DXImageTransform.Microsoft.Alpha"オブジェクト(要素)のopacityプロパティに代入します。
imgObj[n].filters["DXImageTransform.Microsoft.Alpha"].opacity=(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)+yomin
あるいは
imgObj[n].filters.DXImageTransform.Microsoft.Alpha.opacity=(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)+yomin
あるいは
imgObj[n].filters.item("DXImageTransform.Microsoft.Alpha").opacity=(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)+yomin
あるいは
imgObj[n].filters.item(0).opacity=(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)+yomin
フィルタは一つしか付いていないので、
imgObj[n].filters[0].opacity=(yz[n]-ybmin)*(100-yomin)/(ybmax-ybmin)+yomin
インデックス値やサブオブジェクトネームを使用する方法など結構いろいろあって混乱するのですね。()と[]どちらを使用するのかとかね。
[ソース]
<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="overflow:auto; margin:0px; padding:0px">
<img id="img1"
src="yuki.gif" style="display:none">
<div id="stage"
style="position:absolute; left:10px; top: 10px; background-color:black;
width:600px; height:500px; overflow:hidden">
<script>
var
ys=20//雪の数
var dd=5//落ちる重さ標準値
var th=30//上部配置位置
var
bh=50//下部end位置
var sk=50//速度(ミリ秒)
var yt=2//雪の間隔(秒)
var
hk=30//揺れ半径
var dg=10//揺れの周期角度
var ybmax=1.0//倍率最大値
var
ybmin=0.3//倍率最小値
var yomin=30//不透明度最小値
//設定ここまで
var
yz=new Array()//雪の倍率用配列
var yd=new Array()//落ちる重さ用配列
var
imgtop=new Array()//雪のTOP計算用配列
var imgleft=new Array()//雪のLFT用配列
var
deg=new Array()
var hn=new Array()
var cx=new Array()
var imgObj=new
Array()//雪オブジェクトを入れる配列
for(i=1;i<=20;i++){
document.write("<img
src='"+img1.src+"' style='position:absolute; left:-1000px; top:0px'>")
}
imgObj=stage.all
function
yukiMove(n){
imgtop[n]=(imgtop[n]+yd[n])%(th+stage.clientHeight+bh)
deg[n]=deg[n]+dg
imgleft[n]=Math.cos(deg[n]*Math.PI/180)*hn[n]+cx[n]
imgObj[n].style.pixelTop=imgtop[n]-th
imgObj[n].style.pixelLeft=imgleft[n]
setTimeout("yukiMove("+n+")",sk)
}
function
yukistart(){
for(i=1;i<=ys;i++){
yz[i]=Math.random()*(ybmax-ybmin)+ybmin
hn[i]=hk*yz[i]
yd[i]=dd*yz[i]
deg[i]=Math.random()*360
cx[i]=Math.random()*(stage.clientWidth-25-25)+25
imgtop[i]=-th
imgleft[i]=Math.cos(deg[i]*Math.PI/180)*hn[i]+cx[i]
imgObj[i].style.filter="progid:DXImageTransform.Microsoft.Alpha()"
imgObj[i].filters["DXImageTransform.Microsoft.Alpha"].opacity=(yz[i]-ybmin)*(100-yomin)/(ybmax-ybmin)+yomin
imgObj[i].style.zIndex=Math.floor(yz[i]*100)
imgObj[i].style.zoom=yz[i]
imgObj[i].style.pixelTop=imgtop[i]
imgObj[i].style.pixelLeft=imgleft[i]
setTimeout("yukiMove("+i+")",yt*(i-1)*1000)
}
}
setTimeout("yukistart()",3000)
</script>
</div>
</body>
</html>
雪降り横揺れ有、サイズ違い有、z-index対策有、不透明度設定有![]()
雪降り横揺れ有、サイズ違い有、z-index対策有、ぶれフィルタ有![]()
次回は剰余計算の便利さをもう少し追求してみたいと思います。