Как вы, возможно, знаете, с 16 июля 2018 г. цена на API Карт Google резко изменится. Ознакомьтесь с руководством по ценам и оплате для существующих пользователей здесь.
Если в прошлом вы показывали карту огромному количеству пользователей бесплатно, с новой ценой это станет очень дорогим. 🙁
Есть много других решений, таких как Mapbox, который предоставляет настраиваемый и производительный javascript SDK с великолепным пользовательским интерфейсом с использованием технологии холста.
Но исходя из бесплатного плана Google Maps API, Mapbox кажется не подходящим решением из-за их цены.
К счастью, Apple только что выпустила MapKit для Интернета! 🚀
С ограничением бесплатного использования: 250 000 инициализаций карт в день для каждого ключа, а также 25 000 запросов на обслуживание для геокодирования и поиска.
Apple MapKit JS использует технологию WebGL, это гладко и быстро.
На момент публикации этой статьи SDK все еще находится в стадии бета-версии. Следуя документации, вам, возможно, придется настроить идентификаторы, ключи и токены Карт. Я не буду объяснять все это в этой статье, вы можете выполнить следующую процедуру:
Настройка MapKit JS (дополнительную информацию можно найти в слайдах тезисов презентации во время выступления)
Настройка карты:
В Google Maps API:
const map = new google.maps.Map( document.getElementById('mapElementId'), { zoom: 4, center: { lat: 48.864716, lng: 2.349014 } } );
В Apple MapKit JS:
const map = new mapkit.Map('mapElementId', { showsMapTypeControl: false, showsCompass: mapkit.FeatureVisibility.Hidden, center: new mapkit.Coordinate(48.864716, 2.349014) })
Различия между Google Maps API и Apple MapKit JS заключаются в том, что вы не можете определить уровень масштабирования карты в MapKit JS. Возможно, вам придется определить CoordinateRegion, который вы можете передать в качестве параметра с помощью атрибута region.
Отобразить маркер:
В Google Maps API:
const marker = new google.maps.Marker({ position: { lat: 48.864716, lng: 2.349014 }, map: map });
В Apple MapKit JS:
const coordinates = new mapkit.Coordinate(48.864716, 2.349014) const annotation = new mapkit.MarkerAnnotation
(coordinates, { data: { /* Custom data here */ },color: 'green'
}) map.addAnnotation(annotation)
Существует много типов аннотаций, таких как базовая аннотация, ImageAnnotation (для использования пользовательских изображений), а также MarkerAnnotation. Ознакомьтесь с документацией по аннотациям здесь
Отобразить информационное окно (всплывающее окно):
В Google Maps API:
const infowindow = new google.maps.InfoWindow({ content: '<h1>My popup content here</h1>' }); const marker = new google.maps.Marker({ position: { lat: 48.864716, lng: 2.349014 }, map: map, title: 'Paris' }); marker.addListener('click', () => { infowindow.open(map, marker); });
В Apple MapKit JS:
const AnnotationCallout = { calloutElementForAnnotation: (annotation) => { return '<h1>My popup content here<h1>' } } const coordinates = new mapkit.Coordinate(48.864716, 2.349014) const annotation = new mapkit.MarkerAnnotation
(coordinates, {color: 'green',
callout: AnnotationCallout }) map.addAnnotation(annotation)
Бонус: управление ZoomLevel с помощью MapKit JS
Поскольку вы не можете управлять уровнем масштабирования в MapKit JS так же, как вы можете сделать это с помощью Google Maps API и Mapbox, вы, вероятно, хотели бы знать, как установить уровень масштабирования по заданному целочисленному значению?
С помощью MapKit вам может потребоваться определить CoordinateRegion или BoudingRegion, и MapKit автоматически масштабирует и центрирует карту.
Это может быть проблемой, если вы используете Google Maps API или Mapbox. Надеюсь, эта суть, написанная на Swift позволит нам получить значения дельты, необходимые для SDK MapKit, из желаемого ZoomLevel.
Поскольку Javascript SDK Mapkit полностью идентичен IOS SDK, вот версия Javascript, которую я написал, работая с ZoomLevel, который я использовал в Google Maps API и Mapbox:
let mercadorRadius = 85445659.44705395 let mercadorOffset = 268435456 function longitudeToPixelSpaceX(longitude) { return Math.round(mercadorOffset + mercadorRadius * longitude * Math.PI / 180.0); } function latitudeToPixelSpaceY(latitude) { return Math.round(mercadorOffset - mercadorRadius * Math.log((1 + Math.sin(latitude * Math.PI / 180.0)) / (1 - Math.sin(latitude * Math.PI / 180.0))) / 2.0); } function pixelSpaceXToLongitude(pixelX) { return ((Math.round(pixelX) - mercadorOffset) / mercadorRadius) * 180.0 / Math.PI; } function pixelSpaceYToLatitude(pixelY) { return (Math.PI / 2.0 - 2.0 * Math.atan(Math.exp((Math.round(pixelY) - mercadorOffset) / mercadorRadius))) * 180.0 / Math.PI; } /** * * @param {object} map * @param {object} centerCoordinates * @param {number} zoomLevel */ const deltaFromZoomLevel = (map, centerCoordinates, zoomLevel) => { // convert center coordiate to pixel space let centerPixelX = longitudeToPixelSpaceX(centerCoordinates.longitude) let centerPixelY = latitudeToPixelSpaceY(centerCoordinates.latitude) // determine the scale value from the zoom level let zoomExponent = 20 - zoomLevel let zoomScale = Math.pow(2, zoomExponent) // scale the map’s size in pixel space let mapSizeInPixels = map.visibleMapRect.size let scaledMapWidth = mapSizeInPixels.width * zoomScale let scaledMapHeight = mapSizeInPixels.height * zoomScale // figure out the position of the top-left pixel let topLeftPixelX = centerPixelX - (scaledMapWidth / 2) let topLeftPixelY = centerPixelY - (scaledMapHeight / 2) // find delta between left and right longitudes let minLng = pixelSpaceXToLongitude(topLeftPixelX) let maxLng = pixelSpaceXToLongitude(topLeftPixelX + scaledMapWidth) let longitudeDelta = maxLng - minLng // find delta between top and bottom latitudes let minLat = pixelSpaceYToLatitude(topLeftPixelY) let maxLat = pixelSpaceYToLatitude(topLeftPixelY + scaledMapHeight) let latitudeDelta = -1 * (maxLat - minLat) // create and return the lat/lng span return { latitudeDelta, longitudeDelta } }
А вот пример того, как им пользоваться:
import deltaFromZoomLevel from './deltaFromZoomLevel' const coordinates = new mapkit.Coordinate(48.864716, 2.349014) const annotation = new mapkit.MarkerAnnotation
(coordinates, { data: { /* Custom data here */ },color: 'green'
}) annotation.addEventListener('select', () => { const currentZoomLevel = map._impl.zoomLevel; const zoomLevel = Math.min(13 - currentZoomLevel, 28); const delta = getDelta(map, coordinates, Math.round(zoomLevel)); // Create the CoordinateRegion from the delta latitude and // the delta longitude multiplied by 111 (1deg = 111km) const span = new mapkit.CoordinateSpan(delta.latitudeDelta * 111, delta.longitudeDelta * 111); const region = new mapkit.CoordinateRegion(center, span); map.setRegionAnimated(region) }) map.addAnnotation(annotation)
Вуаля! 🚀