地图和地理编码库的 JavaScript 兼容替换

前端代码是更换服务商时最痛苦的地方,因为地图库、地理编码组件和计费都纠缠在一起。这些加载器和设置让您可以保留现有的库代码。在其背后,瓦片、地理编码、自动补全和海拔数据都由我们提供。地图加载和瓦片免费;只有地理编码调用会计入您的配额。

关于 REST 方面,全部十七个主机的对照表和迁移清单请参阅兼容替换的工作原理

本页内容

Google Maps JavaScript API 地图库

从 gapi.mygeocode.com 而不是 maps.googleapis.com 加载地图库。我们提供 google.maps 命名空间,地图瓦片、标记、Geocoder、Places Autocomplete 和 ElevationService 均由我们提供服务。地图加载不计入您的配额。

之前
<script async defer
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_KEY&libraries=places&callback=initMap">
</script>
之后
<script async defer
  src="https://gapi.mygeocode.com/maps/api/js?key=YOUR_MYGEOCODE_KEY&libraries=places&callback=initMap">
</script>
然后像以前一样使用
// Nothing below this line changes.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 51.5074, lng: -0.1278 },
    zoom: 12
  });

  const geocoder = new google.maps.Geocoder();
  geocoder.geocode({ address: "221B Baker Street, London" }, (results, status) => {
    if (status === "OK") {
      map.setCenter(results[0].geometry.location);
      new google.maps.Marker({ map, position: results[0].geometry.location });
    }
  });

  const input = document.getElementById("search");
  const autocomplete = new google.maps.places.Autocomplete(input, { fields: ["geometry", "formatted_address"] });
  autocomplete.addListener("place_changed", () => {
    const place = autocomplete.getPlace();
    if (place.geometry) map.panTo(place.geometry.location);
  });
}

包含

  • 使用我们瓦片的 google.maps.Map(roadmap、satellite 和 terrain 地图类型)
  • Marker、InfoWindow、Polyline、Polygon、Circle、Rectangle、LatLng、LatLngBounds 和 event
  • Geocoder(正向和逆向)
  • places.Autocomplete 组件和 places.AutocompleteService
  • ElevationService
  • 控件、手势,以及使用相同样式数组格式的自定义样式地图

不包含

  • 街景(Street View)
  • Directions、Distance Matrix 和 Routes
  • Places Details、Photos 和 Nearby Search
  • Drawing、Visualization 和 Geometry 库
  • 3D 和 WebGL 叠加视图

什么算作一个请求。地图加载和瓦片请求免费。每次 Geocoder 调用、每个 Autocomplete 会话以及每次 ElevationService 调用各计为一个请求。

Bing Maps V8 Web Control 地图控件

V8 控件已随 Bing Maps for Enterprise 的其他部分一同停用。从 bing.mygeocode.com 加载该控件,Microsoft.Maps 命名空间即可继续工作,背后使用我们的瓦片、地理编码和自动建议。

之前
<script async defer
  src="https://www.bing.com/api/maps/mapcontrol?key=YOUR_BING_KEY&callback=loadMap">
</script>
之后
<script async defer
  src="https://bing.mygeocode.com/api/maps/mapcontrol?key=YOUR_MYGEOCODE_KEY&callback=loadMap">
</script>
然后像以前一样使用
function loadMap() {
  const map = new Microsoft.Maps.Map("#map", { center: new Microsoft.Maps.Location(47.6396, -122.13), zoom: 12 });

  Microsoft.Maps.loadModule("Microsoft.Maps.Search", () => {
    const search = new Microsoft.Maps.Search.SearchManager(map);
    search.geocode({
      where: "1 Microsoft Way, Redmond, WA",
      callback: (result) => {
        const loc = result.results[0].location;
        map.setView({ center: loc, zoom: 15 });
        map.entities.push(new Microsoft.Maps.Pushpin(loc));
      }
    });
  });
}

包含

  • Microsoft.Maps.Map、Location、LocationRect、Pushpin、Infobox、Polyline、Polygon 和 Layer
  • Search 模块:SearchManager.geocode 和 reverseGeocode
  • Autosuggest 模块:AutosuggestManager 和输入框绑定
  • 使用我们瓦片的道路、航拍和灰度地图类型
  • 事件、导航栏和地图选项

不包含

  • Directions 模块
  • Traffic、Spatial Data Services 和 Spatial Math 高级功能
  • 鸟瞰图(Bird's eye)和街景(Streetside)影像
  • Well Known Text、GeoJSON 和 GeoXml 模块(请改用 Leaflet 或 MapLibre 的 GeoJSON 模块)

什么算作一个请求。地图加载和瓦片免费。每次 geocode、reverseGeocode 以及每个 autosuggest 会话各计为一个请求。

Mapbox GL JS 和 mapbox-gl-geocoder

保留您的地图代码,只需替换两个 URL:样式和地理编码器来源。推荐使用 MapLibre GL JS(开源分支)作为渲染器;Mapbox GL JS v1 也可以使用。mapbox-gl-geocoder 有一个 origin 选项,因此除此之外,地理编码控件无需修改任何代码。

之前
const map = new mapboxgl.Map({
  container: "map",
  style: "mapbox://styles/mapbox/streets-v12",
  accessToken: "YOUR_MAPBOX_TOKEN"
});
map.addControl(new MapboxGeocoder({
  accessToken: "YOUR_MAPBOX_TOKEN",
  mapboxgl: mapboxgl
}));
之后
const map = new maplibregl.Map({
  container: "map",
  style: "https://mapbox.mygeocode.com/styles/v1/mygeocode/streets?access_token=YOUR_MYGEOCODE_KEY"
});
map.addControl(new MapboxGeocoder({
  accessToken: "YOUR_MYGEOCODE_KEY",
  origin: "https://mapbox.mygeocode.com",
  mapboxgl: maplibregl
}));
然后像以前一样使用
// Direct calls keep the same shape too
const res = await fetch(
  "https://mapbox.mygeocode.com/geocoding/v5/mapbox.places/Oxford%20Street%20London.json?access_token=YOUR_MYGEOCODE_KEY",
  { headers: { "X-API-Key": "YOUR_KEY" } }
);
const { features } = await res.json();
map.flyTo({ center: features[0].center, zoom: 15 });

包含

  • 矢量瓦片样式:streets、light、dark 和 outdoors,遵循 Mapbox 样式规范
  • 使用 origin 选项的 mapbox-gl-geocoder,包括 proximity、bbox、countries 和 types
  • 静态图片位于 /styles/v1/mygeocode/{style}/static/{lon},{lat},{zoom}/{width}x{height}
  • 适用于 Leaflet 和 OpenLayers 的栅格瓦片位于 /v4/mygeocode.streets/{z}/{x}/{y}.png

不包含

  • Mapbox GL JS v2 及更高版本(其许可要求使用 Mapbox 令牌;请使用 MapLibre)
  • Directions、Isochrone、Matrix 和 Optimization API
  • Mapbox Studio 自定义样式(请改为将您的样式 JSON 上传到您的账户)

什么算作一个请求。瓦片和静态图片免费。每个地理编码请求计为一个请求;自动补全的按键输入照常由控件进行防抖处理。

Leaflet 地理编码插件

Leaflet 通过插件与地理编码服务通信,常用插件都支持设置服务 URL。将 Leaflet Control Geocoder 或 leaflet-geosearch 指向 osm.mygeocode.com,并使用我们的瓦片作为底图。

之前
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
  attribution: "&copy; OpenStreetMap contributors"
}).addTo(map);

L.Control.geocoder({
  geocoder: L.Control.Geocoder.nominatim()
}).addTo(map);
之后
L.tileLayer("https://tiles.mygeocode.com/streets/{z}/{x}/{y}.png?key=YOUR_MYGEOCODE_KEY", {
  attribution: "&copy; My Geocode"
}).addTo(map);

L.Control.geocoder({
  geocoder: L.Control.Geocoder.nominatim({
    serviceUrl: "https://osm.mygeocode.com/",
    geocodingQueryParams: { key: "YOUR_MYGEOCODE_KEY" }
  })
}).addTo(map);
然后像以前一样使用
// leaflet-geosearch works the same way
import { OpenStreetMapProvider, GeoSearchControl } from "leaflet-geosearch";

const provider = new OpenStreetMapProvider({
  searchUrl: "https://osm.mygeocode.com/search",
  reverseUrl: "https://osm.mygeocode.com/reverse",
  params: { key: "YOUR_MYGEOCODE_KEY", addressdetails: 1 }
});
map.addControl(new GeoSearchControl({ provider, style: "bar" }));

包含

  • Leaflet Control Geocoder:nominatim、google、bing、mapbox、here、opencage、latLng 和 mapquest 地理编码器,各自指向对应的 www.mygeocode.com 主机
  • leaflet-geosearch:OpenStreetMapProvider、GoogleProvider、BingProvider、HereProvider、LocationIQProvider、OpenCageProvider 和 GeoapifyProvider
  • streets、light 和 dark 样式的栅格瓦片
  • 任何允许设置 Nominatim URL 的其他插件

不包含

  • 路线规划插件(Leaflet Routing Machine 及类似插件)
  • 上述三种之外的瓦片样式

什么算作一个请求。瓦片免费。每次地理编码和每次逆地理编码各计为一个请求。

HERE Maps API for JavaScript 地图库

从 here.mygeocode.com 加载 mapsjs 包,并照常创建 platform。H.Map、H.service.Platform 和 search 服务保持原有签名,矢量瓦片和地理编码由我们提供。

之前
<script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
之后
<script src="https://here.mygeocode.com/v3/3.1/mapsjs-core.js"></script>
<script src="https://here.mygeocode.com/v3/3.1/mapsjs-service.js"></script>
<script src="https://here.mygeocode.com/v3/3.1/mapsjs-ui.js"></script>
<script src="https://here.mygeocode.com/v3/3.1/mapsjs-mapevents.js"></script>
然后像以前一样使用
const platform = new H.service.Platform({ apikey: "YOUR_MYGEOCODE_KEY" });
const layers = platform.createDefaultLayers();
const map = new H.Map(document.getElementById("map"), layers.vector.normal.map, {
  center: { lat: 52.5304, lng: 13.3853 }, zoom: 13
});

platform.getSearchService().geocode(
  { q: "Invalidenstraße 116, Berlin" },
  (result) => {
    const { position } = result.items[0];
    map.setCenter(position);
    map.addObject(new H.map.Marker(position));
  },
  (err) => console.error(err)
);

包含

  • H.Map, H.map.Marker, H.map.Polyline, H.map.Polygon, H.map.Group
  • 带 createDefaultLayers 的 H.service.Platform(矢量普通、卫星、地形)
  • SearchService:geocode、reverseGeocode 和 autosuggest
  • H.ui.UI 默认控件和 H.mapevents.Behavior
  • H.geo.Point、H.geo.Rect 及辅助工具

不包含

  • Routing、Isoline 和 Public Transit 服务
  • 交通和事故图层
  • Places Discover 和 Browse
  • 来自 HERE Style Editor 的自定义地图样式(请使用我们的样式 JSON 格式)

什么算作一个请求。地图加载和瓦片免费。每次 geocode、reverseGeocode 和 autosuggest 调用各计为一个请求。

MapQuest.js

MapQuest.js 封装了 Leaflet 并添加了 L.mapquest.geocoding()。从 mapquest.mygeocode.com 加载该包,并像以前一样设置您的密钥。

之前
<script src="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script>
<link type="text/css" rel="stylesheet" href="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.css"/>
之后
<script src="https://mapquest.mygeocode.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script>
<link type="text/css" rel="stylesheet" href="https://mapquest.mygeocode.com/sdk/mapquest-js/v1.3.2/mapquest.css"/>
然后像以前一样使用
L.mapquest.key = "YOUR_MYGEOCODE_KEY";

const map = L.mapquest.map("map", {
  center: [41.8789, -87.6359],
  layers: L.mapquest.tileLayer("map"),
  zoom: 12
});

L.mapquest.geocoding().geocode("233 S Wacker Dr, Chicago, IL", (err, response) => {
  const loc = response.results[0].locations[0].latLng;
  map.setView(loc, 15);
  L.marker(loc, { icon: L.mapquest.icons.marker() }).addTo(map);
});

包含

  • L.mapquest.map 和 tileLayer(map、hybrid、satellite、light、dark)
  • 支持 geocode 和 reverse 的 L.mapquest.geocoding
  • L.mapquest.searchAhead(自动补全)控件
  • 图标、控件位置和标准 Leaflet API

不包含

  • 路线和路线图层
  • 交通图层
  • Static Map API(静态地图)

什么算作一个请求。瓦片免费。每次 geocode、reverse 和 search-ahead 请求各计为一个请求。

地图瓦片与样式

上述所有加载器都使用同一个瓦片服务,您也可以在任何库中直接使用它。

格式URL
栅格,256pxhttps://tiles.mygeocode.com/{style}/{z}/{x}/{y}.png
栅格,512px,适用于高像素密度屏幕https://tiles.mygeocode.com/{style}/{z}/{x}/{y}@2x.png
矢量瓦片(MVT)https://tiles.mygeocode.com/v/{z}/{x}/{y}.pbf
适用于 MapLibre 和 Mapbox GL 的样式 JSONhttps://tiles.mygeocode.com/styles/{style}.json

样式包括 streetslightdarkoutdoorssatellite。瓦片流量不计费,也无需密钥。我们的瓦片由 OpenStreetMap 数据和我们自己的数据渲染而成;署名控件必须显示 © OpenStreetMap contributorsMy Geocode,上述加载器会为您自动添加。

浏览器中的密钥

不要在客户端代码中放置 API 密钥。页面源代码中的密钥任何人都能读取,而且由于一个密钥同时只能从两个或三个 IP 地址使用,在第二或第三位访客之后它也会停止工作。

地图瓦片、样式和上述库加载器完全不需要密钥,因此地图本身始终可以工作。对于这些库发出的地理编码、自动补全和海拔调用,请通过您自己的服务器转发:加载器接受 proxy 参数(gapi.mygeocode.com/maps/api/js?proxy=https://yoursite.com/geo),并将这些调用发送到那里;您的服务器添加密钥后再将请求转发给我们。这样,上面的 YOUR_MYGEOCODE_KEY 占位符就留空即可。

  • 您的代理可以添加缓存和自己的限制,而浏览器做不到这一点。
  • 这样请求都来自您服务器的地址,因此一个密钥即可覆盖任意数量的访客。