
今回からマウスチェーサーを試したいと思います。マウスカーソル(ポインタ)の動きに同調するように画像が動きます。
まず前哨戦として前回使用したひな形を使います。
先のひな形ではクリックすると穴が開きましたね。それに追加して、マウスポインタの位置に穴が開いていて、マウスの動きに合わせて穴が移動するようにします。
<div
id="gbox0" onclick="imgadd(1)" ondblclick="imgadd(3)"
style="position:absolute; z-index:2; left:0px; top:0px;
filter:chroma(color=#ff0000); width:expression(document.body.clientWidth); height:expression(document.body.clientHeight)">
<img id="img2" src="aki2.jpg"
style="position:absolute; z-index:1; top:0px; left:0px; width:expression(document.body.clientWidth);
height:expression(document.body.clientHeight)"></div>
<img
id="a1" src="ana1.gif" style="width:50px; height:50px; visibility: hidden;">
<img
id="a2" src="ana2.gif" style="width:50px; height:50px; visibility: hidden;">
というソースがありましたが、少し書きかえます。a1エレメントとa2エレメントをgbox0の子エレメントになるようにします。始めからこの画像は見えて良いので、visibility:hiddenは削除しておきます。gbox0でのa1エレメントとa2エレメントは一番上に表示されるようにしたいので、a1エレメントのz-indexを3に、a2エレメントのz-indexを4にします。こうしておけばマウスについてくる画像a1エレメントとa2エレメントが一番上位に配置されます。元々のサイズで表示したいので、widthとheightは削除しておきます。とりあえずleftとtopは-200にでもしておきましょう。
※左上に表示させるなら、a1エレメントの(left,top)は(0,0)、a2エレメントの(left,top)は(15,13)にします。
<div
id="gbox0" onclick="imgadd(1)" ondblclick="imgadd(3)"
style="position:absolute; z-index:2; left:0px; top:0px;
filter:chroma(color=#ff0000); width:expression(document.body.clientWidth); height:expression(document.body.clientHeight)">
<img
id="a1" src="ana1.gif" style="position:absolute;
left:-200px; top:-200px; z-index:3">
<img
id="a2" src="ana2.gif" style="position:absolute;
left:-200px; top:-200px; z-index:4">
<img id="img2" src="aki2.jpg"
style="position:absolute; z-index:1; top:0px; left:0px; width:expression(document.body.clientWidth);
height:expression(document.body.clientHeight)"></div>
マウスポインタがが動いた時にa1エレメントとa2エレメントがそれに合わせて移動しなければならないので、画像マウスポインタの座標をマウスポインタが動いた時に取得し、更にa1エレメントとa2エレメントのleftとtopを変更しなければなりません。関数を用意してこの処理をすればいいのですが、ちょっと待ってください。
座標の取得やエレメントの位置計算は既にimgadd()関数にありますよね。
function imgadd(sc){
bang.src=sound
zx=event.x
zy=event.y
status="X座標="+zx+";
Y座標="+zy
gbox0.insertAdjacentHTML("BeforeEnd","<img
src='"+a1.src+"'
style='position:absolute; left:"+(zx-74*sc)+"px;
top:"+(zy-72*sc)+"px;
z-index:1; width:"+152*sc+"px; height:"+152*sc+"px'><img
src='"+a2.src+"'
style='position:absolute; left:"+(zx-59*sc)+"px;
top:"+(zy-59*sc)+"px;
z-index:2; width:"+118*sc+"px; height:"+118*sc+"px'>")
}
これをうまく利用できないか考えましょう。皆さんもちょっと下を読まずに考えてみてください。
imgadd()関数には引数scがありました。クリック或いはダブルクリックすると音が出て穴が開きますね。これは引数に1か3を与えていましたね。引数に0を与えると「音が出る、エレメントを追加する」という処理をしないで、a1エレメントとa2エレメントのleftとtopを変更するだけの処理をして関数から抜けてしまうようにできそうな気配がしませんか?
scが0の時とそうではない時で処理を分ける=>条件分岐構文が使えそうです。どちらの場合もマウスポインタの座標が必要な処理を含みますから、zx=event.xとzy=event.yは条件分岐構文の中で使う理由はなさそうです。
@まずマウス座標を取得しておく。
Aもしscが0の時は取得した座標を使用してa1エレメントとa2エレメントのleftとtopを変更する
エレメントオブジェクトのleftとtopは、object.style.pixelLeft及びobject.style.pixelTop
Bもしscが0以外なら音を出して、穴あけ処理をする
こんなストーリーを考えました。プログラムのストーリー(処理の流れ)あるいはそれを図などに視覚化したものをフローチャートといいます。フローチャートの書き方には「開始」「判断」「アクション」「繰り返し」「分岐」「結合」「終了」などそれぞれに使用する図形の決まりごとがありますが、プロのプログラマーでなければ拘らず自分のわかりやすい図面を書いてみるといいでしょう。複雑なプログラムを書くときには、フローチャートを描いておくとミスの発見が容易になり、プログラミングも楽になります。これはまた機会があれば触れることにします。僕自身プロではないので、詳しくありません。
function imgadd(sc){
zx=event.x
zy=event.y
if(sc==0){
a1.style.pixelLeft=zx-74
a1.style.pixelTop=zy-72
a2.style.pixelLeft=zx-59
a2.style.pixelTop=zy-59
}else{
bang.src=sound
gbox0.insertAdjacentHTML("BeforeEnd","<img
src='"+a1.src+"'
style='position:absolute; left:"+(zx-74*sc)+"px;
top:"+(zy-72*sc)+"px;
z-index:1; width:"+152*sc+"px; height:"+152*sc+"px'><img
src='"+a2.src+"'
style='position:absolute; left:"+(zx-59*sc)+"px;
top:"+(zy-59*sc)+"px;
z-index:2; width:"+118*sc+"px; height:"+118*sc+"px'>")
}
}
後はマウスポインタが動いたらimgadd(0)を実行せよと命令します。
マウスポインタが動いたら・・・onmousemoveというイベントハンドラが用意されています。
onmousemove="imgadd(0)"・・・これをどこに入れますか?そうgbox0上で動けば良いので、gbox0エレメントに入れます。
<div id="gbox0" onclick="imgadd(1)" ondblclick="imgadd(3)" onmousemove="imgadd(0)" style="position:absolute; z-index:2; left:0px; top:0px; filter:chroma(color=#ff0000); width:expression(document.body.clientWidth); height:expression(document.body.clientHeight)">
さあどうかな?
・・・マウスを動かして確認してね。クリック・ダブルクリックもOKよ。
今回はここまで。何?短い?では汎用エレメントを使用して、そのエレメントに個エレメントを配置して、親エレメントをマウスに追従させることをやってみましょう。
ソースは次のようにします。HTML+TIMEを使用します。
[ソース]
<HTML xmlns:t="urn:schemas-microsoft-com:time">
<head>
<meta
http-equiv="content-type" content="text/html; charset=shift_jis">
<META
http-equiv="Content-Style-Type" content="text/css">
<title></title>
<STYLE
type="text/css">
<!--
time{behavior:url(#default#time2)}
t\:*
{behavior:url(#default#time2)}
-->
</STYLE>
</head>
<body
style="overflow:auto; margin:0px; padding:0px">
<div id="mcbox"
style="width:0px; height:0px; position:absolute; top:0px; left:0px;
overflow:hidden">
<img id="img1"
src="octopus.gif" style="position:absolute">
</div>
<t:seq
id="seq0" repeatcount="indefinite">
<t:animatemotion
id="idou1" targetelement="img1" begin="0" dur="1"
path="m 0 0 c 50 0 100 0 150 0" fill="hold" />
<t:animatemotion
id="idou2" targetelement="img1" begin="0" dur="1"
path="m 0 0 c -50 0 -100 0 -150 0" fill="hold" />
</t:seq>
</body>
</html>
mcboxというdivエレメントの子エレメントとしてimg1エレメントを配置し、img1エレメントはHTML+TIMEの<t:animatemotion
/>で移動するようにしています。
<t:seq />はサブエレメントのHTML+TIMEを順番に実行するものです。
このまま表示させると、pathによって右移動と左移動を繰り返しますが、親エレメントであるdivがサイズ0でoverflow:hiddenなので何も表示されません。少しわかりやすくするためにmcboxのサイズを100px×100pxにし、overflow:autoとしてみます。これでmcbox内でどのように動いているのかわかると思います。
<div id="mcbox" style="width:100px; height:100px; position:absolute; top:0px; left:0px; overflow:auto">
ではこのままでは100px×100pxからはみ出た部分はスクロールしないと見えませんので、overflow:visibleとします。ついでに枠線も付けましょう。
<div id="mcbox" style="width:100px; height:100px; position:absolute; top:0px; left:0px; overflow:visible; border:red 1px solid">
ボックスからはみ出しても表示されますね。ここまでが準備段階です。
ではこの親エレメントであるmcboxをマウスに追従して動かすようにしてみましょう。
mcboxの親エレメントはbodyなので、bodyエレメント内でマウスが動いたら、mcboxの表示位置をマウス座標に合わせるようにします。
マウスが動いたら・・・onmousemoveでしたね。bodyエレメント上でのイベントキャッチになるので、bodyタグにonmousemoveをいれます。表示位置を変えるのは関数にしましょう。関数名はmcboxchange()にしてやってみます。
<body onmousemove="mcboxchange()" style="overflow:auto; margin:0px; padding:0px">
<script>
function mcboxchange(){
}
</script>
マウス座標の取得はbodyエレメント内の座標になりますね。つまりは?・・・・event.xとevent.yでOK、わかりますね。mcboxのleftとtopをこの座標に合わせるわけですね。
mcboxのleftとtopは?
そうもう何度も出てきました、mcbox.style.pixelLeftとmcbox.style.pixelTopですね。完成させましょう。
[ソース]
<HTML xmlns:t="urn:schemas-microsoft-com:time">
<head>
<meta
http-equiv="content-type" content="text/html; charset=shift_jis">
<META
http-equiv="Content-Style-Type" content="text/css">
<title></title>
<STYLE
type="text/css">
<!--
time{behavior:url(#default#time2)}
t\:*
{behavior:url(#default#time2)}
-->
</STYLE>
</head>
<body
onmousemove="mcboxchange()" style="overflow:auto;
margin:0px; padding:0px">
<div id="mcbox" style="width:100px;
height:100px; position:absolute; top:0px; left:0px; overflow:visible; border:red
1px solid">
<img id="img1"
src="octopus.gif" style="position:absolute">
</div>
<t:seq
id="seq0" repeatcount="indefinite">
<t:animatemotion
id="idou1" targetelement="img1" begin="0" dur="1"
path="m 0 0 c 50 0 100 0 150 0" fill="hold" />
<t:animatemotion
id="idou2" targetelement="img1" begin="0" dur="1"
path="m 0 0 c -50 0 -100 0 -150 0" fill="hold" />
</t:seq>
<script>
function
mcboxchange(){
mcbox.style.pixelLeft=event.x
mcbox.style.pixelTop=event.y
}
</script>
</body>
</html>
このサンプルではmcboxの左上がマウスの位置になりますが、少し位置をずらしたい場合はその数値分だけ加算・減算すればいいことはもう説明不要でしょう。
次の例では右に50ピクセル、上に30ピクセルずれた位置に表示されます。
<script>
function mcboxchange(){
mcbox.style.pixelLeft=event.x+50
mcbox.style.pixelTop=event.y-30
}
</script>
このサンプルではスクリプトエラーが出る場合があります。関数部分が読み込み完了していないのにonmousemoveが発生してしまうのが原因です。講座8で説明したことがここで起きます。回避策は?
関数定義しているスクリプト部分は</t:seq>の後ろにおかなければならない理由が見当たりません。関数定義は<head>〜</head>内に置いて、onmousemoveが引き起こされる前に、予め関数をメモリに読み込めるようにしておきます。
[ソース]
<HTML xmlns:t="urn:schemas-microsoft-com:time">
<head>
<meta
http-equiv="content-type" content="text/html; charset=shift_jis">
<META
http-equiv="Content-Style-Type" content="text/css">
<title></title>
<STYLE
type="text/css">
<!--
time{behavior:url(#default#time2)}
t\:*
{behavior:url(#default#time2)}
-->
</STYLE>
<script>
function
mcboxchange(){
mcbox.style.pixelLeft=event.x+50
mcbox.style.pixelTop=event.y-30
}
</script>
</head>
<body
onmousemove="mcboxchange()" style="overflow:auto;
margin:0px; padding:0px">
<div id="mcbox" style="width:100px;
height:100px; position:absolute; top:0px; left:0px; overflow:visible; border:red
1px solid">
<img id="img1"
src="octopus.gif" style="position:absolute">
</div>
<t:seq
id="seq0" repeatcount="indefinite">
<t:animatemotion
id="idou1" targetelement="img1" begin="0" dur="1"
path="m 0 0 c 50 0 100 0 150 0" fill="hold" />
<t:animatemotion
id="idou2" targetelement="img1" begin="0" dur="1"
path="m 0 0 c -50 0 -100 0 -150 0" fill="hold" />
</t:seq>
</body>
</html>
もうひとつの対処方法はbodyのonmousemoveイベントハンドラをbodyのインラインに入れるのではなく、スクリプトの最後に入れることです。
document.body.onmousemove=mcboxchange
次回はマウス追従ですが、少し遅れてマウスについてくるものを一緒に考えてみましょう。
まだできていないので、もう少し待ってください。