実践 Ajax が Amazon で在庫ありになっていたので注文したところ早速到着したので、 MochiKit の勉強も兼ねて第2章の地図を MochiKit で作ってみた。
ドラッグの処理を MochiKit.Signal.connect でやろうとすると、 地図のドラッグがうまくできなかったので、仕方なく普通のイベント処理で作ってみた。
どうやればうまく動くんだろう。
(画像をドラッグしようとしてしまい、地図が動かない。 img に preventDefault とかをくっつけてみたけどダメだった。)
addLoadEvent(init);
function init() {
setElementDimensions($('innerDiv'), { w : 2000, h : 1400 });
var div = $('outerDiv');
updateNodeAttributes(div, {'onmousedown' : startMove, 'onmousemove' : processMove, 'onmouseup' : stopMove});
// connect(div, 'onmousedown', window, startMove);
// connect(div, 'onmousemove', window, processMove);
// connect(div, 'onmouseup', window, stopMove);
checkTiles();
}
var dragging = false;
var top;
var left;
var dragStartTop;
var dragStartLeft;
function startMove(e) {
e = e || event;
dragStartLeft = e.clientX;
dragStartTop = e.clientY;
// dragStartLeft = e.mouse().client.x;
// dragStartTop = e.mouse().client.y;
$('innerDiv').style.cursor = '-moz-grab';
var pos = getElementPosition($('innerDiv'), $('outerDiv'));
left = pos.x;
top = pos.y;
dragging = true;
return false;
}
function processMove(e) {
e = e || event;
if (dragging) {
setElementPosition($('innerDiv'),
{ x : left + e.clientX - dragStartLeft, y : top + e.clientY - dragStartTop });
// { x : left + e.mouse().client.x - dragStartLeft, y : top + e.mouse().client.y - dragStartTop });
}
checkTiles();
}
function stopMove(e) {
$('innerDiv').style.cursor = '';
dragging = false;
}
function checkTiles() {
var visibleTiles = getVisibleTiles();
var div = $('innerDiv');
var visibleTilesMap = {};
forEach(visibleTiles, function(t) {
var tileName = 'x' + t[0] + 'y' + t[1] + 'z0';
visibleTilesMap[tileName] = true;
if (!$(tileName)) {
var img = IMG({ id : tileName, src : 'resources/tiles/' + tileName + '.jpg' });
img.style.position = 'absolute';
setElementPosition(img, { x : t[0] * tileSize, y : t[1] * tileSize });
appendChildNodes(div, img);
}
});
var sweptImgs = filter(function(e){ return !visibleTilesMap[e.getAttribute('id')] }, div.getElementsByTagName('img'));
forEach(sweptImgs, removeElement);
}
var tileSize = 100;
var viewportSize = [800, 600];
function getVisibleTiles() {
var mapPos = getElementPosition($('innerDiv'), $('outerDiv'));
var startX = Math.abs(Math.floor(mapPos.x / tileSize)) - 1;
var startY = Math.abs(Math.floor(mapPos.y / tileSize)) - 1;
var tiles = map(function(n){ return Math.ceil(n / tileSize) + 1 }, viewportSize);
var visibleTileArray = [];
forEach(range(startX, tiles[0] + startX), function(x) {
forEach(range(startY, tiles[1] + startY), function(y) {
visibleTileArray.push([x, y]);
})
});
return visibleTileArray;
}
<html>
<head>
<title>Ajaxian Maps</title>
<style type="text/css">
h1 {
font: 20pt sans-serif;
}
#outerDiv {
height: 600px;
width: 800px;
border: 1px solid #000;
position: relative;
overflow: hidden;
}
#innerDiv {
position: relative;
left: 0px;
top: 0px;
z-index: 0;
}
#zoomWidget {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
}
</style>
<script type="text/javascript" src="MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="map-mochi.js"></script>
</head>
<body>
<p><h1>Ajaxian Maps</h1></p>
<div id="outerDiv">
<div id="innerDiv">
The rain in Spain falls mainly in the plains.
</div>
</div>
</body>
</html>