Google Maps API


Google Maps APIは沢山のサイトでも利用されていて、今更説明の必要もないくらいメジャーなものですが、物凄くシンプルに書くと「Googleマップを活用できるAPI」となります。

詳細をグダグダ書いてもわかりにくくなるし、Google Maps APIの詳細は(これも)色んなところで書かれていますから、参考サイトを最後に紹介するにとどめてここでは実際に運用しているソースコードを中心に紹介していきます。

Google Maps API 目次

準備編

トップページも個別ページも共通になっているのが、ヘッダーへの記述になります。これがないといくら頑張っても表示されませんよ、、

といってもそんなに大変ではなく、次のものをheader.phpのscript typeのまとまりの中に追記するだけ

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>

これで、Google Maps APIを使う準備が整います。

トップページ編

Google Maps APIをトップページに設置するに時に注意するポイントは次の2つです。

1、マップ上に表示したくない記事の排除
2、記事が増えた時にも対応できるようにする

記事には純粋な紹介ページだけではなく、レビューやレポート、場合によっては参考情報のようなものがでてくるかもしれませんが、そういった記事はお店の情報が不要でマップ上に表示したくないと思います。それらを上手く排除しないとマップがおかしくなってしまいます。

また、GoogleマップはJavaScript内に「表示する情報のすべて」を記述しなくてはならないため、記事が増えていった時には自動的に追加される対応が必要になります。それぞれについてのやり方は次のようにしています。

マップ上に表示したくない記事の排除

この方法はいくつもありますが、シンプルに使えるのがカテゴリー分けによる排除です。
WordPressにはカテゴリーの機能がありますから、それを使って記事の公開を分けておいてトップページに表示していいカテゴリだけを取得すればOKです。

具体的にはこのような書き方ですね。

<?php if ( have_posts() ) : query_posts('cat=-9,-10'); ?>
ここに記事のループ
<?php endif; ?>

こうすると、カテゴリーIDが9と10のものは取得しないようになります。
カテゴリーIDは投稿のカテゴリーに行き、カテゴリー名の上にマウスを乗せるとブラウザの下側(ステータスバー)にIDが表示されます。

※東池袋カレーマップではお店の記事以外は書かないように設計しているため、上記の方法は使用していません。

記事が増えた時の対応

なんとなく難しそうな感じですが、(ソースコードは別として)考え方としてはとてもシンプルでWordPressのループ機能を使って記事の情報を読み込むだけ、、、要はトップページにすべての記事を表示させるつもりで作ればいいだけです。

マーカーに必要な緯度経度はすでにカスタムフィールドで埋め込んでありますからそれを使うとして、もう一つ重要なことがあって、それは「マーカー用のID」が必要になること。表示使われているソースコードのこの部分ですね。

これが、1記事ずつユニークになっているので、それを追記してあげる必要があります。
方法論はいくつかあるみたいですが、今回は最初に各ID(全部で4つ)の「スタート=0」を作っておいて、数字を足してく記述を入れています。

リセット用の記述

<?php $m=0; $m1=0; $m2=0; $i=0; $i2=0; ?>

加算部分の例

marker[<?php echo $m++; ?>] 

この記述でループする度に「1」を加算していき、結果的に0から始まる連番で生成されます。

<参考>
この他に記事のIDを使う方法もありますが、最後に説明するMarkerClustererを使うためにはIDが「0」から始まっている必要があるため、この方法にしています。

記事が増えた時の対応(追記)

WordPressでは初期設定で1ページ表示する数が「10」と決まっているため、記事が10ページ以上になる場合は以下のいずれかの方法で1ページに表示できる記事数を増やす必要があります。

[方法1]
ダッシュボード→表示設定で、「1ページに表示する最大投稿数」の数字を編集
Google-map-api

ただしここの数字を変更するとカテゴリページ、月別アーカイブの最大投稿数も変更になってしまいますので、トップページだけ変更したい場合は次の方法を使ってください。

[方法2]
WordPressの記事のループの前にこれを記述します。

<?php query_posts($query_string . "&showposts=100"); ?>

&showpostsの後に続く数字が最大投稿数になりますので、サイトのページ数に合わせて調整してください。

もしもカテゴリを制限している場合は

<?php if ( have_posts() ) : query_posts('cat=-9,-10&showposts=100'); ?>
ここに記事のループ
<?php endif; ?>

とカテゴリ制限につなげて記述する必要があります(他にも書き方はありますが、基本的な考え方は同じです)。

公開しているGoogle Maps APIのソース

実際に公開しているGoogle Maps APIのソースはこのようになっています。

<div id="map" style="width: 579px; height: 620px;"></div>
<script type="text/javascript">
    google.maps.event.addDomListener(window, 'load', function() {
        var mapdiv = document.getElementById( 'map' );
        var myOptions = {
            zoom: 15,
            center: new google.maps.LatLng( 35.728264,139.718276 ),
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scaleControl: true
        };
        var map = new google.maps.Map( mapdiv, myOptions );
 
        var marker = [];
        var infowindow = [];

<?php $m=0; $m1=0; $m2=0; $i=0; $i2=0; ?>

<?php while (have_posts()) : the_post(); ?>

          marker[<?php echo $m++; ?>] = new google.maps.Marker({
            icon: 'http://maps.google.co.jp/mapfiles/ms/icons/blue-pushpin.png',
            position: new google.maps.LatLng( <?php echo post_custom("Map_lat")?>,<?php echo post_custom("Map_lng")?> ),
            map: map,
            title: '<?php the_title(); ?>'
        });
        infowindow[<?php echo $i++; ?>] = new google.maps.InfoWindow({
            content: '<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>',
            size: new google.maps.Size( 50, 30 )
        });
        google.maps.event.addListener( marker[<?php echo $m1++; ?>], 'click', function() {
            infowindow[<?php echo $i2++; ?>].open( map, marker[<?php echo $m2++; ?>] );
        });
<?php endwhile; // End the loop. Whew. ?>
        var markerCluster = new MarkerClusterer( map, marker );
    });
</script>

WordPressのループ部分は以下のところで、その中にカスタムフィールドが引っ張ってきた緯度経度などの情報を入れています。あとIDも前に書いたように、連番になるようにしてあります。

<?php while (have_posts()) : the_post(); ?>
から
<?php endwhile; // End the loop. Whew. ?>

緯度経度の呼び出しはここになっています。

position: new google.maps.LatLng( <?php echo post_custom("Map_lat")?>,<?php echo post_custom("Map_lng")?> ),

ソースとしてはイマイチ綺麗にはまっていない感じはありますが、これを使ってトップページに必要な記事から緯度経度情報と、リンク先の情報を取得してマッピングしています。

地図の中心になる緯度経度

トップページへの表示で少し悩むのが、地図の中心になる緯度経度の求め方です。
個別ページの場合は、各店舗を中心にすればいいのですが、トップページはどこかを基準にするわけにいかないため、自分で探さないといけません。

駅やビルなどランドマークがあればそれを使うのもいいですが、微調整したいこともあると思うのでそういったときには以下のサイトを活用して緯度経度を算出してみるのもいいと思います。

Geekなページ:緯度/経度の取得

地図の大きさ

ソースを見れば一目瞭然ですが、地図の大きさを決めているのはこの部分なので、サイトに合わせて変更してください。

<div id="map" style="width: 579px; height: 620px;"></div>

↑Google Maps API 目次へ

MarkerClustererを使ってマーカーをまとめる

上記の設定でGoogleマップの設置は完了していますが、このままだとマーカーが重なってしまいあまり見栄えのいいものではなくなってしまいます。特に狭い範囲で作っている東池袋カレーマップは数が増えるともう、ごちゃごちゃして汚く感じてしまいます。

それを解消してくれるのが近い場所に複数のマーカーをまとめて表示してくれる MarkerClusterer というものです(正確にはJavaScriptファイル)。

MarkerClustererの導入

1、MarkerClustererのファイル置き場(GUになってません)から、markerclusterer_compiled.jsをクリック
2、ブラウザ上にスクリプトが表示されるので、すべてをコピー
3、テキストエディタを開き、ペースト
4、ファイル名を「markerclusterer_compiled.js」とし保存
5、WordPressのテーマファイルと同じ場所にアップロード
6、[テーマの編集]でheader.phpを開き、「script type」のまとまりの中に以下のソースを追記

<script type="text/javascript" src="<?php bloginfo('stylesheet_directory'); ?>/markerclusterer_compiled.js"></script>

これで、元々は離れていたGoogleマップのピンがひとつにまとまって、まとめた数が数字として表示されるようになります。

<参考>
もし初期設定ではまとまる範囲が広い(狭い)という場合は、アップロードしているmarkerclusterer_compiled.jsの中にある「gridSize||60」という部分の数字を変更することで調整することができます。

↑Google Maps API 目次へ

個別ページ編

個別ページのマップはその記事の情報だけを使用するため、トップページほど複雑にはならず、表示させたいところにこれを書いておけばOKです。

<div id="map" style="width: 440px; height: 200px;"></div>
    <script type="text/javascript">
    google.maps.event.addDomListener(window, 'load', function() {
        var mapdiv = document.getElementById( 'map' );
        var myOptions = {
            zoom: 17,
            center: new google.maps.LatLng( <?php echo post_custom("Map_lat")?>,<?php echo post_custom("Map_lng")?> ),
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scaleControl: true
        };
        var map = new google.maps.Map( mapdiv, myOptions );
        var marker = [];
        var infowindow = [];
marker[0] = new google.maps.Marker({icon: 'http://maps.google.co.jp/mapfiles/ms/icons/blue-pushpin.png',position: new google.maps.LatLng(<?php echo post_custom("Map_lat")?>,<?php echo post_custom("Map_lng")?>),
            map: map,
            title: '<?php the_title(); ?>'
        });
        var markerCluster = new MarkerClusterer( map, marker );
    });
    </script>

トップページと違うところは、記事をループさせていないことと、地図の中心が任意の地点ではなく、実際に店舗がある緯度経度を使っているという点ですね。もちろん、マーカーを表示させるための緯度経度も同じ物を使用しています。

地図の中心を表す緯度経度

center: new google.maps.LatLng( <?php echo post_custom("Map_lat")?>,<?php echo post_custom("Map_lng")?> ),

マーカー用の緯度経度

marker[0] = new google.maps.Marker({icon: 'http://maps.google.co.jp/mapfiles/ms/icons/blue-pushpin.png',position: new google.maps.LatLng(<?php echo post_custom("Map_lat")?>,<?php echo post_custom("Map_lng")?>),

単体で表示させるほうが楽なのがよくわかります。

↑Google Maps API 目次へ

Google Maps APIの参考サイト

Google Maps API ファミリー – Google Code
Geekなぺーじ:Google Maps JavaScript APIプログラミング
Google Maps入門(Google Maps JavaScript API V3)
Google Maps API サンプル集 – Seis Pesos

こちらの書籍も参考になります。

↑Google Maps API 目次へ

Google Maps API への11件のフィードバック

  1. 世界カフェブログ のコメント:

    こんにちは、はじめまして。

    このサイトを拝見して、「世界カフェブログ」というサイトを作りました。
    プラグインやAPIの解説がわかりやすくて、とても助かりました。
    ありがとうございます。

    ひとつ質問させてください。
    このページを拝見して、GoogleMapsのマップを作成したのですが
    バルーン(吹き出し)がバグったように表示されてしまいます(>_<)

    具体的には
    ・影が表示されない
    ・バルーンの形が変
    ・バルーンを消す「×」が表示されない
    という感じです。

    こちらのサイトと、東池袋カレーマップを参考に同じように作ったつもりなのですが
    なぜか上手く表示されません。

    もし何かわかるようでしたら、教えていただけますと幸いです。

    よろしくお願いしますm(_ _)m
     

  2. akane のコメント:

    とてもわかりやすく設置が出来ました。ありがとうございます。

    試しにwordpressに設置をして200件程度のお店を表示しようとしたのですが47件まででしたら問題なく表示されましたが48件以上になると地図が表示されませんでした。地図自体が真っ白で何も表示されず、ソースには全てのお店が表示されています。
    query_posts(‘cat=7&showposts=1000′)で設定しています。
    もし解決方法をご存知でしたら教えていただけませんでしょうか?

  3. akane のコメント:

    申し訳ございません、先ほど原因が分かりました。カスタムフィールドに座標入力できていない48番目の店舗が原因でした。
    サイト、だいぶ参考にさせていただいています。
    ありがとうございます。

  4. tanaka のコメント:

    はじめまして、ホームページ参考にさせていただいて今作成しています。
    個別のページ表示までは出来たのですが。
    トップページにグーグルマップを表示させることが出来ず
    作成に行き詰っております。

    グーグルマップAPIの「公開しているGoogle Maps APIのソース」部分を
    Twenty Tenのloop.phpに入れると思って追加してみましたが
    白い空白が出る状態です。

    もし間違っていればお教えいただければ幸いです。

    • yuji のコメント:

      tanakaさん
      コメントありがとうございます。

      個別ページで表示できている状況から判断するとGoogleMapよりもWordPressのループがうまく行っていない雰囲気はあります。
      ですので、GoogleMapの読み込みとは別にWordPressのループが正しく動作しトップページに緯度経度が表示できているか確認するのがいいと思います。

      もしうまく表示されていなければWordPress側に、うまく表示されていればGoogleMap側に問題があるため、そこを修正すれば改善すると思います。

      ただし、現状がどのようになっているのか、コメントだけでは判断できないので、差し支えなければ公開しているサイトを教えていただけると、より正確なアドバイスができるかと思います。

  5. もんた のコメント:

    このコードを参考にさせてもらっています。

    質問です。

    下記内容でareaというカスタム分類の一覧ページでピンを表示はできました。ありがとうございます。

    が、しかし、ここで問題が。
    すべてのareaのカスタム分類ページで同じ場所を中心として認識してしまいます。当たり前ですよね(+o+)
    理論的にはわかりますが、下記内容は実現可能なのでしょうか?お答えいただければ幸いです。

    私は、areaというカスタム分類をtaxonomy-area.phpで現在のタームを取得して一覧表示させてます。
    各areaページで中心地を“自動で指定する”場合どういう風に記述すればいいのでしょうか?
    またそんなことできるのでしょうか…。
    それは、ページテンプレートを一ページずつ作ってポイントを指定しないと駄目なのでしょうか…。
    例えば大阪ならここ、名古屋ならここ、という感じ…。
    taxonomy-area-osaka.php
    taxonomy-area-nagoya.php
    みたいな感じで…。
    でもそれだと大変ですよね(+o+)
    ご教授頂けますと幸いです。m(__)m

    google.maps.event.addDomListener(window, ‘load’, function() {
    var mapdiv = document.getElementById( ‘map’ );
    var myOptions = {
    zoom: 15,
    center: new google.maps.LatLng( 35.728264,139.718276 ),
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    scaleControl: true
    };
    var map = new google.maps.Map( mapdiv, myOptions );

    var marker = [];
    var infowindow = [];

    get_post_type(), ‘taxonomy’ => $taxonomy_name, ‘term’ => $taxonomy->slug ) );
    $term_var = get_query_var( ‘term’ );//現在のページのタームを取得する
    $myQuery = new WP_Query(); // WP_Queryオブジェクト生成
    $param = array( //パラメータ。
    ‘post_type’ => ‘realestate’, //カスタム投稿タイプのみを指定。
    ‘post_status’ => ‘publish’, //取得するステータスを指定:publish(公開済み)
    ‘taxonomy’ => $taxonomy_name,//タクソノミー
    ‘term’ => $term_var//ターム
    );
    $myQuery->query($param); // クエリにパラメータを渡す
    ?>

    have_posts()): while($myQuery->have_posts()) : $myQuery->the_post(); ?>

    marker[] = new google.maps.Marker({
    icon: ‘http://maps.google.co.jp/mapfiles/ms/icons/blue-pushpin.png’,
    position: new google.maps.LatLng( , ),
    map: map,
    title: ”
    });
    infowindow[] = new google.maps.InfoWindow({
    content: ‘<a href="”>‘,
    size: new google.maps.Size( 50, 30 )
    });
    google.maps.event.addListener( marker[], ‘click’, function() {
    infowindow[].open( map, marker[] );
    });

    var markerCluster = new MarkerClusterer( map, marker );
    });

  6. yuji のコメント:

    もんたさん、コメントありがとうございます。

    カス投稿タイプは自分も色々と試していますが、通常の投稿タイプと比べると設定が複雑になるため、思うような挙動をしてくなくて難しく感じています。

    ご質問の
    >各areaページで中心地を“自動で指定する”場合どういう風に記述すればいいのでしょうか?

    ですが、さすがに緯度経度を自動は持ってくるのは難しいように感じます(別のAPIを走らせる方法もありますが、処理がより複雑になると思います)。

    ただ、Google Mapsの中心は最初の方に出てくる[center: new google.maps.LatLng( 35.728264,139.718276 ),]で指定しているので、この部分をカスタム分類で指定する地域で「中心となる緯度経度」を設定できればテーマファイルを分けなくても対応は可能だと思います。

    動作検証はしていませんが、できそう方法が2つほど考えられるのでお伝えします。

    1、archive内で、条件分岐を使ってカスタム分類ごとで表示を変える。
      idを確認すればできますが、条件分岐が多くなるのが欠点かもしれません。

    2、カスタム分類の「説明」に緯度経度を入力し呼び出す。
      ループ外で説明が取得できるか不明ですし、「,」が大丈夫かも微妙なところです。

    うまくいくのであれば、2の方法のほうが表示速度は早くなると思います。

    なお、カスタム分類の「説明」の表示はこれでいけるはずです。
    ==
    $post_type = get_queried_object();
    echo esc_attr($post_type->description);
    ==
    (前後に<?php ?>が必要カッコは半角にしてください)

    検証ができていないため、確実に動かせるとは言えないのが辛いところですが、カスタム分類で緯度経度を入力できるのは「説明」ぐらいしかないので、これを活用するのが近道のようには感じます。

    すみません、完全解決の解答になっていませんが、気付きのひとつになれば幸いです。

    よろしくお願いします。

    • もんた のコメント:

      ありあがとうございます。

      いろいろ考えて自己解決できました。

      カスタム分類にカスタムフィールドを追加し、タグで呼び出して緯度経度を反映する、という方法で。

      有難うございました。

      • yuji のコメント:

        もんたさん

        自己解決できてなによりです。

        カスタム分類にカスタムフィールドを追加する方法は自分は経験がなく、逆に勉強させせていただくことになりました。ありがとうございます。

        カスタム投稿タイプは複雑な設定になることが多いですが、上手く使うと色々なことができそうですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>