Профессиональный пакет API Карт Google
Те же замечательные карты плюс SLA, поддержка и контроль рекламы
Наложения – это объекты на карте, которые привязаны к координатам широты и долготы и перемещаются по мере перетаскивания или масштабирования карты. Наложения добавляются к картам для обозначения точек, линий или областей.
В API Карт предусмотрено несколько типов наложений:
GMarker. Они могут также использовать тип GIcon.GPolyline.GTileLayerOverlay или даже собственный тип карты с помощью класса GMapType.GInfoWindow.Каждое наложение реализует интерфейс GOverlay. Наложения можно добавлять к карте с помощью метода GMap2.addOverlay(), а удалять – с помощью метода GMap2.removeOverlay(). (Обратите внимание, что информационное окно добавляется к карте по умолчанию.)
Маркеры обозначают точки на карте. По умолчанию они используют значок G_DEFAULT_ICON, но можно задать и пользовательский значок. В качестве аргументов в конструкторе GMarker используются GLatLng и необязательный объект GMarkerOptions.
Маркеры –·это интерактивные элементы. По умолчанию, они получают, например, события "click" и служат для вывода информационных окон в прослушивателях событий.
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
// Add 10 markers to the map at random locations
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random());
map.addOverlay(new GMarker(point));
}
Просмотреть пример (marker-simple.html)
Маркеры – это интерактивные объекты, которые можно переносить в новые координаты с помощью мыши. В данном примере на карте будет размещен перетаскиваемый маркер и выполнено прослушивание некоторых простых событий этого маркера. Перетаскиваемые маркеры применяют несколько видов событий, отражающих их состояние перетаскивания: click, dragstart, drag и dragend. По умолчанию маркеры можно активировать нажатием кнопки мыши, но не перетаскивать, поэтому их необходимо инициализировать, установив значение дополнительного параметра маркера draggable равным true. Кроме того, перетаскиваемые маркеры по умолчанию передвигаются резко. Если данное поведение нежелательно, установите значение параметра bouncy равным false, и маркер будет передвигаться плавно.
var map = new GMap2(document.getElementById("map_canvas"));
var center = new GLatLng(37.4419, -122.1419);
map.setCenter(center, 13);
var marker = new GMarker(center, {draggable: true});
GEvent.addListener(marker, "dragstart", function() {
map.closeInfoWindow();
});
GEvent.addListener(marker, "dragend", function() {
marker.openInfoWindowHtml("Just bouncing along...");
});
map.addOverlay(marker);
Просмотреть пример (marker-drag.html)
С маркерами можно сопоставить значок, который будет показываться вместо значка по умолчанию. Сопоставление значка –·довольно сложная процедура, поскольку один значок в API Карт состоит из ряда различных изображений. Для размещения значка необходимо, чтобы он содержал как минимум основное изображение, размер (типа GSize) и смещение значка.
В основе простейших значков лежит тип G_DEFAULT_ICON. Если значок создается на основе этого типа, можно быстро сменить значок по умолчанию, изменив всего несколько свойств.
В следующем примере на основе типа G_DEFAULT_ICON создается значок, в котором затем задается использование другого изображения. (Будьте внимательны при использовании других изображений: для корректного отображения необходимо задать правильный размер, аналогичный размеру изображения по умолчанию.)
var map = new GMap2(document.getElementById("map_canvas"));
map.addControl(new GSmallMapControl());
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
// Create our "tiny" marker icon
var blueIcon = new GIcon(G_DEFAULT_ICON);
blueIcon.image = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
// Set up our GMarkerOptions object
markerOptions = { icon:blueIcon };
// Add 10 markers to the map at random locations
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random());
map.addOverlay(new GMarker(point, markerOptions));
}
Просмотреть пример (icon-simple.html)
Большинство значков состоит из основного изображения и тени. Теневое изображение необходимо создавать под углом 45 градусов (вверх и вправо) от основного изображения, а левый нижний угол теневого изображения должен располагаться на одной прямой с левым нижним углом основного. Чтобы передача границ изображения на карте была корректной, теневые изображения должны быть 24-разрядными PNG-изображениями с альфа-прозрачностью.
В этом примере создается новый тип значка по образцу мини-маркеров поиска такси Google. Необходимо выбрать основное и фоновое изображения, а также точки, в которых значок будет прикреплен к карте, а информационное окно – к значку. Обратите внимание, что значок передается в параметрах, определенных в объекте GMarkerOptions.
var map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
// Create our "tiny" marker icon
var tinyIcon = new GIcon();
tinyIcon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
tinyIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
tinyIcon.iconSize = new GSize(12, 20);
tinyIcon.shadowSize = new GSize(22, 20);
tinyIcon.iconAnchor = new GPoint(6, 20);
tinyIcon.infoWindowAnchor = new GPoint(5, 1);
// Set up our GMarkerOptions object literal
markerOptions = { icon:tinyIcon };
// Add 10 markers to the map at random locations
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random());
map.addOverlay(new GMarker(point, markerOptions));
}
Следует заметить, что на примере объектов GMarkerOptions показано использование нотации литерала объекта. Объект не создается с помощью конструктора; вместо этого объект объявляется с помощью пар (имя, значение).
Просмотреть пример (icon-complex.html)
У объектов GIcon есть также несколько других свойств, которые следует настроить, чтобы добиться максимальной совместимости с браузерами и функциональности значков. Например, свойство imageMap служит для задания формы непрозрачных частей изображения значка. Если это свойство в значке не задано, то все изображение значка (включая прозрачные части) будет активно в браузере Firefox/Mozilla. Дополнительные сведения см. в справочных материалах по классу GIcon.
Во многих случаях у значков могут быть различные основные изображения, но одинаковые форма и тень. Проще всего этого достичь с помощью копирующего конструктора для класса GIcon, выполняющего копирование всех прежних свойств в новый значок, который можно затем настроить.
var map = new GMap2(document.getElementById("map_canvas"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
// Create a base icon for all of our markers that specifies the
// shadow, icon dimensions, etc.
var baseIcon = new GIcon(G_DEFAULT_ICON);
baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
baseIcon.iconSize = new GSize(20, 34);
baseIcon.shadowSize = new GSize(37, 34);
baseIcon.iconAnchor = new GPoint(9, 34);
baseIcon.infoWindowAnchor = new GPoint(9, 2);
// Creates a marker whose info window displays the letter corresponding
// to the given index.
function createMarker(point, index) {
// Create a lettered icon for this point using our icon class
var letter = String.fromCharCode("A".charCodeAt(0) + index);
var letteredIcon = new GIcon(baseIcon);
letteredIcon.image = "http://www.google.com/mapfiles/marker" + letter + ".png";
// Set up our GMarkerOptions object
markerOptions = { icon:letteredIcon };
var marker = new GMarker(point, markerOptions);
GEvent.addListener(marker, "click", function() {
marker.openInfoWindowHtml("Marker <b>" + letter + "</b>");
});
return marker;
}
// Add 10 markers to the map at random locations
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngSpan = northEast.lng() - southWest.lng();
var latSpan = northEast.lat() - southWest.lat();
for (var i = 0; i < 10; i++) {
var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
southWest.lng() + lngSpan * Math.random());
map.addOverlay(createMarker(point, i));
}
Просмотреть пример (icon-custom.html)
Если на карту Google нанесено много маркеров, это может замедлить вывод карты и затруднить ее визуальное восприятие, особенно при некоторых уровнях масштабирования. Программа "Диспетчер маркеров" решает обе эти проблемы. Она позволяет эффективно выводить сотни маркеров на одной и той же карте, а также указывать для каждого маркера уровень масштабирования, начиная с которого его следует выводить.
Программа "Диспетчер маркеров" входит в состав библиотеки служебных программ GMaps. Эта библиотека принадлежит к программному обеспечению с открытым исходным кодом и содержит служебные программы, не принадлежащие к базовым программам API Карт Google. Для добавления программ из этой библиотеки нужно непосредственно добавить исходный код JavaScript с помощью тега <script>.
<script src="http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/src/markermanager.js">
Объект MarkerManager из библиотеки markermanager.js берет на себя управление маркерами, зарегистрированными в программе, следит за тем, какие маркеры должны отображаться при определенных уровнях масштабирования текущего вида, и только эти маркеры передает для вывода на карту. Диспетчер наблюдает за текущим окном просмотра карты и коэффициентом масштабирования, динамически добавляя и удаляя маркеры с карты по мере изменения их активности. Кроме того, поскольку маркеры задают коэффициенты масштабирования, начиная с которого они отображаются, разработчики могут реализовать кластеризацию маркеров. Такое управление сильно ускоряет отображение карты и облегчает ее зрительное восприятие.
Чтобы воспользоваться диспетчером маркеров, нужно создать объект MarkerManager. В простейшем случае карта просто передается этому объекту.
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(41, -98), 4);
var mgr = new MarkerManager(map);
Для более детальной настройки работы диспетчера маркеров можно также задать ряд параметров. Эти параметры передаются через объект MarkerManagerOptions, содержащий следующие поля:
maxZoom: задает максимальный коэффициент масштабирования, за которым наблюдает этот диспетчер маркеров. По умолчанию используется максимальный коэффициент масштабирования, поддерживаемый в Картах Google.borderPadding: определяет необязательное заполнение за пределами текущего окна просмотра карты, отслеживаемого диспетчером, выраженное в пикселях. Это позволяет выводить на карту маркеры, располагающиеся сразу за ее пределами, что улучшает панорамирование для небольших дистанций. Значение по умолчанию – 100.trackMarkers: указывает, должен ли диспетчер маркеров отслеживать их перемещение. Если нужны управляемые маркеры, которые можно перемещать методом setPoint(), установите для этого свойства значение true. По умолчанию эта метка имеет значениеfalse. Следует заметить, что при перемещении маркеров, у которых это свойство имеет значение false, маркеры будут видны одновременно на прежнем месте и на новом.Объект MarkerManagerOptions – это литерал объекта, поэтому его можно просто объявить, не используя конструктор:
var map = new GMap2(document.getElementById("map_canvas"));
var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: true };
var mgr = new MarkerManager(map, mgrOptions);
К созданному диспетчеру нужно добавить маркеры. Класс MarkerManager поддерживает добавление маркеров по одному с помощью метода addMarker() и передачу коллекции как массива с помощью метода addMarkers(). Единичные маркеры, добавленные методом addMarker(), появляются на карте немедленно (если они соответствуют требованиям текущего вида и коэффициента масштабирования).
Рекомендуется добавлять маркеры группами с помощью метода addMarkers(), так как это более эффективно. Маркеры, добавленные с помощью метода addMarkers(), не отобразятся на карте, пока не будет явно вызван такой метод refresh(), как MarkerManager, который помещает на карту все маркеры, попадающие в текущее окно просмотра карты и ее границы заполнения. После начального отображения карты MarkerManager заботится обо всех визуальных изменениях, отслеживая события moveend карты.
В этом примере создается образец карты погоды для Европы. При коэффициенте масштабирования 3 выводятся 20 случайным образом распределенных значков погоды. При уровне 6, позволяющем различить все 200 городов с населением более 300 000, становятся видны еще 200 маркеров. И, наконец, при уровне 8 показано 1000 маркеров. (Примечание. Для упрощения примера маркеры размещаются на карте случайным образом.)
function setupMap() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
map.addControl(new GLargeMapControl());
map.setCenter(new GLatLng(41, -98), 4);
window.setTimeout(setupWeatherMarkers, 0);
}
}
function getWeatherMarkers(n) {
var batch = [];
for (var i = 0; i < n; ++i) {
batch.push(new GMarker(getRandomPoint(), { icon: getWeatherIcon() }));
}
return batch;
}
function setupWeatherMarkers() {
mgr = new MarkerManager(map);
mgr.addMarkers(getWeatherMarkers(20), 3);
mgr.addMarkers(getWeatherMarkers(200), 6);
mgr.addMarkers(getWeatherMarkers(1000), 8);
mgr.refresh();
}
Просмотреть пример (weather_map.html)
Диспетчер маркеров может также выполнять простую кластеризацию маркеров. Он не делает этого автоматически, но такого эффекта можно добиться, задав одновременно минимальный и максимальный уровни масштабирования, при которых показывается данный маркер. В данном примере создается карта отделений компании Google в Северной Америке. При максимальном уровне видны флаги стран, в которых расположены отделения компании. При уровнях масштабирования от 3 до 7 показываются значки у населенных пунктов, где расположено хотя бы одно отделение. И, наконец, при уровне 8 и выше выводятся отдельные маркеры для каждого отделения.
var officeLayer = [
{
"zoom": [0, 3],
"places": [
{ "name": "US Offices", "icon": ["us", "flag-shadow"], "posn": [40, -97] },
{ "name": "Canadian Offices", "icon": ["ca", "flag-shadow"], "posn": [58, -101] }
]
},
...
};
function setupOfficeMarkers() {
var mgr = new MarkerManager(map);
for (var i in officeLayer) {
var layer = officeLayer[i];
var markers = [];
for (var j in layer["places"]) {
var place = layer["places"][j];
var icon = getIcon(place["icon"]);
var posn = new GLatLng(place["posn"][0], place["posn"][1]);
markers.push(new GMarker(posn, { title: place["name"], icon: icon }));
}
mgr.addMarkers(markers, layer["zoom"][0], layer["zoom"][1]);
}
mgr.refresh();
}
Просмотреть пример (google_northamerica_offices.html)
Дополнительные сведения можно найти в справочных материалах по программе "Диспетчер маркеров –·программа с открытым исходным кодом".
Объекты GPolyline создают линейные наложения на карте. Объект GPolyline состоит из последовательности точек и создает серию фрагментов линии, упорядоченно соединяющих эти точки.
Ломаные линии создаются на карте в виде последовательности прямых фрагментов. Для линии можно задать пользовательские цвета, плотность и непрозрачность. Цвета необходимо указывать в шестнадцатеричном цифровом HTML-стиле, например #ff0000, а не red. Объект GPolyline не поддерживает названий цветов.
В объектах GPolyline используются доступные возможности векторной графики браузера. В Internet Explorer, Карты Google используют для создания ломаных линий язык VML (см. XHTML и VML), в других браузерах – SVG (если доступен). В остальных случаях изображение линии запрашивается с серверов Google, накладывается на карту и обновляется по мере масштабирования и перетаскивания карты.
В следующем фрагменте кода создается красная ломаная линия шириной 10 пикселей между двумя точками:
var polyline = new GPolyline([ new GLatLng(37.4419, -122.1419), new GLatLng(37.4519, -122.1519) ], "#ff0000", 10); map.addOverlay(polyline);
Просмотреть пример (polyline-simple.html)
Ломаные линии, представленные на карте – это прямые линии, соответствующие текущей проекции. То есть на карте они кажутся прямыми, но фактически они не полностью соответствуют кривизне Земли. Если вместо этого необходимо провести геодезическую ломаную линию (сегмент "большого круга", соответствующий кратчайшему расстоянию между двумя точками поверхности Земли), то необходимо передать geodesic:true в аргументе GPolylineOptions объекта GPolyline.
Объект GPolylineOptions –·это пример литерала объекта. Литералы не служат для создания объекта. Они используются для передачи аргументов в виде последовательных пар (имя, значение) в фигурных скобках. Литералы объекта обычно используются в тех случаях, когда создание экземпляров объекта не требуется.
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(45.828799,-105.292969), 2);
// Create GPolylineOptions argument as an object literal.
// Note that we don't use a constructor.
var polyOptions = {geodesic:true};
var polyline = new GPolyline([
new GLatLng(40.65642, -73.7883),
new GLatLng(61.1699849, -149.944496)
], "#ff0000", 10, 1, polyOptions);
map.addOverlay(polyline);
Просмотреть пример (polyline-geodesic.html)
Объект GPolyline на карте Google задает линию как ряд точек — такую линию легко использовать, но она не обязательно компактна. Для работы с длинными сложными линиями нужно большое количество памяти, и их вывод часто занимает много времени. Кроме того, при высоких уровнях масштабирования отдельные фрагменты незакодированной ломаной линии выводятся на карту независимо от заданного разрешения.
Интерфейс API Карт Google позволяет представлять маршруты в виде закодированных ломаных линий. В этом случае задается ряд точек внутри объекта GPolyline в сжатом формате символов ASCII. Закодированные ломаные линии позволяют также задавать группы коэффициентов масштабирования, которые пропускаются при выводе фрагментов: это дает возможность указывать, насколько детально следует выводить ломаную линию при данном коэффициенте масштабирования. Закодированные ломаные линии труднее создавать, но они позволяют гораздо более эффективно работать с наложениями.
Например, ломаная линия GPolyline из трех точек (двух фрагментов) обычно выводится в следующем виде:
var polyline = new GPolyline([
new GLatLng(37.4419, -122.1419),
new GLatLng(37.4519, -122.1519),
new GLatLng( 37.4619, -122.1819)
], "#FF0000", 10);
map.addOverlay(polyline);
Далее показана закодированная ломаная линия GPolyline для тех же точек (пока будем абстрагироваться от деталей алгоритма кодирования).
var encodedPolyline = new GPolyline.fromEncoded({
color: "#FF0000",
weight: 10,
points: "yzocFzynhVq}@n}@o}@nzD",
levels: "BBB",
zoomFactor: 32,
numLevels: 4
});
map.addOverlay(encodedPolyline);
В этом фрагменте программного кода нужно обратить внимание на два момента.
GPolyline используются обозначения широты и долготы привычного для нас вида. Документация по алгоритму создания этих точек как ряда закодированных символов ASCII содержится здесь. Этот алгоритм нужен, например, если понадобится динамически вычислять закодированные ломаные линии с помощью сервера. Однако, если нужно просто преобразовать существующие точки данных широт и долгот, можно воспользоваться нашей интерактивной программой.
GPolyline. Она особенно удобна для ускорения вывода при высоком коэффициенте масштабирования, где отдельные мелкие фрагменты могут быть не нужны. Например, при отображении в масштабе штата закодированная ломаная линия маршрута поездки из Нью-Йорка в Чикаго не должна обрабатывать фрагменты, представляющие отдельные улицы Манхэттена.
Просмотреть пример (polyline-encoding.html)
Программа для работы с закодированными ломаными линиями
Дополнительные сведения об алгоритме кодировки ломаных линий см. в разделе Алгоритм для ломаных линий.
Объекты GPolygon сходны с объектами GPolyline тем, что они состоят из упорядоченной последовательности точек. Однако они не разомкнуты и служат для определения областей в замкнутом контуре. Как и в случае с ломаными линиями, для границ многоугольника можно задавать пользовательские цвета, толщину и непрозрачность линий, а для области заполнения внутри определенных границ – пользовательские цвета и непрозрачность. Цвета должны быть в шестнадцатеричном цифровом HTML-формате.
В объектах GPolygon, как и в объектах GPolyline, используются доступные возможности векторной графики браузера.
Следующий фрагмент кода создает красный четырехугольник с линией шириной 10 пикселей. Обратите внимание, что многоугольник замкнут — последний фрагмент доходит до начальной точки. Многоугольники всегда следует замыкать – в противном случае их поведение не определено.
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.addControl(new GSmallMapControl());
GEvent.addListener(map, 'click', function(overlay, latlng) {
var lat = latlng.lat();
var lon = latlng.lng();
var latOffset = 0.01;
var lonOffset = 0.01;
var polygon = new GPolygon([
new GLatLng(lat, lon - lonOffset),
new GLatLng(lat + latOffset, lon),
new GLatLng(lat, lon + lonOffset),
new GLatLng(lat - latOffset, lon),
new GLatLng(lat, lon - lonOffset)
], "#f33f00", 5, 1, "#ff0000", 0.2);
map.addOverlay(polygon);
});
Просмотреть пример (polygon-simple.html)
Многоугольники –·это удобные наложения для представления областей произвольных размеров, но они не могут использоваться для изображений. Для размещения на карте изображения служат объекты GGroundOverlay. В качестве параметров конструктора для объекта
GGroundOverlay используются URL-адрес и объект GLatLngBounds изображения.
В следующем примере на обычную карту Ньюарка, штат Нью-Джерси, накладывается старая карта этого города:
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(40.740, -74.18), 12);
// ground overlay
var boundaries = new GLatLngBounds(new GLatLng(40.716216,-74.213393), new GLatLng(40.765641,-74.139235));
var oldmap = new GGroundOverlay("http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg", boundaries);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.addOverlay(oldmap);
Просмотреть пример (groundoverlay-simple.html)
Карты, с которыми работает API Карт Google, состоят из набора фрагментов для каждого коэффициента масштабирования, покрывающих всю земную поверхность. Имеются фрагменты для всех типов используемых карт: G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP и G_PHYSICAL_MAP.
Для некоторых областей и некоторых уровней масштабирования фрагментов не существует. Различные области карты могут содержать фрагменты с различающимися разрешениями и, следовательно, различающимися уровнями масштабирования. Вследствие этого, полнота охвата фрагментов любого типа карты зависит от их положения на глобусе. Например, многие области Тихого океана не отображаются при высоких уровнях масштабирования, тогда как спутниковые снимки Манхэттена могут быть очень подробны.
При минимальном коэффициенте масштабирования (уровень 0) один фрагмент представляет всю земную поверхность:
При переходе к каждому последующему коэффициенту масштабирования карта делится на 4N фрагментов, где N – коэффициент масштабирования. Например, при коэффициенте масштабирования 1 приложение Карт Google делит мир на сетку 2x2, итого 4 фрагмента; при коэффициенте масштабирования 2 приложение Карт Google делит мир на сетку 4x4, итого 16 фрагментов, и т. д.
Для спутниковых карт (типы карт G_SATELLITE_MAP и G_HYBRID_MAP) максимальный коэффициент масштабирования, при котором доступны спутниковые снимки для определенной области, можно определить используя метод GMapType.getMaxZoomAtLatLng().
Нижеследующий пример фиксирует нажатия, сделанные пользователем и определяет наивысший коэффициент масштабирования при котором для места нажатия доступны спутниковые снимки. Отметьте, что для определения максимального коэффициента масштабирования не нужно просматривать спутниковую карту.
var map;
function initialize() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(55.366625,-131.660156), 7);
map.setMapType(G_SATELLITE_MAP);
map.setUIToDefault();
GEvent.addListener(map, 'click', function(overlay, latlng) {
showMaxZoom(latlng);
});
}
}
function showMaxZoom(latlng) {
G_SATELLITE_MAP.getMaxZoomAtLatLng(latlng, function(response) {
if (response && response['status'] == G_GEO_SUCCESS) {
alert("The maximum zoom level where satellite imagery is available at this location is: " + response['zoom']);
}
});
}
Просмотреть пример (map-maxzoom.html)
Если нужно изменить способ вывода фрагментов карты, то есть две возможности:
GTileLayerOverlay.GMapType.Первый способ гораздо проще, но имеет меньшую область применения. Второй способ дает большую степень контроля над способами вывода изображений в приложении. Оба способа обсуждаются далее, однако следует отметить, что процесс создания пользовательского типа карты в данной документации описан не полностью.
В обоих случаях нужно реализовать три абстрактных метода из интерфейса GTileOverlay:
getTileUrl() возвращает карте URL-адрес, по которому располагается изображение фрагмента; в качестве параметров он принимает объект GPoint и коэффициент масштабирования.isPng() возвращает карте значение типа Boolean, которое указывает, является ли образ PNG-файлом (который можно выводить в режиме прозрачности). Если значение равно true, изображение имеет формат PNG.getOpacity() возвращает число в диапазоне от 0.0 до 1.0, задающее коэффициент прозрачности для данного изображения.Различные подходы будут описаны в следующих двух разделах.
Для вывода наложений на карте существующего типа используется объект GTileLayerOverlay. Он требует создания объекта GCopyrightCollection и прикрепления его к слою фрагментов, чтобы задать разрешение на использование изображений.
В следующем отрывке программного кода простое прозрачное наложение выводится в каждом фрагменте во всех масштабах, определяя очертания фрагментов в плавающем перекрестии курсора.
// Set up the copyright information
// Each image used should indicate its copyright permissions
var myCopyright = new GCopyrightCollection("© ");
myCopyright.addCopyright(new GCopyright('Demo',
new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)),
0,'©2007 Google'));
// Create the tile layer overlay and
// implement the three abstract methods
var tilelayer = new GTileLayer(myCopyright);
tilelayer.getTileUrl = function() { return "../include/tile_crosshairs.png"; };
tilelayer.isPng = function() { return true;};
tilelayer.getOpacity = function() { return 1.0; }
var myTileLayer = new GTileLayerOverlay(tilelayer);
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.addOverlay(myTileLayer);
Просмотреть пример (tileoverlay-simple.html)
Примечание. Это раздел повышенной сложности.
Если возможности класса GTileLayerOverlay кажутся слишком узкими, можно создать собственный тип карты и разработать для него совершенно новую систему вывода изображений. Для этого нужно создать объект GMapType и добавить его к карте с помощью метода GMap2.addMapType().
Создание типа карты с нуля – трудоемкий процесс. Нужно разработать способ определения и получения динамических данных для вывода на карту в зависимости от текущих координат; следует также решить, как ссылаться на изображения фрагментов карт и как выводить их на экран. Разработчик должен решить эти задачи самостоятельно; однако описание способа, которым приложение Карт Google ссылается на фрагменты карты, может оказаться полезным.
API Карт Google использует три системы координат:
Далее приводится описание всех трех систем.
Каждый фрагмент, с которым работает приложение Карт Google, содержит 256x256 пикселей. Таким образом, положение точки в фрагменте можно задать с помощью такой пары объекта GPoint, как x,y. Начало координат (0,0) каждого фрагмента располагается в северо-западном углу. Следовательно, начало координат единого фрагмента, представляющего собой всю Землю, располагается на Северном полюсе, на долготе –180 градусов (долготе Аляски). Значения долготы x увеличиваются к востоку, а широты y – к югу, и точка в юго-восточном углу будет иметь координаты (255,255).
При более высоких уровнях масштабирования количество пикселей растет, удваиваясь по обоим направлениям (x и y). Например, при коэффициенте масштабирования 1 карта состоит из четырех фрагментов размером 256x256 пикселей, образуя пространство пикселей 512x512. При коэффициенте масштабирования 19 каждый пиксель x и y на карте можно задать числом в диапазоне от 0 до 256 * 2 19.
Пользоваться координатами точки, уникальными в пределах всей карты, часто нерационально. При более высоких уровнях масштабирования, API Карт Google не может использовать один файл изображения для работы со всей земной поверхностью. Поэтому удобнее определить, какой фрагмент карты сейчас используется, а потом пользоваться пиксельными координатами, задаваемыми относительно начала координат данного фрагмента. Любая карта, реализуемая разработчиком, должна проводить те же вычисления.
Фрагменты в приложении Карт Google нумеруются по тому же принципу, что и пиксели: начальный фрагмент всегда находится в северо-западном углу карты. Фрагменты индексируются с помощью координат x,y начиная от указанного фрагмента. Например, при коэффициенте масштабирования 2, при котором земная поверхность делится на 16 фрагментов, каждый фрагмент можно задать уникальной парой x,y:
Следовательно, однозначно задать конкретную точку для определенного коэффициента масштабирования можно с помощью двух значений GPoint: одно задает используемый фрагмент, а второе — координаты пикселя в фрагменте размером 256x256 пикселей.
Реализация фрагментного наложения для любого масштаба, кроме нескольких самых простых, может оказаться сложной задачей. Необходимо реализовать логику программы, которая будет определять, какой фрагмент карты нужен в данный момент. API Карт Google позволяет создать объект GTileLayer, передавая ему аргумент GTileLayerOptions в виде литерала объекта. Аргумент GTileLayerOptions содержит свойство tileUrlTemplate, сопоставляющее запросы на фрагменты карты с URL-адресами на основании координат фрагмента. Конструктор для наложения будет выглядеть примерно так:
var tileLayerOverlay = new GTileLayerOverlay(
new GTileLayer(null, null, null, {
tileUrlTemplate: 'http://domain.com/myimage_{Z}_{X}_{Y}.png',
isPng:true,
opacity:1.0
})
);
map.addOverlay(tlo);
Эта схема шаблона позволяет индексировать коллекцию фрагментов карт с помощью координат фрагментов, как это делается в Картах Google.
Изображения, из которых создаются карты, обычно приобретаются, создаются или берутся в пользование по лицензии у стороннего поставщика. Часто возникает необходимость воспроизведения изображений, защищенных авторским правом, и в определенных случаях (например, при работе со спутниковыми данными) изображения могут приходить из различных источников в различных местах земного шара. Чтобы в созданных пользователями типах карт можно было динамически выводить информацию об авторских правах, API Карт содержит ряд объектов, хранящих информацию об авторском праве. Эти объекты предоставляют методы и интерфейсы, реализующие получение информации об авторских правах на основе текущих окна просмотра и коэффициента масштабирования.
Объект GCopyright представляет собой простой объект, хранящий основную информацию об авторских правах. Свойства minZoom и bounds этого объекта задают ограничения, при которых действует данная информация об авторских правах, а строка text содержит информацию об авторских правах и выводится при наступлении указанных выше условий.
Наборы объектов GCopyright составляют коллекции GCopyrightCollection. Конструктор GCopyrightCollection позволяет задать текстовый префикс (например, "Imagery © 2007"), который присоединяется ко всем предупреждениям об авторских правах. Следует заметить, что нельзя добавить информацию об авторских правах в коллекцию GCopyrightCollection прямо в конструкторе. Нужно сначала создать коллекцию, а затем вызывать метод addCopyright, добавляя объекты GCopyright по отдельности.
Интерфейс GTileLayer требует, для своего конструктора, аргумент copyrights. Классы, работающие с этими слоями фрагментов (например GTileLayerOverlay и GMapType), должны сначала создать объект GCopyrightCollection, а затем передать его конструктору слоя фрагментов.
Ниже перечислены методы, применяемые в интерфейсе API Карт Google для вывода информации об авторских правах. Эти методы можно переопределить для задания другой функциональности.
GMapType.getCopyrights() вызывает метод GTileLayer.getCopyright() для всех своих дочерних слоев карты.GTileLayer.getCopyright() вызывает метод GCopyrightCollection.getCopyrightNotice() своей коллекции объектов, хранящей информацию об авторских правах.GCopyrightCollection.getCopyrightNotice() возвращается сообщение или сообщения об авторских правах данного объекта; метод также проверяет, выполняются ли заданные требования bounds и zoom к каждому из дочерних объектов GCopyright.Все эти методы имеют параметры bounds и zoom, которые можно переопределить и проверить, чтобы узнать, какую информацию об авторских правах нужно отображать.
По умолчанию API Карт Google при выводе слоя в определенном типе карты каждый раз запрашивает текущую информацию об авторских правах с помощью метода GTileLayer.getCopyright(). Некоторые типы карт содержат несколько слоев фрагментов, а это значит, что может возникнуть необходимость одновременно выводить информацию о нескольких объектах GCopyrightCollection. (Например, тип карты G_HYBRID_MAP реализует одновременно спутниковый слой и слой карты.) В этом случае предупреждения об авторских правах из разных коллекций сцепляются между собой и выводятся вместе.
Земля – шар, а карта – плоский двумерный объект. Карта, выводимая с помощью интерфейса API Карт Google, представляет собой проекцию сферы земной поверхности на плоскость. Проекции, с которыми работает интерфейс API Карт Google, реализуются с помощью интерфейса GProjection. В настоящее время, в API Карт Google реализована только одна проекция: GMercatorProjection. Проще всего определить проекцию как взаимно-однозначное соответствие значений GLatLng координатам на карте. Интерфейс GProjection предоставляет нужные для этого программы преобразования.
Метод GProjection.fromLatLngToPixel() преобразует значение GLatLngGLatLng в пиксельные координаты для заданного коэффициента масштабирования. Аналогичным образом метод GProjection.fromPixelToLatLng() GProjection.fromPixelToLatLng() преобразует пиксельные координаты для заданного коэффициента масштабирования в значение GLatLng. Эти методы удобны для реализации типа карты, так как позволяют решить, какие фрагменты карты нужно выводить, как их выводить и с каким смещением.
В следующем примере обрабатывается событие нажатия – вычисляются пиксельные координаты для текущего коэффициента масштабирования; возвращаются пиксельные координаты и координаты фрагмента данного местоположения:
Просмотреть пример (tile-detector.html)
Дополнительные сведения о реализации типов карт см. в справочных материалах по классу GMapType.
Объекты GLayer – это объекты наложений, хранящие географическую информацию сторонних разработчиков. Слои – это наборы географически связанных компонентов, объединенных некоей общей функцией и отображаемых на карте как группа. Google включает в эти наборы данные, полученные от других источников и сводит их вместе в едином слое.
Слои обычно состоят из широкого набора элементов, таких как маркеры, ломаные линии и прямоугольники, которые однако, не считаются отдельными объектами. Слой (и все его компоненты) считаются в API Карт единственным наложением, которое добавляется к карте с помощью стандартного метода addOverlay(). Слой также может быть интерактивным и допускать выполнение действий над его компонентами с целью, например, отображения информационных окон.
Каждый слой содержит уникальный идентификатор пространства имен, что позволяет без проблем ссылаться на него и обращаться к нему. Этот идентификатор имен, в настоящий момент, основывается на домене исходного слоя. Например, идентификатор пространства имен англоязычного слоя Geotagged Wikipedia © Articles –·"org.wikipedia.en".
В настоящий момент у API Google имеется доступ к следующим общедоступным слоям. К API Карт будут периодически добавляться новые слои. Мы будет поддерживать их список в следующей таблице.
Приведенный ниже фрагмент кода добавляет слой англоязычной Википедии к Гринвич-Виллидж, Нью-Йорк:
function initialize() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(40.730885,-73.997383), 15);
var myLayer = new GLayer("org.wikipedia.en");
map.addOverlay(myLayer);
}
}
Просмотреть пример (layer-simple.html)
API Карт Google позволяет также создавать пользовательские наложения посредством применения интерфейса GOverlay. API Карт Google предоставляет ряд служб –·например, объекты GTrafficOverlay, GGeoXml и GStreetviewPanorama – путем применения интерфейса GOverlay. (Документацию на эти службы см. в разделе Службы section.)
Интерфейс GOverlay требует применения четырех абстрактных методов:
initialize() вызывается в ответ на вызов GMap2.addOverlay();remove() вызывается в ответ на вызов GMap2.removeOverlay();copy() вызывается, чтобы разрешить работу с новым наложением по шаблону.redraw() вызывается в ответ на изменение изображения, выведенного на карте.Интерфейсы API Карт Google реализуются в языке JavaScript назначением свойства prototype экземпляру наследуемого объекта. Например, объект Rectangle наследует интерфейс GOverlay с помощью следующего кода:
OverlaySubclass.prototype = new GOverlay();
Реализация абстрактных методов интерфейса GOverlayGOverlay упрощается назначением этих методов prototype объекта:
OverlaySubclass.prototype.initialize = myInitializeMethod; OverlaySubclass.prototype.remove = myRemoveMethod; OverlaySubclass.prototype.copy = myCopyMethod; OverlaySubclass.prototype.redraw = myRedrawMethod;
В следующем примере создается наложение Rectangle, определяющее географическую область на карте. В классе Rectangle реализованы четыре обязательных метода интерфейса GOverlay. В особенности следует обратить внимание на метод initialize(), создающий элементы DOM, представляющие данное наложение, и метод redraw(), который определяет размеры наложения и его расположение на карте на основании действующей проекции и текущего коэффициента масштабирования.
Каждый элемент DOM, составляющий наложение, существует на панели карты, определяющей z-порядок отображения элементов. Например, ломаные линии располагаются на плоскости карты, поэтому они отображаются в самой нижней панели G_MAP_MAP_PANE. Теневые элементы маркеров располагаются в панели G_MAP_MARKER_SHADOW_PANE, а изображения переднего плана маркеров – в панели G_MAP_MARKER_PANE. Элементы наложения нужно правильно соотносить с панелями. Тогда тени маркеров будут изображаться поверх ломаных линий, а информационное окно – поверх всех остальных наложений карты. В данном примере наложение располагается в плоскости карты, поэтому оно добавляется в панель с самым низким z-порядком, G_MAP_MAP_PANE, подобно GPolyline. Полный список панелей карт см. в справочных материалах по классам.
// A Rectangle is a simple overlay that outlines a lat/lng bounds on the
// map. It has a border of the given weight and color and can optionally
// have a semi-transparent background color.
function Rectangle(bounds, opt_weight, opt_color) {
this.bounds_ = bounds;
this.weight_ = opt_weight || 2;
this.color_ = opt_color || "#888888";
}
Rectangle.prototype = new GOverlay();
// Creates the DIV representing this rectangle.
Rectangle.prototype.initialize = function(map) {
// Create the DIV representing our rectangle
var div = document.createElement("div");
div.style.border = this.weight_ + "px solid " + this.color_;
div.style.position = "absolute";
// Our rectangle is flat against the map, so we add our selves to the
// MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
// below the marker shadows)
map.getPane(G_MAP_MAP_PANE).appendChild(div);
this.map_ = map;
this.div_ = div;
}
// Remove the main DIV from the map pane
Rectangle.prototype.remove = function() {
this.div_.parentNode.removeChild(this.div_);
}
// Copy our data to a new Rectangle
Rectangle.prototype.copy = function() {
return new Rectangle(this.bounds_, this.weight_, this.color_,
this.backgroundColor_, this.opacity_);
}
// Redraw the rectangle based on the current projection and zoom level
Rectangle.prototype.redraw = function(force) {
// We only need to redraw if the coordinate system has changed
if (!force) return;
// Calculate the DIV coordinates of two opposite corners of our bounds to
// get the size and position of our rectangle
var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Now position our DIV based on the DIV coordinates of our bounds
this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
this.div_.style.left = (Math.min(c2.x, c1.x) - this.weight_) + "px";
this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";
}
var map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
// Display a rectangle in the center of the map at about a quarter of
// the size of the main map
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var lngDelta = (northEast.lng() - southWest.lng()) / 4;
var latDelta = (northEast.lat() - southWest.lat()) / 4;
var rectBounds = new GLatLngBounds(
new GLatLng(southWest.lat() + latDelta, southWest.lng() + lngDelta),
new GLatLng(northEast.lat() - latDelta, northEast.lng() - lngDelta));
map.addOverlay(new Rectangle(rectBounds));