Опубликован: 21 января 2010, 12:11, Автор: MaXyC

1. Добавляем карту на вашу страницу.


Начать, естественно, нужно с получения ключа для вашего сайта. Его можно получить бесплатно по адресу code.google.com/apis/maps/signup.html.
Можно просто взять пример, размещенный ниже ключа и, вуаля — карта отображается. В моем же примере будет использоваться страница:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAavRvsXgW_9PVxA6hl0_PfhT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSeXrMELfDdhW0HaXIfNtG9z0yrzQ"
    type="text/javascript"></script>
<script type="text/javascript">
  var map;
  var marker;
  
  function initApp() {
    if (GBrowserIsCompatible()) {
      map = new GMap2(document.getElementById('map'));
      map.setCenter(new GLatLng(40, 0), 2);
      map.addControl(new GSmallMapControl());
      map.addControl(new GMapTypeControl());
      var icon = new GIcon();
      icon.image  = '/img/arrow.png';
      icon.shadow = '';
      icon.iconSize   = new GSize(36, 45);
      icon.shadowSize = new GSize(0, 0);
      icon.iconAnchor = new GPoint(18, 45);
      
      var opts = {
        "icon": icon,
        "draggable": true
      }
      marker = new GMarker(new GLatLng(40, 0), opts);
      map.addOverlay(marker);
    }else{
      alert('Простите, но ваш браузер не совместим с Google Maps');
    }
  }
</script>
<style type="text/css">
  #map{ width: 600px; height: 400px; }
</style>
</head>
<body onload="initApp();" onunload="GUnload();">
  <div>
    <div id="map"></div>
  </div>
</body>
</html>


Google рекомендует использовать , но это пригодится только в том случае, если мы будем рисовать на карте полилинии, т.е. не в нашем.
GBrowserIsCompatible() — проверяем совместим ли браузер с картой
map = new GMap2(document.getElementById('map')) — создаем объект карты. Сейчас в объявлении переменной map как глобальной нет никакой необходимости, однако при развитии примера это нам пригодится.
map.setCenter(new GLatLng(40, 0), 2) — устанавливаем центр карты и начальный масштаб.
Далее добавляем на карту элементы управления:
map.addControl(new GSmallMapControl()) — управление масштабом — мне больше нравится сокращенный вариант без ползунка.
map.addControl(new GMapTypeControl()) — переключение типа карты (топографическая/спутник/гибрид).
Далее добавим на карту маркер.
marker = new GMarker(new GLatLng(40, 0), opts)
Конструктор маркера принимает два параметра — точку, в которую он будет установлен и второй, не обязательный, параметр — набор свойств.
Мы будем использовать всего два из доступных свойств — иконку и возможность перетаскивания. Полный набор свойств можно посмотреть в документации — пространство имен GMarkerOptions.
Иконка задается объектом GIcon и для ее определения нужно указать — путь к файлам иконки и ее тени (обязательно), размер иконки, размер тени и точка привязки иконки.
Точка привязки — это относительные координаты точки изображения в пикселях, которая будет привязываться координатам карты.
Вот, пожалуй, и все что я хотел сделать при добавлении карты.

2. Осуществляем прямое геокодирование.



Геокодирование — процесс назначения географических идентификаторов (таких как географические координаты, выраженные в виде широты и долготы) объектам карты и записям данных.
Т.е. в нашем случае — определение координат места и дополнительной информации о нем по его названию.

Для этого немного усложним наш пример.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAavRvsXgW_9PVxA6hl0_PfhT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSeXrMELfDdhW0HaXIfNtG9z0yrzQ"
    type="text/javascript"></script>
<script type="text/javascript" src="http://nicogoeminne.googlepages.com/greversegeocoderv104.js"></script>
<script type="text/javascript">
  var map;
  var rg;
  var cg;
  var marker;
  
  function initApp() {
    if (GBrowserIsCompatible()) {
      map = new GMap2(document.getElementById('map'));
      map.setCenter(new GLatLng(40, 0), 2);
      map.addControl(new GSmallMapControl());
      map.addControl(new GMapTypeControl());
      var icon = new GIcon();
      icon.image  = '/img/arrow.png';
      icon.shadow = '';
      icon.iconSize   = new GSize(36, 45);
      icon.shadowSize = new GSize(0, 0);
      icon.iconAnchor = new GPoint(18, 45);
      
      var opts = {
        "icon": icon,
        "draggable": true
      }
      marker = new GMarker(new GLatLng(40, 0), opts);
      map.addOverlay(marker);
      cg = new GClientGeocoder();
    }else{
      alert('Простите, но ваш браузер не совместим с Google Maps');
    }
  }
  
  function clearForm(form, start) {
    for (var i=start;i<form.elements.length;i++) {
      form.elements[i].value = '';    
    }
  }
  
  function RGSuccess(placemark) {
    
    if (!('AddressDetails' in placemark)||placemark.AddressDetails.Accuracy == 0) {
      alert('Я об этом месте ничего не знаю.');
      return;
    }
    var address = placemark.AddressDetails;
    var form = document.getElementById('location_updater');
    if (address.Accuracy > 2) {
      if ('SubAdministrativeArea' in address.Country.AdministrativeArea)
        var adminArea = address.Country.AdministrativeArea.SubAdministrativeArea;
      else
        var adminArea = address.Country.AdministrativeArea;
    }
    
    switch(address.Accuracy) {
      case 8:
        var street = adminArea.Locality.Thoroughfare.ThoroughfareName.split(' ');
        form.house.value = street.shift();
        adminArea.Locality.Thoroughfare.ThoroughfareName = street.join(' ');
      case 7:
      case 6:
        form.street.value = adminArea.Locality.Thoroughfare.ThoroughfareName;
      case 5:
      case 4:
        form.city.value = adminArea.Locality.LocalityName;
      case 3:
      case 2:
        form.state.value = address.Country.AdministrativeArea.AdministrativeAreaName;
      case 1:
        form.country.value = address.Country.CountryNameCode;
    }
  }
  
  function CGCallback(responce) {
    if (responce.Status.code != 200) {
      alert(responce.Status.code);
      return;
    }
    var lat = responce.Placemark[0].Point.coordinates[1];
    var lng = responce.Placemark[0].Point.coordinates[0];
    document.getElementById('lat-id').value = lat;
    document.getElementById('lng-id').value = lng;
    map.setCenter(new GLatLng(lat, lng));
    marker.setLatLng(new GLatLng(lat, lng));
    RGSuccess(responce.Placemark[0]);
  }
  

  function setLocation(form) {
    if (!form.location.value.length) {
      alert('Забыли указать место.');
      form.location.focus();
    }else{
      clearForm(form, 2);
      cg.getLocations(form.location.value, CGCallback);
    }
      
    return false;
  }
</script>
<style type="text/css">
  #map{ width: 600px; height: 400px; }
  label { float: left; width: 280px; }
  fieldset { width: 600px; }
  input[type="text"] { width: 300px;}
</style>
</head>
<body onload="initApp();" onunload="GUnload();">
  <div>
    <div id="map"></div><br />
    <form action="index.php" method="get" id="location_updater" onsubmit="return setLocation(this);">
      <label for="location-id">Укажите ваше местоположение:<br /></label>
      <input type="text" value="" name="location" id="location-id" />
      <input type="submit" value="Go" />
      <fieldset>
        <legend>Результаты</legend>
        <label for="lat-id">Широта:<br /></label><input type="text" name="lat" id="lat-id" readonly="readonly" /><br />
        <label for="lng-id">Долгота:<br /></label><input type="text" name="lng" id="lng-id" readonly="readonly" /><br />
        <label for="country-id">Страна:<br /></label><input type="text" name="country" id="country-id" readonly="readonly" /><br />
        <label for="state-id">Штат:<br /></label><input type="text" name="state" id="state-id" readonly="readonly" /><br />
        <label for="city-id">Город:<br /></label><input type="text" name="city" id="city-id" readonly="readonly" /><br />
        <label for="street-id">Улица:<br /></label><input type="text" name="street" id="street-id" readonly="readonly" /><br />
        <label for="house-id">Номер дома:<br /></label><input type="text" name="house" id="house-id" readonly="readonly" /><br />
      </fieldset>
    </form>
  </div>
</body>
</html>


Мы добавили ниже карты поле location — для задания местоположения — и группу полей для отображения результатов.

Теперь о добавления в скрипте.

В функции initApp:
cg = new GClientGeocoder() — заблаговременное создание объекта геокодера.
Функция setLocation — обработчик события отправки формы.
Если поле location не пустое, то очищаем поля формы и запускаем процесс геокодинга. Для этого в классе GClientGeocoder существует два метода:
getLatLng(address, callback), где address — строка исходных данных для геокодинга, а callback — функция обратного вызова, которая принимает единственный параметр — объект GLatLng в случае успеха и null в случае ошибки.
getLocations(address, callback), где address все та же строка исходных данных, а callbaсk функция, принимающая один параметр. В отличие от getLatLng, callback всегда получает в качестве параметра объект следующего вида:


({name:"New York, Madison Ave", Status:{code:200, request:"geocode"}, Placemark:[]})

name — запрос, отправленный геокодеру
Status.code — код операции. Для успешного завершения оперции это 200. Полный список значений можно посмотреть в API Reference GGeoStatusCode.
Status.request — тип запроса. В нашем случа всегда geocode.
Placemark — массив, состоящий из одного или нескольких объектов, описывающих географическую точку.

Формат описания географической точки непостоянен и изменяется в зависимости от уровня точности, с которым удалось определить место, и от того, имеет ли страна внутренее административное деление (и знает ли об этом гугл).
Так, например, по запросу new york, Madison ave 25 мы получаем:

{
  id:"p1", 
  address:"25 Madison Ave, New York, NY 10010, USA", 
  AddressDetails:{
    Country:{
      CountryNameCode:"US", 
      AdministrativeArea:{
        AdministrativeAreaName:"NY", 
        SubAdministrativeArea:{
          SubAdministrativeAreaName:"Manhattan", 
          Locality:{
            LocalityName:"New York", 
            Thoroughfare:{
              ThoroughfareName:"25 Madison Ave"
            }, 
            PostalCode:{
              PostalCodeNumber:"10010"
            }
          }
        }
      }
    }, 
    Accuracy:8
  }, 
  Point:{
    coordinates:[-73.987063, 40.742104, 0]
  }
}


а для «Киев»

{
  id:"p1", 
  address:"Kyiv, Kyyivs'ka, Ukraine", 
  AddressDetails:{
    Country:{
      CountryNameCode:"UA", 
      AdministrativeArea:{
        AdministrativeAreaName:"Kyyivs'ka", 
        Locality:{
          LocalityName:"Kyiv"
        }
      }
    }, 
    Accuracy:4
  }, 
  Point:{
    coordinates:[30.503828, 50.453629, 0]
  }
}<code>

Уровень точности может принимать значение от 0 до 8.
<pre>
Значение	Расшифровка
    0	  Точка не найдена
    1	  С точностью до страны
    2	  С точностью до административной еденицы (штат, провинция, префектура)
    3	  Sub-region (county, municipality, etc.) level accuracy. Признаться, так и не смог перевести. Для нашей Украины этот уровень -- область
    4	  С точностью до населенного пункта
    5	  С точностью до почтового кода
    6	  С точносью до улицы
    7	  С точностью до перекрестка
    8	  С точностью до адреса
</pre>
Функция RGSuccess разбирает объект placemark и присваивает соответствующим полям формы значения.

<h4>3. Осуществляем обратное геокодирование</h4>
Обратное геокодирование - это обратная взаимосвязь, при которой каждая географическая координата связывается с ближайшим известным адресом.

<code><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAavRvsXgW_9PVxA6hl0_PfhT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSeXrMELfDdhW0HaXIfNtG9z0yrzQ"
    type="text/javascript"></script>
<script type="text/javascript" src="http://nicogoeminne.googlepages.com/greversegeocoderv104.js"></script>
<script type="text/javascript">
  var map;
  var rg;
  var cg;
  var marker;
  
  function initApp() {
    if (GBrowserIsCompatible()) {
      map = new GMap2(document.getElementById('map'));
      map.setCenter(new GLatLng(40, 0), 2);
      map.addControl(new GSmallMapControl());
      map.addControl(new GMapTypeControl());
      var icon = new GIcon();
      icon.image  = '/img/arrow.png';
      icon.shadow = '';
      icon.iconSize   = new GSize(36, 45);
      icon.shadowSize = new GSize(0, 0);
      icon.iconAnchor = new GPoint(18, 45);
      
      var opts = {
        "icon": icon,
        "draggable": true
      }
      marker = new GMarker(new GLatLng(40, 0), opts);
      marker.enableDragging();
      GEvent.addListener(marker, 'dragend', markerDrugged);
      map.addOverlay(marker);
      
      cg = new GClientGeocoder();
      
      rg = new GReverseGeocoder(map);
      GEvent.addListener(rg, "load", RGSuccess);
      GEvent.addListener(rg, "error", RGError);
    }else{
      alert('Простите, но ваш браузер не совместим с Google Maps');
    }
  }
  
  function clearForm(form, start) {
    for (var i=start;i<form.elements.length;i++) {
      form.elements[i].value = '';    
    }
  }
  
  function markerDrugged() {
    var latlng = this.getLatLng();
    var form = document.getElementById('location_updater');
    form.lat.value = latlng.lat();
    form.lng.value = latlng.lng();
    clearForm(form, 5) 
    rg.reverseGeocode(latlng);
    map.setCenter(latlng);
  }
  function RGSuccess(placemark) {
    
    if (!('AddressDetails' in placemark)||placemark.AddressDetails.Accuracy == 0) {
      alert('Я об этом месте ничего не знаю.');
      return;
    }
    var address = placemark.AddressDetails;
    var form = document.getElementById('location_updater');
    if (address.Accuracy > 2) {
      if ('SubAdministrativeArea' in address.Country.AdministrativeArea)
        var adminArea = address.Country.AdministrativeArea.SubAdministrativeArea;
      else
        var adminArea = address.Country.AdministrativeArea;
    }
    
    switch(address.Accuracy) {
      case 8:
        var street = adminArea.Locality.Thoroughfare.ThoroughfareName.split(' ');
        form.house.value = street.shift();
        adminArea.Locality.Thoroughfare.ThoroughfareName = street.join(' ');
      case 7:
      case 6:
        form.street.value = adminArea.Locality.Thoroughfare.ThoroughfareName;
      case 5:
      case 4:
        form.city.value = adminArea.Locality.LocalityName;
      case 3:
      case 2:
        form.state.value = address.Country.AdministrativeArea.AdministrativeAreaName;
      case 1:
        form.country.value = address.Country.CountryNameCode;
    }
  }
  
  function CGCallback(responce) {
    document.getElementById('debug').innerHTML = responce.toSource();
    if (responce.Status.code != 200) {
    //обработка ошибок
      alert(responce.Status.code);
      return;
    }
    var lat = responce.Placemark[0].Point.coordinates[1];
    var lng = responce.Placemark[0].Point.coordinates[0];
    document.getElementById('lat-id').value = lat;
    document.getElementById('lng-id').value = lng;
    map.setCenter(new GLatLng(lat, lng));
    marker.setLatLng(new GLatLng(lat, lng));
    RGSuccess(responce.Placemark[0]);
  }
  
  function RGError() {
    alert('Я об этом месте ничего не знаю.');
  }
  
  
  function setLocation(form) {
    if (!form.location.value.length) {
      alert('Забыли указать место.');
      form.location.focus();
    }else{
      clearForm(form, 2);
      cg.getLocations(form.location.value, CGCallback);
    }
      
    return false;
  }
</script>
<style type="text/css">
  #map{ width: 600px; height: 400px; }
  label { float: left; width: 280px; }
  fieldset { width: 600px; }
  input[type="text"] { width: 300px;}
</style>
</head>
<body onload="initApp();" onunload="GUnload();">
  <div>
    <div id="map"></div><br />
    <form action="index.php" method="get" id="location_updater" onsubmit="return setLocation(this);">
      <label for="location-id">Укажите ваше местоположение:<br /></label>
      <input type="text" value="" name="location" id="location-id" />
      <input type="submit" value="Go" />
      <fieldset>
        <legend>Результаты</legend>
        <label for="lat-id">Широта:<br /></label><input type="text" name="lat" id="lat-id" readonly="readonly" /><br />
        <label for="lng-id">Долгота:<br /></label><input type="text" name="lng" id="lng-id" readonly="readonly" /><br />
        <label for="country-id">Страна:<br /></label><input type="text" name="country" id="country-id" readonly="readonly" /><br />
        <label for="state-id">Штат:<br /></label><input type="text" name="state" id="state-id" readonly="readonly" /><br />
        <label for="city-id">Город:<br /></label><input type="text" name="city" id="city-id" readonly="readonly" /><br />
        <label for="street-id">Улица:<br /></label><input type="text" name="street" id="street-id" readonly="readonly" /><br />
        <label for="house-id">Номер дома:<br /></label><input type="text" name="house" id="house-id" readonly="readonly" /><br />
      </fieldset>
    </form>
  </div>
  <div id="debug">
  </div>
</body>
</html>


Как видите, пример не очень усложнился.
1. Подключаем скрипт обратного геокодирования
На данный момент еще не было официального релиза данного сервиса. Вся документация и исходные тексты могут быть найдены по адресу nicogoeminne.googlepages.com/documentation.html
2. В функции initApp создаем объект GReverseGeocode и навешиваем обработчики на его события. Также навешиваем обработчик на перетаскивания маркера (именно так в нашем примере будут изменяться координаты)
rg = new GReverseGeocoder(map);
GEvent.addListener(rg, "load", RGSuccess);
GEvent.addListener(rg, "error", RGError);
GEvent.addListener(marker, 'dragend', markerDrugged);<code>
3. Обработчик markerDrugged.
Если обработчик был навешен с помощью GEvent.addListener, то он будет выполнятся в контексте объекта, для которого произошло событие. Т.е., в нашем случае, this в функции markerDrugged будет указывать на объект маркера.
Далее заполняем поля формы, устанавливаем центр карты в ту точку, куда перетащили маркер, и запускаем процесс обратного геокодирования.
4. Обработчиком события для успешного завершения обратного геокодирования выступает уже рассматривавшаяся нами функция RGSuccess. Дело в том, что в обработчик передается объект placemark, который мы при прямом геокодировании передавали из CGCallback.


  • Blogger Post
  • Delicious
  • Digg
  • Google Gmail
  • Google Bookmarks
  • Google Reader
  • LiveJournal
  • MySpace
  • StumbleUpon
  • Technorati Favorites
  • Twitter
  • Yahoo Bookmarks
  • Yahoo Mail
  • Yahoo Messenger
  • WordPress

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.