Google MapsのLoadをPromise化する

2015-8-25

Google MapsのLoadをPromise化する。。ってよくわからない題名になりましたが、要するにGoogle Mapsを使ったサイトで遅延ロードするってことです。

Google Mapsを使った地図のマッシュアップ系(古い?)サイトでは、あるアクションが起きた時にはじめて地図を描画したい場合があります。 その場合、別のページに移動するのではなく、Ajax的に地図をロードするためにはひと工夫必要です。

例えば、以前によく行われていたgoogle.loadを使った方法では、ページ自体に<script>タグでgoogleローダーを読み込んでおきますので、実際にGoogle Mapsが使用されない場合は無駄になりますし、ミニマルなサイト構築を心情とする私にとってなんかスッキリしません。

最近ではブラウザの標準機能のみでPromiseが実用的に使用できるようになってきましたので、それを活かして地図がロードされたら何かを実行するということをやりたいときにもgoogle.loadの標準機能では物足りません。

以下のデモは、スクリプトがロードされた直後に何かアクションするのではなく、地図のタイルがすべて描画された後に何かアクションをする簡単なサンプルです。

デモ(ボタンをクリックするとGoogle Mapsがロードされて地図が描画されます)

ここに地図が描画されます。

デモでは、すべてのタイルが描画されたらalertが出るようになっています。

HTMLのコード

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Google MapsのLoadをPromise化する</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
<style>
#map-canvas{
    width: 300px;
    height: 300px;
    border: 1px solid #999;
}
</style>
</head>
<body>
<input id="draw-map" type="button" value="地図を表示する">
<div id="map-canvas">ここに地図が描画されます。</div>
<script>
(function(){
    var div;
    document.getElementById('draw-map').addEventListener('click', function(){
        new Promise(function(resolve){
            window['initMap'] = function(){
                initMap().then(resolve);
                delete window['initMap'];
            }
            var script = document.createElement('script');
            script.src = 'http://maps.googleapis.com/maps/api/js?key=ご自分のAPIキー&callback=initMap';
            document.body.appendChild(script);
        }).then(alert);
    });
    function initMap() {
        var map = new google.maps.Map(document.getElementById('map-canvas'), {
            center: {'lat': 33.172370, 'lng':129.720717},
            zoom: 13
        });
        return new Promise(function(resolve){
            google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
                resolve('done!');
            });
        });
    }
})();
</script>
</body>
</html>

Google mapsのJavaScript呼び出す際に必要なcallback関数も、無駄にグローバル変数として定義するのではなく一時的にグローバル化しているあたりが素敵な感じがしませんか?

元ネタはGFoley83/load-google-maps.jsです。

JavaScript