门店查询(store locator)是每家多网点企业最终都会用到的小功能:那个把邮编变成地图上一小串排序门店的「查找最近门店」输入框。从外面看它很简单,主流程也确实简单,但一个做得好的门店查询在暗处把三件事都做对了:读懂杂乱的位置输入、按真实距离排序网点、把结果渲染成人能据此行动的地图。
本文讲解门店查询的实际工作方式、用地图 API 构建它的四个步骤,以及区分 demo 与可上线产品的那些细节。本文中的每张地图都由 MapAtlas API 自身渲染。
门店查询到底做了什么
剥掉样式,门店查询就是一条三阶段的流水线:
- 地理编码访客输入。「1012 Amsterdam」、「SW1A 1AA」或共享的 GPS 位置,都必须变成唯一的一组经纬度。
- 周边排序门店。有了该坐标和网点位置列表,在合理半径内找出最近的几家。
- 渲染结果。把排好序的门店以标记放到地图上,每个标记带地址、营业时间和导航链接。
下面这张地图正是第三阶段,用 MapAtlas 瓦片渲染:阿姆斯特丹市中心的六家网点,按与访客的距离标注。这里的标记是超市,但无论标记来自 POI 数据集还是你自己的门店列表,地图都是一样的。

颜色顺序就是排序结果。访客从地图中心发起搜索,标记按由近及远的顺序对应最近的网点。
第 1 步:地理编码访客输入
访客输入邮编、城市或完整地址,你需要的是一组坐标。这就是正向地理编码。
// Turn what the visitor types into a coordinate (autocomplete geocoding)
const res = await fetch(
`https://gateway.mapmetrics-atlas.net/autocomplete/` +
`?token=${API_TOKEN}&text=${encodeURIComponent(query)}` +
`&focus.point.lat=52.37&focus.point.lon=4.89` // bias toward your service area
);
const { features } = await res.json();
const [lon, lat] = features[0].geometry.coordinates; // [lon, lat]
const label = features[0].properties.label; // "Damrak, Amsterdam, North Holland, Netherlands"
这里有两个细节要注意。传入靠近服务区的 focus.point,让「Cambridge」解析到正确的那一个;另外要处理访客共享设备 GPS 而非手动输入的情况,此时坐标已经拿到,这一步可以完全跳过。
第 2 步:按距离对门店排序
现在有了访客坐标。门店本身是自有数据:一份网点列表,每条带经纬度,存在你的数据库里。排序就是一次直线(haversine)距离计算,无需调用 API:
// Your branches, each with a lat/lon. Rank by distance from the visitor.
const ranked = stores
.map(s => ({ ...s, distance_m: haversine(lat, lon, s.lat, s.lon) }))
.sort((a, b) => a.distance_m - b.distance_m)
.slice(0, 6);
基础版门店查询到这里就够了。网点规模大时,应先用访客周围的 bounding box 过滤,避免每次请求都对全部网点算距离,再对剩下的排序。输出是一份最近网点的短列表,每条带 distance_m。
第 3 步:先按距离排序,再用通行时间修正
直线距离是正确的默认值。它快、不需要额外调用,对密集网点通常也是对的。但直线最近的门店未必最快到达:隔着一条河的 400 米门店,可能意味着绕到最近的桥要多花十分钟。
如果门店查询里的「最近」真正含义是「最快到达」,就用 directions 或 matrix 调用按真实通行时间对头部几个候选重新排序:
// Re-rank the closest stores by real drive time (MapAtlas Matrix API)
const res = await fetch(`https://gateway.mapmetrics-atlas.net/matrix/?token=${API_TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sources: [{ lat, lon }],
targets: top3.map(s => ({ lat: s.lat, lon: s.lon })),
costing: 'auto', // 'auto' | 'bicycle' | 'pedestrian'
}),
});
const { sources_to_targets } = await res.json();
const row = sources_to_targets[0]; // one entry per target, each with .time (seconds)
const byTime = top3
.map((s, i) => ({ ...s, time: row[i].time }))
.sort((a, b) => a.time - b.time);
这一步只对少数最近候选执行,因此始终是一次廉价调用,而不是每家门店一次。
第 4 步:把门店渲染到地图上
最后一步是地图本身。给每家排好序的门店放一个标记,加上带地址和营业时间的弹窗,并调整视野让所有结果都可见。当瓦片、地理编码和搜索由同一家地图 API 提供时,整套门店查询端到端只有一家供应商、一套坐标系,本文前面那张地图正是这样构建的。
给每个标记配一个弹窗,放上访客据以行动的关键信息:名称、地址、距离、营业时间,以及把坐标交给路径引擎的「导航」链接。
区分 demo 与生产的细节
空结果。 有人从你没有网点的区域发起搜索。要事先决定:自动扩大半径、无论多远都展示唯一最近的门店,还是诚实地告知「50 公里内无门店」。
营业时间。 把已经关门的店当成最近选项展示,体验很糟。按营业时间过滤或打标,让「现在营业」成为一等选项。
歧义输入。 「Cambridge」在英格兰和马萨诸塞州都有,「Springfield」有几十个。在地理编码步骤做国家偏置能消除大部分歧义,输入时提供自动补全能消除剩下的。
移动端 GPS 与授权。 移动端最强的体验是「使用我的位置」按钮,但读取设备 GPS 属于位置数据,需要用户授权。先征求同意,访客拒绝时回退到文本输入。
隐私。 访客位置一旦与其身份绑定,就是个人数据。按需地理编码、避免存储原始坐标、使用位于欧盟的 API 让位置不离开 EEA。完整说明见我们的 GDPR 合规地图指南。
用 MapAtlas 构建门店查询
MapAtlas 用一套 API、一套坐标系提供完整流水线。Geocoding API 把邮编和城市转成坐标,并支持国家偏置;你用该坐标对自有网点列表排序;Directions 与 Matrix API 按真实通行时间对头部候选重新排序;Dynamic Maps 瓦片把结果渲染出来,就是本文展示的效果。由于全流程默认在欧盟境内运行,访客位置始终留在 EEA,门店查询无需额外工作即可保持 GDPR 合规。
各端点完整的请求与响应格式见 MapAtlas API 文档。如果希望门店查询不仅能找到自有网点,还能发现访客周边的兴趣点,Search API 也值得一看。
门店查询是个小功能,内部却藏着大量安静的判断:读懂模糊输入、按真实距离排序、尊重「位置属于个人数据」这一事实。把这三点做对,「查找最近门店」输入框就不再是事后补充,而会成为站点上使用最频繁的功能之一。
常见问题
什么是门店查询(store locator)?
门店查询就是零售或服务网站上的「查找离你最近的门店」功能。访客输入邮编、城市,或直接共享位置,功能返回按距离排序的最近网点,每个网点都在地图上标出,并附带地址、营业时间和路线链接。底层只有三步:把输入地理编码成坐标、对自有门店列表跑一次周边查询、再把结果渲染到地图上。
门店查询功能怎么做?
分四步构建。第一步,用地理编码 API 把访客输入(邮编或城市)转成经纬度。第二步,对门店坐标跑半径查询或最近邻查询,取出最近的网点。第三步,按距离排序,可选再按驾车时间排序。第四步,把排好序的门店以标记形式渲染到地图上,并配上弹窗。如果地图 API 由同一家提供商同时提供地理编码、周边查询和地图瓦片,这四步无需拼接多家服务即可完成。
一定要用 store locator API 吗?
需要的是地理编码、地图瓦片,通常还有按通行时间排序的能力;门店列表本身是自有数据。可以把少量门店硬编码进代码,自己算直线距离,但一旦要支持邮编搜索、驾车时间排序和地图渲染,把地理编码、matrix 和地图渲染集成在一家提供商的 API 就能省去对接三家供应商、调和三套坐标格式的麻烦。
门店查询如何对最近的门店排序?
最简单的排序是从访客坐标到各门店的直线(大圆)距离,升序排列。这种方式快,对密集的城市网点通常够用。想要更好的体验,就用路径或 matrix API 按真实通行时间对头部候选重新排序,因为一旦遇上河流、高速和单行道,直线最近的门店未必最快到达。
门店查询符合 GDPR 吗?
可以符合,而当访客位于欧盟境内时必须符合。门店查询处理的是位置,而位置一旦与用户绑定就属于个人数据。保持合规的做法是:按需地理编码而不存储访客坐标、使用位于欧盟的地图 API 让位置数据不离开 EEA、读取设备 GPS 前先征得同意。MapAtlas 默认在欧盟境内处理位置查询。

