南極の図書館

ペンギンが寝ていた…。

初めてのJavaScript第二版 12章の例題をじっくりやってみる。

初めてのJavaScript第二版 P258 12.3.2 ドラッグ
この例題を考える。


結果の画面からコードを起こせれば合格だと思うので、本書を参考にしながらやってみよう。
オフィシャルのサポートページ(http://www.marlin-arms.com/support/ljs2/index12.php)の例題12-6を参照。


画面を見たうえで、思いついた流れで作ってみよう。(関数名は本と合わせる。)
おそらくいくつか抜けていて動かないと思うので、その場合は本を参照する。

1.script以外のhtml部分を流用する。
2.イベントハンドラを割り当てる。

(ここからは関数を作る。)
3.マウスの位置を補足する。
4.移動するオブジェクトのオフセットを取得する。
5.クリックしている状態を補足する。
6.クリックを離したことを補足する。
7.マウスを動かしたときに画像もが動く関数を作る。(3,4,5,6と組み合わせる)
8.書いてからわかったことを追記する。
9.動かす。

それではやってみよう。

1.script以外のhtml部分を流用する。

中でも、重要なのは枠と画像のidなので、ここではこれだけ書く。(実際には全部必要)

<div id="div1" >
<img id="img1" src="../chap09/pictno1.jpg" alt="例題の図" />
</div>
(枠はdiv1にcssでつけているのだがそれは省略。)

2.イベントハンドラを割り当てる。

document.onmousedown = mouseDown;	//クリックした(押した)
document.onmousemove = mouseMove;	//マウスの座標が変わった
document.onmouseup = mouseUp;		//クリックを上げた(指を離した)

3.マウスの位置を補足する。

基本に忠実に、clientX,Yを使う。

//event.clientX,Yの値をMousePointに格納する。
function mousePosition(event){
	var x = event.clientX;
	var y = event.clientY;
	return new MousePoint(x,y);
}
function MousePoint(x,y){
	this.x = x;
	this.y = y;
}

4.移動するオブジェクトのオフセットを取得する。

画像(id = img1)位置を取得する。
マウスの位置と、offsetの位置を利用する。

element.offsetLeftは、
offsetParent(つまりbody要素だが、今回は=div1要素のはず)の左上の座標を基準とした相対的なX座標。

function getMouseOffset(target, event){		//引数は[object HTMLImageElement],[object MouseEvent]が入る想定
	var theEvent = event ? event : window.event;
	var mousePos = mousePosition(theEvent);	//マウスの位置

	var x = mousePos.x - target.offsetTop;	//マウスのX座標 - img1のX座標
	var y = mousePos.y - target.offsetTop;	//マウスのY座標 - img1のY座標
	return new MousePoint(x, y);
}

5.クリックしている状態を補足する。

考えてみると「クリックしている状態」ではなく「ドラッグできる要素(img1)をクリックしている状態か否か」が知りたいので、
onmousedownしたときにimg1上であればオブジェクトを受け取り、それ以外は何もしない。


それによりdocument.getElementById("img1").onmousedownだけ有効とするので、1.で書いた
document.onmousedown = mouseDown;は消して、以下のようにする。

functino makeDraggable(itemid){			//実際はmakeDraggable("img1")と呼ばれることを想定。
if(itemid){
	item = document.getElementById(itemid);
	item.onmousedown = function(theEvent){		//theEventに渡されるのは[object MouseEvent]
		dragObject = this;			//dragObjectはグローバルで宣言する。thisは[object HTMLImageElement]
		mouseOffset = getMouseOffset(this, theEvent);	//mouseOffsetもグローバルで宣言。
		return false;				//onmousedownをキャンセルするために必要
	};

}
}

6.クリックを離したことを補足する。

これも、img1を抱えてるときだけ行えば良い。

function mouseUp(Event){
	if(dragObject){			//←例ではifで囲まず、常に↓を行っている。
		dragObject = null;	//dragObjectはグローバル変数として定義が必要。
	}
}

7.マウスが動く関数を作る。(3,4,5,6と組み合わせる)

dragObjectに何か入ってるときに、正規化されたマウス位置を取りだし、

function mouseMove(event){
	var theEvent = event ? event : window.event;
	var mousePos = mousePosition(theEvent);

	dragObject.style.position = 'relative';
	dragObject.style.left = mousePos.x - mouseOffset.x + "px";
	dragObject.style.top = mousePos.y - mouseOffset.y + "px";
	//return false;		//本書にあったのだが、なぜあるのか分からない。無くても動作する@firefox。

}

8.書いてからわかったことを追記する。

var dragObject = null;		//グローバル変数
var mouseOffset = null;		//グローバル変数
window.onload = function(){
	makeDraggable("img1");
}

9.動かす。

最初はところどころスペルミス等はあったり、動かなかったのだが、少し手直ししたら動いた。
(今まで書いたコードは直した後のもの)
とはいえ、7.のreturn falseが何故必要なのか調べきれていない。(無くても動くことは確認。)


じっくり書いたらすごい時間がかかってしまったので、13章の例題は明日以降に。
綺麗なソースはサポートページ(最初に書いたURL)からどうぞ。殆ど同じですので。


※後ほど修正するかも。その場合は履歴を残す。