Personal tools
You are here: Home 原稿・資料 ワークス、アリエル共同勉強会 Google Mapplets開発
Document Actions

Google Mapplets開発

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

1.

Key features

  • Google Maps
  • Google Maps API
  • KML
  • My Maps
  • Mapplets
  • Geocoding

Key features; Google Maps

  • A Web application (service).
  • The base technology of the following story

Key features; Google Maps API

  • JavaScript API
  • With this API, you can use Google Maps service on your site.

Key features; Google Maps API; architecture

  • sequence diagrams (shows only data transfer)
  • assume 'you' as a developer
  your web       end-user     google server
   server        (browser)

    +-+
    | | html ====> 
    +-+ (js1)
src="http://www.google.com/maps"
                                +-+
                         <====  | | js2
                                +-+
               js runs
               - js1 calls 
                 js2's API
               js2 does
                - load images  <=== images...
                - draw them 
                  on html

Key features; KML

  • KML: Keyhole Markup Language

  • Data format definition (XML)

  • Quote from 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: a company name (bought by Google)

Key features; My Maps

  • A service on Google Maps
  • You can create your own maps by GUI
  • without programming
  • without keyboard
  • without brain

Key features; Mapplets

  • A service on Google Maps
  • A new API of Google Maps
  • It is also JavaScript API
  • What you need for application development is just creating one XML file (although it would contain JavaScript and partial HTML)
  • A Mapplet is a special type of Google Gadget (in the future, I'll talk about it)

Key features; Mapplets; architecture

  • sequence diagrams (shows only data transfer)
  • assume 'you' as a developer
your web       end-user     google server
 server        (browser)


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

            add your mapplet(URL-m)

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

                        <=== js,html

Key features; Geocoding

  • You can get the location from address
  • Geocoding is not a Google specific
  • You can try as follows (the below is an incomplete API key)

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

Google Maps API vs. Mapplets API

If you just want to play with Google Maps programming, use Mapplets API. Because

  • it's easier to develop
  • it's much easier to deploy

If you want to develop a whole site using Google Maps, use Google Maps API. Because

  • you can do everything you want
  • you could make a better site than Google Maps site (in contrast, you're on Google Maps site with Mapplets)

2.

Let's play with Mapplets API.

How to start

  1. get an account of Google Maps (If you're Arieler, you can use gmap@ariel-networks.com)
  2. add the following two Mapplets
  • Mapplet Scratch Pad
  • Developer Mapplet

A simple example

Let's map hello, world!

This is from the official tutorial,

<?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>

Paste this code to 'Mapplet Scratch Pad', and press 'Preview' button.

A simple example (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>

we love prototype.js

Mapplets requires many asynchronous calls.

Personally, I cannot write JavaScript code without prototype.js. prototype.js is huge, so that I use part of it (handling asynchronous calls).

Copy&paste the following code from prototype.js to our Mapplets.

// 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

We have GEvent.bind, but...

  • GEvent.bind
  • GEvent.bindDom

It looks good, but it's insufficient.

We need general 'bind()' like prototype.js for other asynchronous calls.

Development process

  1. Select 'Mapplet Scratch Pad'
  2. Paste the following skelton code
  3. Add your code
  4. Press 'Preview' button
  5. debug your code

Class based skelton code

<?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>

Note

From here, we see only inside of MyMapplet.prototype.

A simple asynchronous call

Shows the center latitude and longitude (only once).

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>';
  }
}

A simple asynchronous call (cont.)

Shows the center latitude and longitude on every move.

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

Shows markers on every click.

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

Shows pretty girls on every click.

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.)

Ariel Area on 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>';
  }
}

For plotting, use KML

If you want to plot static locations, use KML. Don't write a code (loop).

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>';
  }
}

It makes Nakameguro center, and plot two KML data.

KML data are created by 'My Maps'.

Play with Geocoding

All code;

<?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>

Homework

Create a new mapplet.


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