
さあはじめましょう。その前にちょっとおさらいから。
前々回(講座7)の初頭で比較演算子a===b・・・aがデータ型も含めてbと等しいと書きました。データ型っていう説明をしていませんので、少し解説しますね。
一般にプログラムでは、プロパティや変数など扱う値に型というものがあります。型には文字列・数値・真偽値・オブジェクトなどがあり、数値型にも16ビット浮動小数点型とか32ビット整数型とか扱える値の性質や範囲内で計算や処理を行わなければならないのが普通です。文字列を扱うように宣言した変数に数値を代入したり、算術計算したりは通常できないのです。JavaScriptでは型の扱いがあいまいというか自動判断されて処理されることがあります。
JavaScriptにおいては、文字列が数値として扱える場合は、文字列型であっても数値としての処理が行える。但し、文字列として処理が可能な場合はそちらが優先されます。
第一回で、文字列に数値を+で演算させると文字列の連結になるといいました。
var hensu="2"・・・hensuという変数には2という数値ではなく、文字列としての2が入ります。結果a=hensu+1・・・文字列"2"に1を連結。aは"21"という文字列型になります。+には算術計算の加算と文字列の連結という二つの意味があります。
ところがa=hensu*2とすると文字列"2"をニ倍するという計算自身ができませんし*は算術計算の乗算ですから、hensuの値は数値として扱えるので、自動的に2*2という計算をします。aは4という数値型に変わります。*には算術計算の乗算の意味しかありません。
第一回でimg1.style.leftは数値計算に使えないと書きましたが、数値として扱える場合は数値変換することが可能になります。
例えば変数を用意して数値として処理し、結果をimg1.style.leftに代入すると、文字列型に数値型を代入できる(数値は文字としての数字になる)のです。
img1.style.left=img1.style.left+1という処理はできなくても・・・
var
hensu=0
hensu=hensu+1
mg1.style.left=hensu
は可能です。
<html>
<head>
<title></title>
<style></style>
</head>
<body
style="margin:0px; overflow:hidden">
<img id="img1"
src="akiakane.gif" style="position:absolute; left:0px; top:100px">
<script>
var
hensu=0
hensu=hensu+1
img1.style.left=hensu
status=img1.style.left
</script>
</body>
</html>
上記のスクリプトはエラーなく動作します。status=img1.style.leftによりステータスバーには1pxと表示されます。
JavaScriptには文字列が数値として扱えるかどうかを調べる関数isNaN()や文字列を数値や式として評価するeval()などが用意されていますが、ここでは一応そういうのもあるとだけ認識しておいてくださいね。
さあ今回のテーマは「移動しながら消えたり現れたり?フィルタをスクリプトで扱う」でしたね。消えたり現れたりって単にぱっと消えてぱっと現れるのではなくて、次第に薄くなって消え、次第に濃くなって現れるってことです。これには表示透明度を設定できるアルファフィルタを使用します。
アルファフィルタには二種類あります。progid:DXImageTransform.Microsoft.Alpha()というDirectX系のものとAlpha()というイメージフィルタです。ああそれからBasicImageフィルタにも透明度を扱える属性があります。今回は一番簡単なAlpha()を使用してみますね。progidとつくフィルタはIE5.5以降で利用でき、それ以前のIEでは利用できません。IE4.0用のビジュアルフィルタしか利用できません。IE5.5以前を使用しているひな形愛好家はいまどきいないと思うけど。
{ FILTER: Alpha(Opacity=opacity,
FinishOpacity=finishopacity,
Style=style, StartX=startX,
StartY=startY, FinishX=finishX,
FinishY=finishY)"}
パラメータ
解説
opacity
不透明度。デフォルト値は0で透明。100は不透明。
finishopacity
(オプション) 0(透明)から100(不透明)までの値。
style
不透明度の形。0(一定)、1(直線形)、2(放射線)、3(矩形)の値を指定する。
startX
不透明度を開始するX座標。
startY
不透明度を開始するY座標。
finishX
不透明度を終了するX座標。
finishY
不透明度を終了するY座標。
いろいろと設定できる項目(パラメータ)があるようですね。しかしフィルタは設定変更しない限りデフォルト値を持っていますので、全てを必ずしも設定する必要ありません。デフォルト値のままでいいのならば設定不要なんですね。
ここでは不透明度だけを扱います。opacityですが、100で100%不透明(逆に言うと透明度0%ですね)、0で0%不透明(逆に言うと100%透明)とあります。上記内容はMSDNというマイクロソフトの技術情報サイトから抜粋意したものです。インターネットは検索できて便利ですね。
フィルタはスタイルシートとして記述しますから、imgエレメントにフィルタを適用させる場合は
<img
style="filter:フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・)"のように記述します。複数のフィルタを適用するには、フィルタを適用する順番に半角スペースで区切ります。
例)<img
style="filter:フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・) フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・) フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・)"
またスクリプトでは(objectはフィルタを適用するエレメント)
object.style.filter="フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・)"のように記述します。
既にフィルタが適用されている場合は、フィルタを追加するようにしなければなりません。
object.style.filter="フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・)"のように記述すると、既に適用されているフィルタは消えてなくなります。
フィルタの追加:object.style.filter+="フィルタ名(パラメータ1=設定値,パラメータ2=設定値,・・・)"のように記述します。ああこれは文字列の連結なんですね。
スクリプトでフィルタを扱う五つの方法
@object.filters.alpha // サブ オブジェクト
Aobject.filters["alpha"] // インデックスの指定
Bobject.filters[0] // 数値インデックス
Cobject.style.filter="文字列"//スタイルシート(スクリプトではobjectのサブオブジェクトとしてのstyleオブジェクト)のフィルタプロパティとして、文字列でフィルタを書き換える。
Dobject.filters.item(0)//objectのフィルタコレクションとして、インデックスで識別させるitem()メソッドを使用できる。
@alphaフィルタをフィルタオブジェクトとして扱います。
Aフィルタをコレクションとしてコレクション名"alpha"として扱います。
Bフィルタをコレクションとしてコレクションの番号で扱います。
Cstyleはobjectのサブオブジェクト(オブジェクトのプロパティはオブジェクトとして取り扱いできる)です。そのstyleオブジェクトのプロパティとしてfilterプロパティがあります。これは文字列扱いになり、読み書きが可能です。
Dfiltersコレクションはオブジェクトであり、コレクションについてはitem()メソッドを持つので、インデックス番号でアクセスできます。インデックス番号は現れる順番に0から付きます。
インデックスはコレクションのひとつを指し示すもので、名前で指定したり、番号で指定できます。
コレクションとは、文字列、数値、オブジェクト、およびその他の値を格納する配列的なデータ構造です。複数のアイテムの集合体ともいえます.。同じ種類のオブジェクトの集合体となります。
コレクション番号はコレクションの個々のデータ格納順番です。
例)<img id="img1" style="filter:aplha() glow(color=red)">
上記imgエレメントにはアルファフィルタとグロウフィルタが適用されています。この時img1エレメントオブジェクトのフィルタコレクションはalphaフィルタとglowフィルタ二つをデータとして持ちますが、その適用順番からimg1.filters[0]はalpha()を指し、img1.filters[1]はglow()を指し示します。インデックス番号は配列変数同様に0から始まります。
尚、コレクションも配列同様にlengthプロパティでデータ数を得ることができます(img1.filters.length)。
スクリプトに限らず、オブジェクトのプロパティはまたオブジェクトです。つまりフィルタはエレメントのプロパティのように振舞いますが、このフィルタ自身もオブジェクトとして扱います。ということはフィルタの属性(パラメータ)はフィルタをオブジェクトとするプロパティとなります。
フィルタの属性値を扱う。Cでは既存フィルタをかき消してしまうので、使用の際は注意を要する。@ABDいずれにおいてもオブジェクトとして扱える以上、その属性はプロパティとして扱えます。プロパティは.で区切ってプロパティ名を書きますから、次のようになりますね。
@object.filters.alpha.opacity=100
Aobject.filters["alpha"].opacity=100
Bobject.filters[0].opaicty=100
Cobject.style.filter="alpha(opacity=100)"
Dobject.filters.item(0).opacity=100
Cでの注意点
例えば<img id="img1" src="hoge.jpg"
stlye="filter:alpha(opacity=0) glow(color=#ff0000)">・・・このimg1エレメントの不透明度を40%に変更する。
<script>
img1.style.filter="alpha(opacity=40)
glow(color=#ff0000)"としなければならない。
ここまでは予備知識。基本設計を考えましょう。
@透明度は右移動する関数または左移動する関数どちらかが実行される度に変更する。
A最初はopacity=100からはじまり、5ずつ減少して0まで行う。
B0になったら今度は5ずつ増大させて100間で行う。
C以下AとBを繰り返す。
このようにしましょうか。
opacityの値は変数を用意しましょう。増減値はそうですね。フラグを用いてフラグが1の時は減少処理、0の時は増大処理というようにしてもいいですね。別の方法はないでしょうか?フラグを用いず、増減値そのものを+5か-5に切り替えてもできそうにないですか?最初は-5にしておいて足し算させます。マイナス値を足すと値は小さくなりますね。それを0になるまで続けます。0になったら+5にして足し算します。今度は増大しますね。それを100になるまで続けます。100になったらまた-5にすれば・・・なんだかできそうですね。
これも関数にしてしまいましょうか。
まず増減値を変数に入れましょう。最初は減算なので、
var
kagen=-5
次は関数とりあえず作ってみましょう。
function opchange(){
img1.filters["alpha"].opacity+=kagen
}
これ意味わかりますね。とりあえずkagenの値を加算します。このままでは0以下でも加算実行されますので、もしimg1.filters["alpha"].opacity+kagenが0未満ならばkagenを+5にしてからimg1.filters["alpha"].opacity+=kagenを実行しなければなりません。aの値がプラスマイナスいずれであってもaに逆符号の値を入れるには-aを代入すればいいですから、kagen=-kagen
※絶対にimg1.filters["alpha"].opacityがマイナスにならないように!
function opchange(){
if(img1.filters["alpha"].opacity+kagen<0)kagen=-kagen
img1.filters["alpha"].opacity+=kagen
}
今度はkagenが+5の時そのまま続行すると100を超過しますね。100になったらkagenを-5にしなければなりません。これもkagen=-kagenですね。
条件式はもしimg1.filters["alpha"].opacity+kagenが100を超えたら
※絶対にimg1.filters["alpha"].opacityが100を超えないように!
function opchange(){
if(img1.filters["alpha"].opacity+kagen>100)kagen=-kagen
if(img1.filters["alpha"].opacty+kagen<0)kagen=-kagen
img1.filters["alpha"].opacty+=kagen
}
これでもいいのですが、
if(img1.filters["alpha"].opacity+kagen>100)kagen=-kagen
if(img1.filters["alpha"].opacty+kagen<0)kagen=-kagen
なんだか同じようなことをしていると思いませんか?
kagen=-kagenにし泣ければならない条件をもう一度練り直すと、もし「img1.filters["alpha"].opacity+kagenが0未満」または「img1.filters["alpha"].opacity+kagenが100を超えた」ならばということになりますよね。
またはは論理和といわれるもので、これを表す演算子があります。これを論理演算子と呼びます。
aまたはb・・・a||b
条件式aがtrueまたは条件式bがtrueという意味です。
もし「img1.filters["alpha"].opacity+kagenが0未満」または「img1.filters["alpha"].opacity+kagenが100を超えた」ならば
if(img1.filters["alpha"].opacity+kagen<0||img1.filters["alpha"].opacity+kagen>100)
さあ後は左右の移動関数で移動処理を行う部分にこの関数を実行せよという命令を入れましょう。
[ソース]
<html>
<head>
<title></title>
</head>
<body
style="margin:0px;
overflow:hidden">
<img id="img1" src="akiakane.gif"
style="filter:Alpha(opacity=100);
position:absolute; left:0px; top:100px; width:100px">
<script>
var
ix=5//一度に動くピクセル数
var iy=5//一度に動くピクセル数(縦)
var rtime=10//繰り返し実行時間(ミリ秒)
function
lidou(){//右移動する関数
status="ix="+ix+"
;iy="+iy
if(img1.style.pixelLeft+ix>=document.body.clientWidth-img1.clientWidth){
if(img1.style.pixelLeft<document.body.clientWidth-img1.clientWidth){
opchange()
img1.style.pixelLeft=document.body.clientWidth-img1.clientWidth
}else{
ixchange()
ridou()
return
}
}else{
opchange()
img1.style.pixelLeft+=ix
}
//status=img1.style.pixelLeft
setTimeout("lidou()",rtime)
}
function
ridou(){//左移動する関数
status="ix="+ix+"
;iy="+iy
if(img1.style.pixelLeft>0){
opchange()
if(img1.style.pixelLeft-ix<0){
img1.style.pixelLeft=0
}else{
img1.style.pixelLeft-=ix
}
setTimeout("ridou()",rtime)
}else{
ixchange()
lidou()
return
}
}
function
didou(){//下移動する関数
if(img1.style.pixelTop+iy>=document.body.clientHeight-img1.clientHeight){
if(img1.style.pixelTop<document.body.clientHeight-img1.clientHeight){
img1.style.pixelTop=document.body.clientHeight-img1.clientHeight
}else{
iychange()
uidou()
return
}
}else{
img1.style.pixelTop+=iy
}
setTimeout("didou()",rtime)
}
function
uidou(){//上移動する関数
if(img1.style.pixelTop>0){
if(img1.style.pixelTop-iy<0){
img1.style.pixelTop=0
}else{
img1.style.pixelTop-=iy
}
setTimeout("uidou()",rtime)
}else{
iychange()
didou()
return
}
}
var
saikoro=Math.floor(Math.random()*4)+1
switch(saikoro){
case
1:
img1.style.pixelLeft=-img1.clientWidth
img1.style.pixelTop=Math.floor(Math.random()*(document.body.clientHeight+img1.clientHeight+1))-img1.clientHeight
break
case
2:
img1.style.pixelTop=-img1.clientHeight
img1.style.pixelLeft=Math.floor(Math.random()*(document.body.clientWidth+img1.clientWidth+1))-img1.clientWidth
break
case
3:
img1.style.pixelLeft=document.body.clientWidth
img1.style.pixelTop=Math.floor(Math.random()*(document.body.clientHeight+img1.clientHeight+1))-img1.clientHeight
break
case
4:
img1.style.pixelTop=document.body.clientHeight
img1.style.pixelLeft=Math.floor(Math.random()*(document.body.clientWidth+img1.clientWidth+1))-img1.clientWidth
}
var
flag=0
function clstart(){
if(flag==0){
ixchange()
iychange()
lidou()
didou()
}
flag=1
}
function ixchange(){
ix=Math.floor(Math.random()*46)+5
}
function iychange(){
iy=Math.floor(Math.random()*46)+5
}
var
kagen=-5
function opchange(){
if(img1.filters["alpha"].opacity+kagen>100)kagen=-kagen
if(img1.filters["alpha"].opacity+kagen<0)kagen=-kagen
img1.filters["alpha"].opacity+=kagen
}
document.onclick=clstart
</script>
</body>
</html>
どうですか。思惑通りですね。今回は増減値を5にしましたが、var kagen=-2とでもすればもっとゆっくり消えたり現れたりします。
まとめ
aまたはb・・・a||b
aかつb・・・a&&b
次回のテーマは未定です
参考:主なコレクションの種類
| コレクション名 | 適用 | 内容 |
| anchors | documentオブジェクト | 空でないnameプロパティのあるAエレメント |
| applets | document | APPLETエレメント |
| areas | MAPエレメント | マップのAREAエレメント |
| cells | TRエレメント | 行のTDエレメントやTHエレメント |
| elements | FORMエレメント | フォームのBUTTON、INPUT、SELECT、TEXTAREAエレメント |
| embeds | document | EMBEDエレメント |
| filters | すべてのエレメント | filterオブジェクト |
| forms | document | FORMエレメント |
| frames | documentおよびwindow | FRAMEエレメントとIFRAMEエレメントで定義されたwindowオブジェクト |
| images | document | IMGエレメント |
| links | document | 空でないhrefプロパティのあるAエレメント |
| options | SELECTエレメント | OPTIONエレメント |
| rows | TABLE | 表のTRエレメント |
| scripts | document | SCRIPTエレメント |
| tbodies | TABLE | TBODYエレメント |
他にもall,childrenなどいくつかあります。