Personal tools
You are here: Home 原稿・資料 ワークス、アリエル共同勉強会 Googleマプレット(Mapplets)開発(日本語版)
Document Actions

Googleマプレット(Mapplets)開発(日本語版)

社内有志の英語勉強会での発表資料の翻訳版です。Google Mapplets開発の説明です。

1.

要素技術

  • Google Maps
  • Google Maps API
  • KML
  • マイマップ
  • マプレット
  • Geocoding

要素技術; Google Maps

  • Webアプリの名称(サービス)
  • 今から話すことのベース技術です

要素技術; Google Maps API

  • JavaScriptのAPIです
  • このAPIを使うと、Google Mapsのサービスを自分のサイトで利用できます

要素技術; Google Maps API; アーキテクチャ

  • 動作シーケンス (データ転送のみを記述)
  • 'you'を開発者と想定しています
  your web       end-user     google server
   server        (browser)

    +-+
    | | html ====> 
    +-+ (js1)
src="http://www.google.com/maps"
                                +-+
                         <====  | | js2
                                +-+
               jsが走る
               - js1が
                 js2のAPIを
                 呼ぶ
               js2が
                - 画像のロード  <=== images...
                をして
                - HTML上に描画

要素技術; KML

  • KML: Keyhole Markup Language

  • データフォーマット(XML)の定義

  • http://code.google.com/apis/kml/ から引用

    KML is a file format used to display geographic data in an earth browser, such as Google Earth, Google Maps and Google Maps for mobile.

  • @fyi Keyhole: 会社名(Googleに買収された)

要素技術; マイマップ

  • Google Maps上のサービスのひとつ
  • 自分のマップをGUIで作れます
  • プログラミング不要
  • キーボード不要
  • ついでに、脳味噌も不要

要素技術; マイマップ (cont.)

KMLの出力例

要素技術; マプレット

  • Google Maps上のサービスのひとつ
  • Google Mapsの新しいAPIです
  • これもJavaScript APIです
  • アプリ開発に必要なことはXMLファイルをひとつ作ることだけです (もっとも、JavaScriptのコードとHTMLの断片を含んだXMLですが)
  • マプレットはGoogle Gadgetsの一種です

要素技術; マプレット; アーキテクチャ

  • 動作シーケンス (データ転送のみを記述)
  • 'you'を開発者と想定しています
your web       end-user     google server
 server        (browser)


                        <===  http://maps.google.co.jp
                              contents(html,images,...)

            あなたのmappletを追加(URL-m)

 URL-m
  +-+
  | |   ====================> XML(Mapplet application)
  +-+

                        <=== js,html

要素技術; Geocoding

  • アドレスから位置情報を取得できます
  • GeocodingはGoogle固有の技術ではありません
  • 以下のように試せます (注意; APIキーは不完全にしています)

http://maps.google.co.jp/maps/geo?q=tokyo&output=xml&key=BQIAAAAQwOsu0fP7tQWAZVG5p5O0RTMBGvk5A1EIQY4Y1odibCkfESiaRTFS6ybq1JabfkHa1y8or-OOgh_6w

Google Maps API vs. マプレットAPI

もしGoogle Mapsプログラミングを手軽に楽しみたいなら、マプレット APIを勧めます 理由は

  • 作るのが簡単
  • デプロイも簡単

Google Mapsを使った新しいサービスを作りたい場合、Google Maps APIを勧めます 理由は

  • とりあえずなんでもできます(APIの範囲ですが)
  • Google Mapsサイトを越えるサイトを作るかもしれません (マプレットを使う限り、Google Mapsサイトの手の中から出られません)

2.

マプレット APIで遊んでみましょう

始め方

  1. Google Mapsのアカウントを取得してください (アリエルの人は、gmap@ariel-networks.com を共用アカウントとして使えます)
  2. 以下のふたつのマプレットを選択追加してください
  • Mapplet Scratch Pad
  • Developer Mapplet

簡単な例

とりあえず、hello, world!

Googleのチュートリアルから引用

<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello World" 
             description="Displays a Hello World message in the left panel"
             author="ariel"
             author_email="gmap@ariel-networks.com"
             height="150">
  <Require feature="sharedmap"/>
</ModulePrefs>
<Content type="html"><![CDATA[
<h2>Hello World!</h2>
]]></Content>
</Module>

このコードを'Mapplet Scratch Pad'にペースして、'Preview'ボタンを押してください

簡単な例 (cont)

<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello World" 
             description="Displays a Hello World message in the left panel"
             author="ariel"
             author_email="gmap@ariel-networks.com"
             height="150">
  <Require feature="sharedmap"/>
</ModulePrefs>
<Content type="html"><![CDATA[
<script type="text/javascript">
function init() {
  alert('init called');
}
function onClick() {
  alert('onClick called');
  _gel('content').innerHTML = 'innerHTML is our friend';  // _gel() is document.getElementById()
}
_IG_RegisterOnloadHandler(init);
</script>
<style type="text/css"> 
.highlight { color: red }
</style>
<h2 class="highlight" onclick="onClick()">Hello World!</h2>
<div id="content"/>
]]></Content>
</Module>

prototype.js

マプレットのアプリ開発では、多くの非同期呼び出しが必要です

個人的に、prototype.js無しでJavaScriptのコードが書けません。 prototype.jsは巨大なので、一部(非同期呼び出しまわり)のコードだけ拝借します

以下のコードをマプレットのアプリのコードにコピー&ペーストしてください

// derived from prototype.js  =begin
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}
// derived from prototype.js  =end

GEvent.bindがありますが...

  • GEvent.bind
  • GEvent.bindDom

一見良さそうですが、これらだけでは不充分です

汎用的な'bind()'が必要なので、prototype.jsのbind()を使います

開発プロセス

  1. 'Mapplet Scratch Pad'アプリを選択
  2. 以下のスケルトンコードをペースト
  3. 自分のコードを追加
  4. 'Preview'ボタンを押して動作確認
  5. デバッグ

クラスベースのスケルトンコード

<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello World" 
             description="Displays a Hello World message in the left panel"
             author="ariel"
             author_email="gmap@ariel-networks.com"
             height="150">
  <Require feature="sharedmap"/>
</ModulePrefs>
<Content type="html"><![CDATA[
<script type="text/javascript">
// derived from prototype.js  =begin
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}
// derived from prototype.js  =end
var MyMapplet = Class.create();
MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    // ADD YOUR CODE(initialization)
  },
  // ADD YOUR CODE
  debug: function(msg) {      // this is your only friend
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}
function init() {
  new MyMapplet();
}
_IG_RegisterOnloadHandler(init);
</script>
<div id="msg"/>
]]></Content>
</Module>

注意

以降、MyMapplet.prototype 内のみを表記します

簡単な非同期呼び出しの例

中心の座標を表示します(一回のみ)

MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    this.map.getCenterAsync(function(latlng) {
      this.debug('lat = ' + latlng.lat() + ', lng = ' + latlng.lng());
    }.bind(this));
  },
  debug: function(msg) {
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}

簡単な非同期呼び出しの例 (cont.)

中心の座標を表示します(移動ごと)

MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    GEvent.addListener(this.map, 'dragend', this.onMove.bind(this));
  },
  onMove: function() {
    this.map.getCenterAsync(function(latlng) {
      this.debug('lat = ' + latlng.lat() + ', lng = ' + latlng.lng());
    }.bind(this));
  },
  debug: function(msg) {
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}

マーカー(Marker)

クリックごとにマーカーを表示します

MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    GEvent.addListener(this.map, 'click', this.onClick.bind(this));
  },
  onClick: function(overlay, point) {
    if (!overlay) {
      this.map.addOverlay(new GMarker(point));
    }
  },
  debug: function(msg) {      // this is your only friend
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}

InfoWindow

クリックすると、女性が現れます

MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    GEvent.addListener(this.map, 'click', this.onClick.bind(this));
  },
  onClick: function(overlay, point) {
    if (point) {      // point could be null
      if (!overlay) {
        this.map.openInfoWindowTabsHtml(point, 
                                        [new GInfoWindowTab('tozawa', '<img src="http://www.ariel-networks.com/company/employee/images/tozawa.jpg"/>'), 
                                         new GInfoWindowTab('takatera', '<img src="http://www.ariel-networks.com/company/employee/images/takatera.jpg"/>'), 
                                         new GInfoWindowTab('tien', '<img src="http://www.ariel-networks.com/company/employee/images/tien.jpg"/>')]);
      }
    }
  },
  debug: function(msg) {      // this is your only friend
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}

InfoWindow(cont.)

クリックすると、Google Maps上にありえりえりあが現れます

MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    GEvent.addListener(this.map, 'click', this.onClick.bind(this));
  },
  onClick: function(overlay, point) {
    if (point) {
      this.map.openInfoWindowHtml(point, '<iframe src="http://dev.ariel-networks.com"/>');
    }
  },
  debug: function(msg) {      // this is your only friend
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}

プロットするなら、KML

静的な位置情報をプロットするだけならKMLを使ってください。 コードを書く必要はありません(書いてはいけません)。

MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    this.map.setCenter(new GLatLng(35.644307, 139.699157), 15);
    this.map.addOverlay(new GGeoXml("http://maps.google.co.jp/maps/ms?hl=ja&gl=jp&ie=UTF8&msa=0&msid=107061927227382858092.0004436b779d2ca57b1a9&z=17&om=1&output=kml"));
    this.map.addOverlay(new GGeoXml("http://maps.google.co.jp/maps/ms?ie=UTF8&hl=ja&msa=0&msid=107466427548098455555.00043a52ff3965b48e83c&z=17&om=1&output=kml"));
  },
  debug: function(msg) {
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}

上記コードは中目黒を中心に、ふたつのKMLをプロットします。 KMLは'マイマップ'で生成しています。

Geocodingを使う例

全コード掲載;

<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Hello World" 
             description="Displays a Hello World message in the left panel"
             author="ariel"
             author_email="gmap@ariel-networks.com"
             height="150">
  <Require feature="sharedmap"/>
</ModulePrefs>
<Content type="html"><![CDATA[
<script type="text/javascript">
// derived from prototype.js  =begin
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}
// derived from prototype.js  =end
var MyMapplet = Class.create();
MyMapplet.prototype = {
  initialize: function() {
    this.map = new GMap2();
    this.geocoder = new GClientGeocoder();
    this.geo_input = _gel('geo-input');
    GEvent.bindDom(this.geo_input, 'change', this, this.onInput);
  },
  onInput: function(ev) {
    var address = this.geo_input.value;
    this.geocoder.getLatLngAsync(
        address,
        function(latlng) {
          if (!latlng) {
            alert(address + " not found");
          } else {
            this.map.setCenter(latlng, 15);
            var marker = new GMarker(latlng);
            this.map.addOverlay(marker);
            marker.openInfoWindowHtml(address);
          }
        }.bind(this)
    );
  },
  debug: function(msg) {
    _gel('msg').innerHTML += '<div>' + msg + '</div>';
  }
}
function init() {
  new MyMapplet();
}
_IG_RegisterOnloadHandler(init);
</script>
<input type="text" id="geo-input"/>
<div id="msg"/>
]]></Content>
</Module>

宿題

何かマプレットを作ってみてください


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.