Google Maps API позволяет встраивать карты от Google в web-приложения при помощи JavaScript. Библиотека Google Maps for GWT предоставляет доступ к JavaScript API из Java кода скомпилированного GWT компилятором.
Рассмотрим использование Google Maps API и библиотеку для GWT. Создадим приложение на GWT, которое будет определять местоположение пользователя, выводить подробную информацию и показывать место на карте с маркером в центре.
Для работы с картами в classpath проекта нужно добавить библиотеку gwt-maps.jar, а также в конфигурационный файл MapGwtApp.gwt.xml дописать следующие строки:
<!-- Include Google Maps API bindings -->
<inherits name='com.google.gwt.maps.Maps' />
<script src="http://maps.google.com/maps/api/js?key=ABQIAAAAxp9dobcDAi8qyMyXsLdS6hT2yXp_ZAY8_ufC3CFXhHIE1NvwkxRiFg5rKqsubGL2ZNYXGXzEg7K5kA&sensor=false" />
* This source code was highlighted with Source Code Highlighter.
Создадим контейнер AnimatedMapWidget для карты, который позволит ей появляться/скрываться плавно с анимацией.
/**
* @author Dmitry Nikolaenko
*/
public class AnimatedMapWidget extends FlowPanel {
/**
* how long will take the panel to animate
*/
private final int ANIMATION_DURATION = 500;
public AnimatedMapWidget() {
super();
initWidgetStyle();
show(false);
this.setSize("300px", "250px");
}
private void initWidgetStyle() {
this.getElement().getStyle().setPosition(Position.ABSOLUTE);
this.getElement().getStyle().setBottom(0, Unit.PX);
this.getElement().getStyle().setZIndex(-1);
this.getElement().getStyle().setRight(0, Unit.PX);
}
@Override
public void setVisible(final boolean visible) {
AnimationEffect animationEffect = new AnimationEffect(visible);
animationEffect.run(ANIMATION_DURATION);
if (visible) {
show(visible);
} else {
new Timer() {
@Override
public void run() {
show(visible);
}
}.schedule(ANIMATION_DURATION);
}
}
/**
* hide or show main panel without animation
*/
public void show(boolean show) {
super.setVisible(show);
}
/**
* animation which will change property of the panel depending on the show value
*/
private class AnimationEffect extends Animation {
private boolean show = true;
AnimationEffect(boolean show) {
super();
this.show = show;
}
@Override
protected void onUpdate(double progress) {
double rightValue = progress;
if (!show) {
rightValue = 1.0 - progress;
}
AnimatedMapWidget.this.getElement().getStyle().setRight(-AnimatedMapWidget.this.getOffsetWidth() * rightValue, Unit.PX);
}
}
}
* This source code was highlighted with Source Code Highlighter.
Давайте опишем с помощью enum GoogleMapZoomType тип увеличения для карты:
/**
* @author Dmitry Nikolaenko
*/
public enum GoogleMapZoomType {
COUNTRY_ZOOM(5),
REGION_ZOOM(9),
TOWN_ZOOM(13),
ADDRESS_ZOOM(17);
private int zoom;
private GoogleMapZoomType(int zoom) {
this.zoom = zoom;
}
public int getZoomLevel() {
return zoom;
}
}
* This source code was highlighted with Source Code Highlighter.
Инициализация карты и ее свойств происходит в методах initGoogleMapsWidget() и getGoogleMapsWidget(). Для отображения локации по текущим географическим координатам и установки маркера на карте используются методы displayLocationOnMap() и displayLocationMarker().
/**
* display the current location on the map
* @param geoCoord the geographical coordinates, latitude and longitude
* @param zoomType the zoom level for the map
* @param addressLocation the new address location
*/
private void displayLocationOnMap(HasLatLng geoCoord, GoogleMapZoomType zoomType, String addressLocation) {
geoRequest.setLatLng(geoCoord);
geoRequest.setAddress(addressLocation);
displayLocationMarker(geoRequest, zoomType);
}
* This source code was highlighted with Source Code Highlighter.
/**
* show the marker on the map
*/
public static void displayLocationMarker(final GeocoderRequest request, final GoogleMapZoomType zoomType) {
new Geocoder().geocode(request, new GeocoderCallback() {
@Override
public void callback(List<HasGeocoderResult> responses, String status) {
if (status.equalsIgnoreCase("ok")) {
final HasGeocoderResult geoResult = responses.get(0);
final HasLatLng geoLatLng = geoResult.getGeometry().getLocation();
StringBuilder sb = new StringBuilder();
for (HasAddressComponent component : geoResult.getAddressComponents()) {
sb.append(component.getLongName()).append(", ");
}
addressLocationInfo.setText(sb.toString());
mapMarker.setPosition(geoLatLng);
mapMarker.setDraggable(true);
mapMarker.setMap(mapWidget.getMap());
mapWidget.getMap().setZoom(zoomType.getZoomLevel());
mapWidget.getMap().panTo(geoLatLng);
mapMarker.setMap(mapWidget.getMap());
} else {
GWT.log("Geocoder failed with response : " + status);
}
}
});
}
* This source code was highlighted with Source Code Highlighter.
С помощью JSNI в методе detectCurrentLocation() определяем текущее положение(долготу и ширину).
/**
* JSNI method, try detect current location
*/
private static native void detectCurrentLocation() /*-{
if ($wnd.navigator.geolocation) {
$wnd.navigator.geolocation.getCurrentPosition(function(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
@com.dmitrynikol.map.gwt.client.MapGwtApp::currentLocationDetected(DD)(lat, lon);
}, function() {
// could not find location
});
}
}-*/;
* This source code was highlighted with Source Code Highlighter.
А если у браузера есть поддержка HTML 5, то для нахождения текущих координат можно воспользоваться методом findCurrentLocation().
/**
* another way to find current location
*/
private void findCurrentLocation() {
Geolocation.getIfSupported().getCurrentPosition(new Callback<Position, PositionError>() {
@Override
public void onSuccess(Position result) {
double latitide = result.getCoordinates().getLatitude();
double longitude = result.getCoordinates().getLongitude();
GWT.log(latitide + " / " + longitude);
}
@Override
public void onFailure(PositionError reason) {
GWT.log(reason.getLocalizedMessage());
}
});
}
* This source code was highlighted with Source Code Highlighter.
Метод refreshGoogleMapsWidget() позволяет возбудить resize событие, обновить и отцентрировать карту.
/**
* refresh google maps widget and preserves the center point
*/
public void refreshGoogleMapsWidget() {
if (mapWidget != null) {
HasLatLng center = mapWidget.getMap().getCenter();
Event.trigger(mapWidget.getMap(), "resize");
mapWidget.getMap().setCenter(center);
}
}
* This source code was highlighted with Source Code Highlighter.
Полный код класса MapGwtApp, где и будет стартовать приложение:
/**
* @author Dmitry Nikolaenko
*/
public class MapGwtApp implements EntryPoint {
private FlowPanel mainPanel;
private AnimatedMapWidget animatedMapWidget;
private Button show;
private static Label addressLocationInfo;
private static MapWidget mapWidget;
private MapOptions options;
private static GeocoderRequest geoRequest;
private static Marker mapMarker;
private boolean showMap = false;
@Override
public void onModuleLoad() {
mainPanel = new FlowPanel();
animatedMapWidget = new AnimatedMapWidget();
show = new Button("show map");
addressLocationInfo = new Label();
show.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
showMap = !showMap;
show.setText(showMap ? "hide map" : "show map");
animatedMapWidget.setVisible(showMap);
if (showMap) {
refreshGoogleMapsWidget();
}
}
});
mainPanel.setStyleName("mainPanelStyle");
mainPanel.add(show);
mainPanel.add(addressLocationInfo);
mainPanel.add(animatedMapWidget);
RootPanel.get().add(mainPanel);
initGoogleMapsWidget();
detectCurrentLocation();
}
private void initGoogleMapsWidget() {
geoRequest = new GeocoderRequest();
mapMarker = new Marker();
options = new MapOptions();
getGoogleMapsWidget();
displayLocationOnMap(options.getCenter(), GoogleMapZoomType.REGION_ZOOM, "");
animatedMapWidget.add(mapWidget);
}
/**
* create map widget that presents a viewable Google Map to a user
*/
public void getGoogleMapsWidget() {
options.setCenter(new LatLng(39.509, -98.434));
options.setDraggable(true);
options.setNavigationControl(true);
options.setMapTypeId(new MapTypeId().getRoadmap());
options.setMapTypeControl(true);
options.setScrollwheel(true);
mapWidget = new MapWidget(options);
mapWidget.setSize("100%", "100%");
}
/**
* refresh google maps widget and preserves the center point
*/
public void refreshGoogleMapsWidget() {
if (mapWidget != null) {
HasLatLng center = mapWidget.getMap().getCenter();
Event.trigger(mapWidget.getMap(), "resize");
mapWidget.getMap().setCenter(center);
}
}
/**
* display the current location on the map
* @param geoCoord the geographical coordinates, latitude and longitude
* @param zoomType the zoom level for the map
* @param addressLocation the new address location
*/
private void displayLocationOnMap(HasLatLng geoCoord, GoogleMapZoomType zoomType, String addressLocation) {
geoRequest.setLatLng(geoCoord);
geoRequest.setAddress(addressLocation);
displayLocationMarker(geoRequest, zoomType);
}
/**
* another way to find current location
*/
private void findCurrentLocation() {
Geolocation.getIfSupported().getCurrentPosition(new Callback<Position, PositionError>() {
@Override
public void onSuccess(Position result) {
double latitide = result.getCoordinates().getLatitude();
double longitude = result.getCoordinates().getLongitude();
GWT.log(latitide + " / " + longitude);
}
@Override
public void onFailure(PositionError reason) {
GWT.log(reason.getLocalizedMessage());
}
});
}
/**
* JSNI method, try detect current location
*/
private static native void detectCurrentLocation() /*-{
if ($wnd.navigator.geolocation) {
$wnd.navigator.geolocation.getCurrentPosition(function(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
@com.dmitrynikol.map.gwt.client.MapGwtApp::currentLocationDetected(DD)(lat, lon);
}, function() {
// could not find location
});
}
}-*/;
public static void currentLocationDetected(double latitude, double longitude) {
geoRequest.setLatLng(new LatLng(latitude, longitude));
displayLocationMarker(geoRequest, GoogleMapZoomType.REGION_ZOOM);
}
/**
* show the marker on the map
*/
public static void displayLocationMarker(final GeocoderRequest request, final GoogleMapZoomType zoomType) {
new Geocoder().geocode(request, new GeocoderCallback() {
@Override
public void callback(List<HasGeocoderResult> responses, String status) {
if (status.equalsIgnoreCase("ok")) {
final HasGeocoderResult geoResult = responses.get(0);
final HasLatLng geoLatLng = geoResult.getGeometry().getLocation();
StringBuilder sb = new StringBuilder();
for (HasAddressComponent component : geoResult.getAddressComponents()) {
sb.append(component.getLongName()).append(", ");
}
addressLocationInfo.setText(sb.toString());
mapMarker.setPosition(geoLatLng);
mapMarker.setDraggable(true);
mapMarker.setMap(mapWidget.getMap());
mapWidget.getMap().setZoom(zoomType.getZoomLevel());
mapWidget.getMap().panTo(geoLatLng);
mapMarker.setMap(mapWidget.getMap());
} else {
GWT.log("Geocoder failed with response : " + status);
}
}
});
}
}
* This source code was highlighted with Source Code Highlighter.
Вот так выглядит запущенное приложение:
Комментариев нет:
Отправить комментарий