ブログ (Movable Type) と Google Map を組み合わせる

今回取り組む内容の仕様としては、以下の通りである。
  • ブログを利用する。
  • ブログに自分の好きな地域(どこかは予め決めておく)の地図を表示する。
  • 地図にはマーカーが表示される。
  • マーカーの情報は AJAX (XMLHttpRequest) の非同期通信により、サーバーから XML ファイルを読み込んだものである。
  • マーカーをクリックすると吹き出しにその地点の情報が出る。
  • 吹き出し中の「続きを読む」リンクをクリックすると、ブログエントリにジャンプする。
  • マーカーは自分独自のアイコンを使う。
まずは、実例をみてイメージをつかんでもらった方がいいだろう。 このサイトで動作している JavaScript は以下のものである。
//<![CDATA[

var BASE_URL = "https://2kids.net";   
var GMAP_FILE = "/yas/gmap.xml";
var ICON_DEFAULT = "/yas/images/icon_restaurant.png";
var ICON_SHADOW = "/yas/images/icon_restaurant_shadow.png";

var map;
var baseicon;
var xmlHttp;

function init() {

    map      = new GMap(document.getElementById("map")); // 地図オブジェクトを生成
    baseicon = new GIcon();  // アイコンオブジェクトを作成
    xmlHttp  = GXmlHttp.create(); // XmlHttpRequest オブジェクトを作成

    // 地図を設定
    map.addControl(new GLargeMapControl()); // 拡大縮小のボタン
    map.addControl(new GMapTypeControl());  // 地図と衛星の切り替え
    map.centerAndZoom(new GPoint(-122.0745, 37.4170), 7); // ベイエリアを表示
   
    // アイコンを設定
    baseicon.image            = BASE_URL + ICON_DEFAULT;
    baseicon.shadow           = BASE_URL + ICON_SHADOW;
    baseicon.iconSize         = new GSize (16, 16);
    baseicon.shadowSize       = new GSize (34, 20);
    baseicon.iconAnchor       = new GPoint( 8,  8);  // <- (icon_width / 2, icon_height)
    baseicon.infoWindowAnchor = new GPoint( 9,  2);
    baseicon.infoShadowAnchor = new GPoint(18, 25);
   
    // マーカーを設定: XML データを読み込んで表示
    xmlHttp.open("GET", BASE_URL + GMAP_FILE,  true);
    xmlHttp.onreadystatechange = showMarkers;
    xmlHttp.send(null);
}

function showMarkers() {

    if (xmlHttp.readyState == 4) {

        var xmlDoc = xmlHttp.responseXML;
        var marker = xmlDoc.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < marker.length; i++) {
            addMarker(marker[i]);
        } // End of for
    }
}

function addMarker(xml) {

    var point  = new GPoint(xml.getAttribute("lng"),
                            xml.getAttribute("lat"));
    baseicon.image = BASE_URL + xml.getAttribute("icon");
    var icon   = new GIcon(baseicon);
    var marker = new GMarker(point, icon);
    map.addOverlay(marker);
    var html   = '<div id="InfoWindow">'
               + '<img src="' + baseicon.image + '" alt="icon"> '
               + '<a href="' + xml.getAttribute("site") + '">'
               + xml.getAttribute("name")
               + '</a><br />'
               + xml.getAttribute("street") + '<br />'
               + xml.getAttribute("city")   + '<br />'
               + xml.getAttribute("phone")  + '<br />'
               + '<a href="' + BASE_URL + xml.getAttribute("link") + '">'
               + 'レビューを読む'
               + '</a><br />'
               + '</div>';
    GEvent.addListener(marker, "click", function() {
    //  marker.showMapBlowup(3);  // 吹き出しに地図が表示される模様。
    //  map.centerAndZoom(p, 3);
        marker.openInfoWindowHtml(html);
    });  // click のイベントリスナ登録
}
//]]>
このスクリプトは以下のようなフォーマットの XML データを利用する。
<markers>

    <marker
        lng="-121.9485855102539" lat="37.318707484418496"
        icon="/yas/images/icon_mexican.png"
        name="Chevys Winchester"
        site="https://www.chevys.com/"
        link="/yas/archives/cat60/#a000761"
        street="550 S. Winchester"
        city=" San Jose, CA 95128"
        phone="(408) 241-0158"
    />

<!-- 以下、上と同じデータの繰り返し。必要なだけ増やす。-->

</markers>
さて、それでは仕組みについてひとつひとつ説明していこう。 今回の動作確認済み環境としては、以下の通りである (2005/10/28 現在)。
  • Movable Type 3.2 Release 2 (日本語版)
  • Firefox 1.0.7 または IE 6.0SP2 または Safari 2.0.1
というわけでここでは Movable Type 3.2 Release 2 (日本語版) と Firefox 1.0.7 を例に取って話を進める。以下は必要な手順である。
  1. アイコンの作成 (Google Map に表示するマーカーのこと)
  2. JavaScript 作成 (Google Map 用)
  3. map.xml の作成 (XMLHttpRequest を使ってマーカーの情報を読み込む)
  4. ブログテンプレートの修正
  5. スタイルシートの設定
  6. ブログエントリの追加
それではまずはアイコンについ説明しよう。
  • Google Map API では、マーカーと呼ばれるポイントを指し示すアイコンが必要となる。Google が用意したデフォルトのマーカーアイコンはオレンジ色の水玉を逆さにしたような感じのものだが、これは自由にカスタマイズできる。
  • アイコンの実体は画像ファイルである。画像のフォーマットは、JPEG、GIF、PNG が使えるが、PNG がいいだろう。
  • なぜなら、アイコンには影を付けられるのだが、この影は、αチャネルを透過にした PNG を使うことになっているからだ (まぁ、どの画像フォーマットを選ぶかは実際は好みの問題だ)。
  • ちなみにアイコンの影は、オリジナルのアイコンに対して45度の傾きを付けるのが、Google からのガイドラインのようである。実際影をつけるのは結構難しかった。私の場合はオリジナル画像をグレー処理し、その後何度かソフト処理をし、ぼかしをかけた…という感じで、この作業に多くの時間を取ってしまった^^;
以下、JavaScript からのアイコン部分生成に関する抜粋だ。要は、GIcon オブジェクトに用意されているいろいろなプロパティを設定してあげれば、自分で作ったアイコンが表示されるのである。
var BASE_URL = "https://2kids.net";
var baseicon;

function init() {

    baseicon = new GIcon();  // アイコンオブジェクトを作成

    // アイコンを設定
    baseicon.image            = BASE_URL + "/yas/images/icon_restaurant.png";
    baseicon.shadow           = BASE_URL + "/yas/images/icon_restaurant_shadow.png";
    baseicon.iconSize         = new GSize (16, 16);
    baseicon.shadowSize       = new GSize (34, 20);
    baseicon.iconAnchor       = new GPoint( 8,  8);  // <- (icon_width / 2, icon_height)
    baseicon.infoWindowAnchor = new GPoint( 9,  2);
    baseicon.infoShadowAnchor = new GPoint(18, 25);
    baseicon.image = BASE_URL + xml.getAttribute("icon");
}

function addMarker(xml) {

    var point  = new GPoint(xml.getAttribute("lng"),
                            xml.getAttribute("lat"));
    baseicon.image = BASE_URL + xml.getAttribute("icon");
    var icon   = new GIcon(baseicon);
    var marker = new GMarker(point, icon);
    map.addOverlay(marker);
}
//]]>
次に肝心の JavaScript であるが、Movable Type のテンプレート作成機能を利用する。Movable Type で、環境設定 / テンプレート-モジュールと選択していき、「モジュールを新規作成」をクリックして以下のように作成(設定)し、保存する。
  • テンプレート名: gmap.js (←ここは実は何でもいい)
  • このテンプレートにリンクするファイル: gmap.js (別のテンプレートから使用するファイル名)
  • モジュールの内容: 冒頭の JavaScript
JavaScript を保存したら、
map.xml
というファイル名で、XML ファイルを保存する。以下に XML ファイルの内容 (属性) を説明しよう (属性は独自に設定したものです)。
<markers>

    <marker
        lng="-121.9485855102539" lat="37.318707484418496" <font color="blue">← ここは、</font><b><font color="orange">経度</font><font color="blue">・</font><font color="red">緯度</font></b><font color="blue">の順で入る</font>
        icon="/yas/images/icon_mexican.png" <font color="blue">← アイコン画像へのルートからのパス + ファイル名 (https:// は、JavaScript 中の最初に記述済み)</font>
        name="Chevys Winchester" <font color="blue">← 吹き出し中の一番上に表示される、マーカーの名前</font>
        site="https://www.chevys.com/" <font color="blue">← マーカーの名前をクリックすると表示されるウェブページ</font>
        link="/yas/archives/cat60/#a000761" <font color="blue">← Movable Type のブログのエントリへのリンク※</font>
        street="550 S. Winchester" <font color="blue">← マーカーの住所 (サンプルはアメリカなので番地が先)</font>
        city=" San Jose, CA 95128" <font color="blue">← マーカーの住所 (サンプルはアメリカなので市町村がが後)</font>
        phone="(408) 241-0158" <font color="blue">← 電話番号</font>
    />

<!-- 以下、上と同じデータの繰り返し。必要なだけ増やす。-->

</markers>
※…「Movable Type のブログのエントリへのリンク」とあるのは、個別ブログについている ID である。個々のブログエントリのソースを見ればわかると思う。 これでスクリプト & XML データの準備が整うので、テンプレートを修正する。環境設定 / テンプレートで、
  • メインページ
  • アーカイブ → カテゴリーアーカイブ
  • アーカイブ → 日付アーカイブ
  • アーカイブ → 個別エントリーアーカイブ
のすべてのテンプレートにおいて、
<head>

<script src="https://maps.google.com/maps?file=api&v=1&key=ここにあなたが取得した Google Map API のキーが入る" type="text/javascript"</script>

<script src="/ルートからブログへのパス/gmap.js" type="text/javascript"></script>
</head>

<body onLoad="init()">

</body>
のように修正する。onLoad="..." で最初に呼ばれる関数を指定しないと、IE ではうまく動作しなかった。また、吹き出し中に表示されるリンクをクリックすることによって、個別のブログエントリにジャンプできるように、テンプレートを少し修正する。ブログエントリのタイトルを表示する箇所を見つけ、以下のように... タグをはさむ。
<a name="a<$MTEntryID pad="1"$>">
<h3 id="a<$MTEntryID pad="1"$>"><$MTEntryTitle$></h3>
</a>
また、個別エントリから地図に戻れるように、以下の部分の最後に「地図に戻る」リンクを追加する。「#a000835」とある部分は、個別ブログエントリで、Google Map を表示したいブログエントリの ID である。
<p class="posted">
投稿者 <$MTEntryAuthor$> : <a href="<$MTEntryPermalink valid_html="1"$>"><$MTEntryDate format="%Y/%m/%d"$></a>
<MTEntryIfAllowComments>
| <a href="<$MTEntryPermalink archive_type="Individual"$>#comments">コメント (<$MTEntryCommentCount$>)</a>
</MTEntryIfAllowComments>
<MTEntryIfAllowPings>
| <a href="<$MTEntryPermalink archive_type="Individual"$>#trackbacks">トラックバック</a>
</MTEntryIfAllowPings>
| <a href="#a000835">地図に戻る</a>
</p>
続いてスタイルシートも設定してしまおう。Movable Type のテンプレート→スタイルシートで、スタイルシートの最後に以下の内容を追加する。
#map {

    font-family: "Trebuchet MS", Trebuchet, verdana, arial, sans-serif;
    text-align: center;
}

#InfoWindow {

    font-family: "Trebuchet MS", Trebuchet, verdana, arial, sans-serif;
}
こんな具合である。#map と #infoWindow を自由にいじってみて欲しい (#InfoWindow は実は JavaScript 中にそのように設定できるように記述してある)。 最後はブログエントリの追加である。ブログの本文に、以下の1行を追加すれば Google Map が表示される。width と height は地図の大きさなので自由に設定して欲しい。
<div id="map" style="width: 500px; height: 400px;"></div>
トラックバック URL: https://perltips.twinkle.cc/trackback/20