Google Maps APIメモ(v2) #6 オリジナルマーカー情報をjsonデータで読み込み

シリーズ第6弾、シリーズこれで終了
第5弾では、オリジナルマーカーは1種類1個だけだったのですが、今回はオリジナルマーカーを複数種類、複数個読み込んでみようかと。
しかも、それをjsonデータから読み込んで、ズームレベルでの表示/非表示の管理や、情報ウインドウの管理も一度にしちゃおうじゃないか。
というBlogに書くのがめんどくさくなった?反響がないことによる手抜き?みたいな感じです。

やることの整理

  • オリジナルアイコンは、第5弾で作った雪と、星の2種にする。
  • オリジナルアイコンの数は適当に複数個。
  • 任意のレベルでオリジナルアイコン出現
  • オリジナルアイコンをクリックするとそのアイコンの情報ウインドウが表示

参考にしたところ

サンプル

jsonデータ

用意したjsonデータは下記の通り

{
    "marker":[
    {
        "category": "star",
        "lat":75,
        "lng":10,
        "html":"オリジナルアイコンの一番星や〜!",
        "minZoom":1,
        "maxZoom":2
    },
    {
        "category": "star",
        "lat":-23,
        "lng":107,
        "html":"スターですが何か?",
        "minZoom":2,
        "maxZoom":3
    },
    {
        "category": "snow",
        "lat":60,
        "lng":60,
        "html":"オリジナルアイコンの初雪や〜!",
        "minZoom":2,
        "maxZoom":3
    },
    {
        "category": "snow",
        "lat":-64,
        "lng":18,
        "html":"きっと君は・・・",
        "minZoom":3,
        "maxZoom":3
    },
    {
        "category": "snow",
        "lat":-80,
        "lng":-117,
        "html":"降りますか?降られますか?",
        "minZoom":3,
        "maxZoom":3
    }
    ]
}

スクリプト

function createCustomTileLayer(){
    var dataLayer = new GTileLayer(new GCopyrightCollection(),0,3);
    //0,3はズームレベルの範囲
    dataLayer.getOpacity=CustomTileLayer_getOpacity;
    dataLayer.isPng=CustomTileLayer_isPng;
    dataLayer.getTileUrl=CustomTileLayer_getTileUrl;
    return dataLayer;
}
var CustomTileLayer_opacity = 1.0;
var CustomTileLayer_png = true;
var CustomTileLayer_getOpacity = function getOpacity() {
    return CustomTileLayer_opacity;
}

var CustomTileLayer_isPng = function getOpacity() {
    return CustomTileLayer_png;
}

var CustomTileLayer_getTileUrl = function(tile, zoom) {
    var x = tile.x;
    var y = tile.y;
    return "tiles/"+zoom+"/"+x+"_"+y+".png";
}

function createCustomProjection() {
    var myProjection = G_NORMAL_MAP.getProjection();
    myProjection.tileCheckRange = function (tile, zoom, tilesize) "
    return myProjection;
}

var map;
var manager;

function initialize(){
    if(GBrowserIsCompatible()){
        var mapCustom = new GMapType([createCustomTileLayer()],createCustomProjection(),"")
        map = new GMap2(document.getElementById("gMap"),{
            mapTypes:[mapCustom]
        });
        map.addControl(new GSmallMapControl());
        map.enableDoubleClickZoom();
        map.enableScrollWheelZoom();
        map.setCenter(new GLatLng(0,0),1);

        manager = new GMarkerManager(map);
        GDownloadUrl("./data.json",createMap);
        
        //クリックされた場所の緯度、経度を表示
        GEvent.addListener(map, "click", function(marker, point) {
            document.getElementById("lat").innerHTML   = point.lat();
            document.getElementById("lng").innerHTML = point.lng();
        });
    }
}

function createMap(jsondata){
    var json = eval("(" + jsondata + ")");
    for (i=0;i<json.marker.length;i++){
        var category = json.marker[i].category;
        var lat = json.marker[i].lat;
        var lng = json.marker[i].lng;
        var html = json.marker[i].html;
        var minZoom = json.marker[i].minZoom;
        var maxZoom = json.marker[i].maxZoom;
        var marker = createMarker(category,lat,lng,html,minZoom,maxZoom);
        manager.addMarker(marker,minZoom,maxZoom);
        manager.refresh();
    }
}

var icon = Array();

icon["snow"] = new GIcon();
icon["snow"].image = "./icon/snow.png";
icon["snow"].shadow = "./icon/snow_s.png";
icon["snow"].iconSize = new GSize(20,20);
icon["snow"].shadowSize = new GSize(21,23);
icon["snow"].iconAnchor = new GPoint(10,10);
icon["snow"].infoWindowAnchor = new GPoint(10,10);

icon["star"] = new GIcon();
icon["star"].image = "./icon/star.png";
icon["star"].shadow = "./icon/star_s.png";
icon["star"].iconSize = new GSize(34,34);
icon["star"].shadowSize = new GSize(35,37);
icon["star"].iconAnchor = new GPoint(17,17);
icon["star"].infoWindowAnchor = new GPoint(17,17);

function createMarker(category,lat,lng,html){
    var point = new GLatLng(lat,lng);
    var marker = new GMarker(point,icon[category]);
    GEvent.addListener(marker, "click", function(){
        map.panTo(new GLatLng(lat,lng));
        marker.openInfoWindowHtml(html);
    });
    return marker;
}

あんまりイラスト汚すのも忍びないので、数も少なめで雰囲気も似せてますが、オリジナルアイコンには影を付けてるのでよく見るとわかると思います。
minZoomというのは、アイコンが出現するレベルで、maxZoomまでは、アイコン出てます。
それ以上のズームレベルになるとアイコン消えます。
1箇所どうにもできないところがあって、mixZoom(オリジナルアイコンが表示されるズームレベル)が1の場合が、ズームレベル0の時も表示されてしまうようです。
これは、バグなんだろうか?
このネタは、もともと「沢山の情報をうまく整理して、楽しげにイラストに落とし込めないか?」というのを解決するために、Google Maps API使ったらできるかな。ということで作ったのが基になってまして、それをメモしてました。
なんかもやもやして解決したいことあったらお気軽にご相談ください。

サンプル

スペシャルサンクス
Sampleで使用しているイラストは、高田さんに無理言って借りちゃいました。
ありがとうございます。
プロジェクト管理ツールBacklog(バックログ)の本体、告知サイトSubversionページのインターフェースデザインも高田さんです。
関連エントリー