2008/07/31

Slippy Mapを表示してみる

OpenStreetMapではサイトに表示しているメインの地図をSlippy Mapと呼んでいます。

最近、日本語サイトのOpenStreetMap Japan地図ページの改良をなさっている方が居て、私もちょっと触ってみたくなってBloggerに表示させてみることにしました。


ベースにしたのは、MediaWiki用のSlippy Map MediaWiki Extensionからの出力です。

サーバーからタイル(細分化された地図画像)を引っ張ってくることは直ぐにできましたが、タイル同士の間に数ピクセルの隙間が空いてしまいます。OSM.orgやOSM.jpで使用しているコードを覗いて見たり、OpenLayersの文書やソースを読んでみても解決できず二日程悩んでいました。ふと思い立ってFirefoxのアドオンのページを確認してみるとFirebugのFirefox3対応版が出ていたので早速インストール。HTMLを調査すると適用されているスタイル (padding:4px;) や要素のクラス名 (olTileImage) が簡単に分かり、直ぐに解決。この程度のことだから、OpenLayersのFAQやメーリングにも質問が出ていなかったんだと思いました。それにしてもFirebugは便利だなぁ。あまり使ったことがないので、使い方も良く分かんないけど...

やろうと思ったけどやり方が分からず、とりあえず現時点では諦めたこと。
  • 地図のスクロール時やズーム時に、OSM.orgの地図へのURLに入っている座標やズームレベルを更新すること。
    • URLのベースをOSM.orgサーバーへ向ける。
    • 座標の形式を lat=35.67255 lon=139.76183 のように普段GPSなどで見ているものと同じにする。
    • リンクテキストを Permalink 以外のものにする
  • ズームレベルに合わせたスケールを表示する。
これからやろうと思っていること。



上の地図を表示させているコードはこちら。( "+ expand source" のリンクをクリックして下さい。)
<style>
.map img { padding: 0px !important; border: none !important;}
</style>

<div class="map" style="margin-bottom:-35px;">

<!-- define a DIV into which the map will appear -->
<div style="width:400px; height:350px; border-style:solid; border-width:1px; border-color:#000;" id="map"></div>

<br/>
<span style="font-size:70%; background-color:white; position:relative;top:-65px;left:5px;z-index:1003;">Data by <a href="http://www.openstreetmap.org/?lat=36&lon=139&zoom=4" title="See this map on OpenStreetMap.org">OpenStreetMap</a><br/>
<a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Creative Commons Attribution-Share Alike 2.0">CC-BY-SA-2.0</a></span>

</div>

<!-- bring in the OpenLayers javascript library -->
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<!-- bring in the OpenStreetMap OpenLayers layers. Using this hosted file will make sure we are kept up to date with any necessary changes. --> 
<script src="http://openstreetmap.org/openlayers/OpenStreetMap.js"></script> 

<script type="text/javascript"> 
var lon=139; 
var lat=36; 
var zoom=4; 
var map; 

function lonLatToMercator(ll) {
  var lon = ll.lon * 20037508.34 / 180;
  var lat = Math.log (Math.tan ((90 + ll.lat) * Math.PI / 360)) / (Math.PI / 180);
  lat = lat * 20037508.34 / 180;
  return new OpenLayers.LonLat(lon, lat);
}

window.onload=init; 

function init() {
  map = new OpenLayers.Map("map", {
    controls:[
      new OpenLayers.Control.Navigation(),
      new OpenLayers.Control.PanZoom(),
      new OpenLayers.Control.LayerSwitcher()],
    maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
    maxResolution:156543.0399,
    units:'meters',
    projection: "EPSG:900913"
  } );
  var mapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
  map.addLayer(mapnik);
  var osmarender = new OpenLayers.Layer.OSM.Osmarender("Osmarender");
  map.addLayer(osmarender);
  var cyclemap = new OpenLayers.Layer.OSM.CycleMap("Cycle Map");
  map.addLayer(cyclemap);
  var maplint = new OpenLayers.Layer.OSM.Maplint("Maplint");
  map.addLayer(maplint);
  var lonLat = lonLatToMercator(new OpenLayers.LonLat(lon, lat));
  map.setCenter (lonLat, zoom);
} 
</script>


追記

Widget追加ボタンを作成しました。
尚、上のコードで表示できるSlippy Mapは1ページに1つだけで、Widgetでは複数のSlippy Mapを同じページに表示できます。また、上のコードによるSlippy Mapと同じページ内にWidgetによるSlippy Mapがあると、その影響により指定した座標・ズームで表示できないことがあるようです。
Atom