実践 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>