Как плавно приближать в гугл картах
Перейти к содержимому

Как плавно приближать в гугл картах

  • автор:

Как сделать плавное зумирование в Yandex/Google картах?

Хочу сделать чтобы при заходе на страницу карта плавно сменила масштаб с страны до улицы. Помогите, как это сделать?

  • Вопрос задан более трёх лет назад
  • 1118 просмотров

Комментировать

Решения вопроса 0

Ответы на вопрос 1

rizhenkov

Веб-программист

Я не очень большой специалист в картах, но работал с ними.
Так вот, масштаб там меняется шагами. Из-за чего масштабирование бывает только «дёрганое».
Это связано с тем, что карты передаются в браузер в виде небольших квадратиков и для каждого масштаба карты — квадратики свои. Невозможно плавно так сделать (ну или почти невозможно).

Ответ написан более трёх лет назад

Комментировать

Нравится Комментировать

Google Maps: перемещение карты и маркеров

В одном из предыдущих сообщений я писал про то, как вывести карту с помощью Google Maps API и поставить на ней маркер. Тема, как выяснилось, весьма востребованная, и я решил начать по ней серию публикаций, где буду рассказывать о том, как сделать различые действия с Google Maps. Итак, сегодня речь пойдет о перемещении самой карты и маркеров на ней при наступлении каких-либо внешних событий.

MyMap = function () < 
self = this; // потребуется для ссылки на экземпляр MyMap во вложенных функциях
this.map = new google.maps.Map(document.getElementById("map_canvas"), < zoom: 10, center: , // можно не создавать объект LatLng явно, а использовать литерал такого вида mapTypeId: google.maps.MapTypeId.ROADMAP >);
this.markers = new Array;
this.markers[0] = new google.maps.Marker( < position: new google.maps.LatLng(55.763525,37.560893), // опять обходимся без дополнительной переменной
map: this.map, title: 'Пробная точка!' >); // сюда будет добавляться новый код
>;
myMap = new MyMap;
google.maps.event.addDomListener(window, 'load', myMap);

Здесь мы создали объект myMap, внутри которого хранится экземпляр карты, с которой мы работаем и массив маркеров на карте (пока с одним элементом). Кроме того, для того, чтобы повесить код отображения на событие onload, мы воспользовались методом google.maps.event.addDomListener, что является более правильным решением, чем использование window.onload, так как позволяет избежать переопределения обработчика, если он был задан где-то еще.

Шаг 1. Узнаем коордианты нужных объектов

Поскольку все объекты на карте привязаны к географическим коордианам, нам нужно сначала научится узнавать координаты интересущего нас места. Сделать это можно двумя способами: зайти на основной сайт Google Maps, найти там нужный объект, щелкнуть по нему правой кнопкой мыши и выбрать «Что это». Появится краткая информация об объекте, включая два числа в самой нижней строке. Это и будут его координаты.

Второй вариант — чуть более сложный, но он позволяет получить координаты не только точки, но и протяженных объектов в виде JSON. Для этого нужно выполнить запрос по адресу http://maps.googleapis.com/maps/api/geocode/json?address=название_объекта&sensor=false&language=ru, где вместо название_объекта подставляем требуемое название, например, http://maps.googleapis.com/maps/api/geocode/json?address=Нижний+Новогород&sensor=false&language=ru В полученном JSON можно использовать либо location (координаты центра), либо bounds (объект Rectangle с координатами границ протяженного объекта), либо viewport (координаты области просмотра для отображения объекта).

Шаг 2. Перемещение видимой области карты

Для перемещения видимой области в Google Maps API у объекта Map есть несколько методов: panTo, panToBounds и panBy, fitBounds, setCenter. Метод panTo плавно перемещает центр карты на указанные географические коордианты (объект LatLng), setCenter делает то же самое без анимации, panToBounds — смещает карту так, чтобы уместить в ней объект с заданными границами, fitBounds делает то же самое, но при необходимости еще меняет zoom (что полезно для больших объектов), и panBy — смещает карту на указанное количество пикселей.

 




this.MoveMapTo = function(lat,lng) < 
return function(e) <
self.map.panTo(new google.maps.LatLng(lat,lng));
>
>
google.maps.event.addDomListener(document.getElementById('moscow'), 'click', this.moveMapTo(55.763525,37.560893));
google.maps.event.addDomListener(document.getElementById('peterburg'), 'click', this.moveMapTo(59.939956, 30.344911));
google.maps.event.addDomListener(document.getElementById('n_novgorod'), 'click', this.moveMapTo(56.325418, 43.935667));

Поскольку в обработчик события onclick нельзя передавать параметры, мы применили возможность JavaScript под названием замыкание (closure). Работает оно следующим образом: возвращает анонимную функцию, где в качестве некоторых переменных используются переменные вышестоящей функции (в данном случае это параметры lat и lng), которые в момент создания «запоминаются». Вместо замыкания можно было написать три обычных функции, которые делали бы panTo на жестко прописанные в них координаты, и передать их имена вместо вызова this.moveMapTo, но это менее красивое и профессиональное решение.

google.maps.event.addDomListener(document.getElementById('map_left'), 'click', function () < 
self.map.panBy(25,0);
>);
google.maps.event.addDomListener(document.getElementById('map_right'), 'click', function () <
self.map.panBy(-25,0);
>);

Шаг 3. Перемещение маркера

setInterval(function() < 
self.markers[0].setPosition( new google.maps.LatLng(self.markers[0].getPosition().lat()+Math.random()*0.0002-0.0001, self.markers[0].getPosition().lng()+0.0001));
>,100);

Шаг 4. Проверка, что объект находится в области видимости

setInterval(function() < 
if (self.map.getBounds().contains(self.markers[0].getPosition())) <
self.map.panTo(self.markers[0].getPosition());
>
>,5000);

Вот и все на сегодня! Посмотреть полностью работающий пример можно в прикрепленном файле. Пишите в комментариях, какие еще примеры действий с картами вы хотели бы увидеть, возможно, я расскажу о них в следующих выпусках.

Работа с интерфейсом в Google Maps SDK для Android

Данная статья будет полезна тем, кто ранее не использовал в своей работе Google Maps SDK.

Под катом описаны основные приемы работы с картой, такие как добавление и управление маркерами, способы перемещения камеры над картой, управление зумом, построение маршрута и геокодинг. А так же ограничения и способы их обхода.

image

Источник

На написание статьи меня сподвиг собственный опыт, который я извлек при написании приложения для курьеров использующего в своей работе гугл карты. Так что все скриншоты и возможное упоминание бизнес логики будут происходить в контексте построения интерфейса курьера.

К сожалению Google Maps SDK for Android не позволяет изменять положение кнопок управления, т.н. UI controls, к ним относятся: IndoorLevelPicker — показ поэтажного плана строений, Compass — компас, My Location button — перейти на карте к текущему местоположению, Map toolbar — кнопи построения маршрута и открытия карты, а так же ZoomControls — увеличения и уменьшения маштаба карты.

На примере Map toolbar и ZoomControls посмотрим какие сложности могут возникнуть из-за невозможности сменить положение контролов и как это обойти.

image

Проблемы с отображением UI controls из SDK (выделено оранжевым) и их кастомные аналоги (выделено зеленым)

В данном случае у нас в правом нижнем углу расположена кнопка (floating action button) перехода к списку адресов заказов на доставку, на картинке слева видно, что ZoomControls оказались под ней и практически недоступны для нажатия. На картинке справа, при нажатии на маркер, появляются кнопки из Map toolbar, они так же оказались под кнопкой перехода к списку заказов.

Первое что нам необходимо сделать — это скрыть отображение оригинальных кнопок. Сделать это можно переопределив метод onMapReady, он вызывается в тот момент, когда карта готова к использованию.

Не показывать кнопки Zoom контрола и не показывать кнопки построить маршрут из SDK

private GoogleMap mMap; private UiSettings uiSettings; @Override public void onMapReady(GoogleMap googleMap) < mMap = googleMap; uiSettings = mMap.getUiSettings(); //Не показывать кнопки Zoom uiSettings.setZoomControlsEnabled(false); //Не показывать кнопки построить маршрут и открыть карту из SDK uiSettings.setMapToolbarEnabled(false); >

Добавляем в верстку фрагмента нужные кнопки, там где они должны быть в соответствии с нашим дизайном:

image

Расположение кастомных кнопок управления картой

Затем в методе onCreateView указываем действия, которые должны произойти при нажатии на наши кнопки:

Обработчики кнопок увеличения и уменьшения маштаба, а так же построения маршрута

private ImageButton imageButtonZoomIn; private ImageButton imageButtonZoomOut; private ImageButton imageButtonRoute; private GoogleMap mMap; @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) < //Увеличить карту imageButtonZoomIn = view.findViewById(R.id.imageButtonZoomIn); imageButtonZoomIn.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < mMap.animateCamera(CameraUpdateFactory.zoomIn()); >>); //Уменьшить карту imageButtonZoomOut = view.findViewById(R.id.imageButtonZoomOut); imageButtonZoomOut.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < mMap.animateCamera(CameraUpdateFactory.zoomOut()); >>); //Открыть гугл карту и построить маршрут imageButtonRoute = view.findViewById(R.id.imageButtonRoute); imageButtonRoute.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < String latitude = String.valueOf(activMarker.getPosition().latitude); String longitude = String.valueOf(activMarker.getPosition().longitude); Uri gmmIntentUri = Uri.parse("google.navigation:q=" + latitude + "," + longitude); Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); mapIntent.setPackage("com.google.android.apps.maps"); try< if (mapIntent.resolveActivity(Objects.requireNonNull(getActivity()).getPackageManager()) != null) < startActivity(mapIntent); >>catch (NullPointerException e) < Log.e(TAG, "onClick: NullPointerException: Couldn't open map." + e.getMessage() ); Toast.makeText(getActivity(), "Couldn't open map", Toast.LENGTH_SHORT).show(); >> >); > 

Особенность метода animateCamera в том, что маштаб изменяется плавно, а не мгновенно и если нужно, например, отключить анимацию конкретной кнопки зума, по достижению максимального или минимального маштаба, то для этого нужно переопределить метод onCameraIdle, который вызывается в момент прекращения изменения маштаба карты.

Активация и деактивация кнопок зума

 @Override public void onCameraIdle() < if (mMap.getCameraPosition().zoom == mMap.getMinZoomLevel())< //при минимальном зуме, делаем неактивной кнопку минус imageButtonZoomOut.setEnabled(false); imageButtonZoomIn.setEnabled(true); >else if (mMap.getCameraPosition().zoom == mMap.getMaxZoomLevel())< //при максимальном зуме, делаем неактивной кнопку плюс imageButtonZoomOut.setEnabled(true); imageButtonZoomIn.setEnabled(false); >else < //во всех остальных случаях обе кнопки активны imageButtonZoomOut.setEnabled(true); imageButtonZoomIn.setEnabled(true); >> 

Что бы выполнить какое либо действие с маркером(кроме перетаскивания), например, создать новый заказ, удалить случайно поставленный маркер, перейти в уже существующий заказ или позвонить по телефону казанному в заказе добавляем в верстку соответствующие кнопки управления и прописываем их обработчики.

image

Кнопки управления маркером

Обработка нажатия на карту для добавления маркера и отображения кастомных кнопок управления

private GoogleMap mMap; private ImageButton imageButtonRoute; @Override public void onMapReady(GoogleMap googleMap) < mMap = googleMap; mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() < @Override public void onMapClick(LatLng latLng) < imageButtonRoute.setVisibility(View.GONE); if (myMarker !=null)< //Удаляем старый маркер myMarker.remove(); >//Добавляем маркер на карту myMarker = mMap.addMarker(new MarkerOptions() .position(latLng) //Указываем название маркера .title(Objects.requireNonNull(getContext()).getString(R.string.title_on_marker_to_new_order)) //Значение true , означает что маркер при длительном таче можно перетаскивать .draggable(true)); myMarker.setTag(null); //Показываем кастомные кнопки управления imageButtonAddMarker.setVisibility(View.VISIBLE); imageButtonRemoveMarker.setVisibility(View.VISIBLE); > >); > 

Указываем, что мы хотим сделать с маркером при нажатии на кнопку добавления заказа

private ImageButton imageButtonAddMarker; private Marker myMarker; @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) < imageButtonAddMarker = view.findViewById(R.id.imageButtonAddMarker); imageButtonAddMarker.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < if (myMarker !=null && myMarker.getTag()==null) < //Скрываем кастомные кнопки управления imageButtonAddMarker.setVisibility(View.GONE); imageButtonRemoveMarker.setVisibility(View.GONE); //Делаем что либо, в данном случае открываем фрагмент для ввода содержимого заказа listener.openOrderContentsFragmentFromMap(null, myMarker); //Удаляем маркер с карты, если он больше ненужен myMarker.remove(); >> >); > 

Еще одна особенность, это то что в SDK нет кнопки для удаления поставленного на карту маркера. Для этого тоже делаем свою кнопку:

Указываем, что мы хотим сделать с маркером при нажатии на кнопку удаления маркера

private ImageButton imageButtonRemoveMarker; private Marker myMarker; @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) < imageButtonRemoveMarker = view.findViewById(R.id.imageButtonRemoveMarker); imageButtonRemoveMarker.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View v) < if (myMarker !=null && myMarker.getTag()==null)< //Скрываем кнопки управления imageButtonAddMarker.setVisibility(View.GONE); imageButtonRemoveMarker.setVisibility(View.GONE); //Удаляем маркер с карты myMarker.remove(); >> >); > 

При нажатии на маркер открывается его заголовок, нажатие на который так же можно использовать для совершения какого либо действия, я при нажатии на заголовок нового маркера создаю новый заказ на доставку курьеру, а на маркер уже существующего заказа — открываю подробную информацию о доставке, включающюю перечень товаров.

Задаем действие при нажатии на информационное окно маркера

private GoogleMap mMap; @Override public void onMapReady(GoogleMap googleMap) < mMap = googleMap; mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() < @Override public void onInfoWindowClick(Marker marker) < if (marker.getTag()==null) < //Совершаем действие с новым маркером: //например создаем новый заказ на доставку listener.openOrderContentsFragmentFromMap(null, marker); if (myMarker != null) < //Удаляем маркер с карты, если он больше ненужен myMarker.remove(); >> else < //Совершаем действие с уже существующим маркером: //например мы ранее вывели адреса курьерских доставок на карту listener.openOrderContentsFragment((Long) marker.getTag()); >> >); > 

Процесс вывода нескольких маркеров (считай списка заказов) на карту ничем принципиально не отличается от вывода одного маркера. Маркер состоит из координат (position), заголовка (title), мелкого текста под заголовком (snippet) и тэга (setTag) — его можно использовать для идентификации множества маркеров на карте.

image

Несколько маркеров на карте

Отрисовка нескольких маркеров с заданными координатами

public void drawListMarker(List latLngList) < if (latLngList == null || latLngList.size() == 0) < return; >//очищаем карту от маркеров mMap.clear(); LatLngBounds.Builder builder = new LatLngBounds.Builder(); boolean fiarstGreean = true; int count = 1; for (InfoMarker latLng : latLngList) < BitmapDescriptor icon; if (fiarstGreean)< //первый отрисованный маркер будет зеленого цвета //т.к. заказы отсортированны по времени и первый на доставку выделен цветом icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN); fiarstGreean = false; >else < icon = latLng.getIcon(); >//добавляем маркер на карту в цикле mMap.addMarker(new MarkerOptions().position(latLng.getLatLng()).title(String.valueOf(count)).snippet(latLng.getTitle()).icon(icon)).setTag(latLng.getIdOrder()); builder.include(latLng.getLatLng()); count++; > //отображаем на карте участок с заданным маштабом CameraUpdate cameraUpdate; if (loaded) < cameraUpdate = CameraUpdateFactory .newLatLngBounds(builder.build(), 100); >else < cameraUpdate = CameraUpdateFactory.newLatLng(builder.build().getCenter()); >mMap.moveCamera(cameraUpdate); mMap.animateCamera(CameraUpdateFactory.zoomIn()); mMap.animateCamera(CameraUpdateFactory.zoomTo(10), 1000, null); > 

Пара слов о геокодере

Геокодер используется для получения адреса, на основании координат. Поставив маркер на карте и нажав кнопку добавить заказ, мы получаем географические координаты нужной точки, т.е. широту и долготу. Но для удобства пользователя неплохо будет показать адрес в человекочитаемом виде, т.е., например, страна, город, улица, дом.

Google Maps SDK содержит класс Geocoder, вызвав его метод getFromLocation можно получить массив адресов по указанным координатам.

Для того, что бы не блокировать UI thread долгими, особенно если медленный или недоступный интернет, вызовами — будем использовать RxJava:

image

Полученный адрес точки на карте на основании географических координат

Использование Java RX для обращения к геокодеру Google

 LatLng position = myMarker.getPosition(); Location location = new Location("new"); location.setLatitude(position.latitude); location.setLongitude(position.longitude); LocationRepostiory locationRepostiory = new LocationRepostiory(context, location); locationRepostiory.getLastLocation(). observeOn(SchedulerProvider.getInstance().ui()). subscribeOn(SchedulerProvider.getInstance().computation()). subscribe(locationString -> < if(editTextAddress.length()==0)< //Тут нам возвращается представление адреса в виде строки, полученное на основе географических координат editTextAddress.setText(locationString); >>, throwable -> < >); 

Текст класса LocationRepostiory в котором происходит обратное геокодирование

  • Программирование
  • Java
  • Интерфейсы
  • Разработка под Android
  • Google API

9 полезных функций Google Maps, о которых вы могли не знать

Google Maps уже давно является одним из самых удобных приложений для геолокации. Помимо очевидных функций, вроде поиска маршрута из пункта «А» в пункт «Б» и онлайн-навигации, карты скрывают в себе еще множество полезных и удобных элементов, которые сразу не бросаются в глаза. AIN.UA решил собрать 9 функций Google Maps, о которых вы, возможно, раньше не знали.

1. Сохранение карт офлайн

В больших городах Украины уже есть 3G, а значит интернет может быть доступен повсеместно. Тем не менее, функция офлайн-сохранения карт может пригодиться в любой момент. В зарубежной поездке, при отключенном интернете, для экономии батареи — далеко не полный список обстоятельств, при которых сохраненная географическая область окажется очень кстати.

21

zkUHrlWbIaYdpgvVlGEaPw

Есть только один принципиальный момент, который стоит учесть при сохранении карт. Большие карты занимают довольно много места. Поэтому выгружать, например, весь Киев особого смысла нет Лучше всего сохранить именно ту часть карты, в рамках которой вы планируете перемещаться. А за ненадобностью — не забыть удалить. Иначе, свободная память в устройстве очень быстро исчерпается.

2. Возможность делиться локацией

Казалось бы, очевидная функция может очень пригодиться в ситуации, если вам нужно срочно кому-то сообщить свое местоположение или адрес какого-либо учреждения. Сделать это проще простого — нужно выбрать место на карте, нажать на полоску внизу экрана и, в открывшемся окне, выбрать «Поделиться».

3uqHYrmDWbJk

3. Домашний и рабочий адреса

В Google Maps есть возможность сохранить свои домашний и рабочий адреса. Таким образом их легко будет выбрать в любой момент, а, если у вас установлен еще и Google Now, он сам будет рассчитывать время езды на работу или домой, и сообщать вам о начале или об окончании рабочего дня.

45

4. Расписание последнего маршрута общественного транспорта

Помимо того, что Карты умеют рассчитать оптимальный маршрут общественным транспортом, включая пересадки, в них имеется и расписание движения этого транспорта. На отдельной вкладке можно специально посмотреть, когда отходит последний троллейбус, трамвай или метро. Это, с точностью до нескольких минут, работает в США и Европе. В Украине мы бы советовали не полагаться на данную информацию стопроцентно. Не потому что Google не дорабатывает, а потому что движение общественного транспорта в стране плохо поддается систематизации.

6 7 84n8lfeSPACI

5. Велодорожки

Не так давно в Google Maps появилась возможность строить не только автомобильный, транспортный и пешеходный маршруты, а и велосипедный. Впрочем, украинцам радоваться еще рано — даже те велодорожки, которые есть в украинских городах, Карты пока не отображают. Но если вы окажетесь в США или, например, в Вене, то вполне сможете покататься по городу на велосипеде полагаясь на Карты.

KBUPBnHKE8sUC8cFNGQTvs

6. Подсказки по ближайшим заправкам, кафе и прочим заведениям

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

98Dh2yKs5k7k

7. Нестандартный поиск

Возможности поисковой строки Google Maps гораздо шире, чем просто определение адреса, который вы хотите найти. Английская версия включает в себя больше хаков, но и на русском/украинском есть с чем побаловаться. Например, по запросу «кафе рядом со мной», Карты подыщут ближайшие заведения, которые в базе данных Google обозначены, как «кафе». Или же можно написать «тренажерные залы в центре», что тоже даст релевантный результат. В общем, скорее всего Google угадает большинство ваших запросов, написанных «человеческим языком», но рассчитывать на особую проницательность поисковика все же не стоит.

XjIC5oJivW4xkCVo6AfcXU

8. Сохранение мест при помощи указателей

Еще одна простая функция, которая может пригодится в самый неожиданный момент. Если дважды кликнуть по экрану карты, появится красный указатель. Кликнув на нижнюю полоску экрана, адрес по указателю можно будет добавить в «сохраненные». Очень помогает, если нужно вспомнить место, в котором вы бывали только раз, или же запланировать себе локацию для будущей поездки.

3fLdEimQGm8w

9. Увеличение и уменьшение масштаба одним пальцем

Последняя рекомендация касается способа увеличить или уменьшить карту, которым вы, возможно, не пользуетесь. Самым очевидным способом сделать Zoom in/Zoom out является «раздвинуть» карту на экране при помощи двух пальцев. Но есть еще один вариант — если сделать двойной клик по карте, и этим же пальцем начать скроллить вверх или вниз — масштаб начнет меняться. Это сложно отобразить на скриншоте — просто попробуйте. Преимущество данного метода, помимо того, что для него требуется на один палец меньше, в том, что изменение масштаба происходит более плавно. Очень может пригодиться, если вы, например, мчитесь по городу, держа в руках пакет с продуктами или сумку, и срочно ищете нужный адрес на экране смартфона.

Напомним, что недавно в Google Maps появился инструмент, который показывает историю всех ваших перемещений.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *