在黑暗里发一点光

发布于     更新于
网页上嵌入地图

愿中国青年都摆脱冷气,只是向上走,不必听自暴自弃者流的话。能做事的做事,能发声的发声。有一分热,发一分光,就令萤火一般,也可以在黑暗里发一点光,不必等候炬火。此后如竟没有炬火:我便是唯一的光。

自由地在网页上嵌入地图。

通常想要在网页上通过经纬度显示地图,一般需要去服务提供商网站申请一个 key,这意味着调用频次的限制和使用者信息的追踪。而面向用户的地图服务商往往有分享功能,可以提供一个固定坐标的 iframe 。这里可以使用这个功能曲线救国。

获取经纬度坐标

const [lat, lon] = locArr.map(x => x * 1) // 首先拿到经纬度

在下面会需要将 经纬度(例如:35.6772,139.7708) 转为 GPS 坐标(例如:35°40'37.9"N 139°46'14.9"E

所以现找到相关的转换方法:

const transformLonlatToDD = coordinate => {
  const d = Math.floor(coordinate)
  const m = Math.floor((coordinate % 1) * 60)
  const s = ((((coordinate % 1) * 60) % 1) * 60).toFixed(1)
  return `${d}°${m}'${s}"`
}

const convertLoc = (lat, lon) => {
  const latstr = transformLonlatToDD(lat) + (lat > 0 ? 'N' : 'S')
  const lonstr = transformLonlatToDD(lon) + (lon > 0 ? 'E' : 'W')
  return latstr + ' ' + lonstr
}

// 输入经纬度,输出 坐标
convertLoc(lat, lon)

使用 OpenStreetMap

OpenStreetMap 是一个世界地图,由像您一样的人们所构筑,可依据开放许可协议自由使用。

使用 OpenStreetMap 的分享功能,可以获取到这样的代码:

<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://www.openstreetmap.org/export/embed.html?bbox=132.83569335937503%2C31.690781806136822%2C146.68945312500003%2C39.47860556892209&amp;layer=mapnik&amp;marker=35.679609609368605%2C139.7625732421875" style="border: 1px solid black"></iframe><br/><small><a href="https://www.openstreetmap.org/?mlat=35.680&amp;mlon=139.763#map=7/35.680/139.763">查看更大的地图</a></small>

看起里这里并不能简单的通过经纬度和缩放级别来生成一个链接,稍微灵光一现一下就可以想到,链接里的参数 bbox 是一个拥有四个值的盒子,通过四个值画出一个范围来显示地图。marker 是地图标记的经纬度。

最终只需要这样处理就可以了。

const iframeSrc = `https://www.openstreetmap.org/export/embed.html?bbox=${lon - x}%2C${lat - y}%2C${lon + x}%2C${lat + y}&layer=mapnik&marker=${lat}%2C${lon}`
<iframe
    width="500"
    height="350"
    frameBorder="0"
    title="OpenStreetMap"
    src={iframeSrc}>
</iframe>

使用 谷歌地图

同样使用谷歌地图的分享功能,可以获取到这样的代码:

<iframe src="https://www.google.com/maps/embed?pb=!1m10!1m8!1m3!1d13275103.061721278!2d139.7708!3d35.6772!3m2!1i1024!2i768!4f13.1!5e0!3m2!1sen!2sjp!4v1620227399374!5m2!1sen!2sjp" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"></iframe>

这里除了能看到经纬度的坐标,其他的也看不懂,网上查找了一下,pb= 后面的参数是一种独特的编码:

参数的结构类似于(![id][type][value]),类型如下:

  • m: matrix
  • f: float
  • d: double
  • i: integer
  • b: boolean
  • e: enum (as integer)
  • s: string
  • u: unsigned int

经过反复的测试,然后删掉可能不需要的参数(比如 !4v 是时间戳, 1024768 看着像屏幕尺寸,enjp 是语言),最终得出一下可以用的结构:

// 在谷歌地图上可以显示地图标记,但是需要使用上面的方法获取到 GPS 坐标,然后转为 base64 编码格式。
const b64 = btoa(unescape(encodeURIComponent(convertLoc(lat, lon))))

const iframeSrc =  `https://www.google.com/maps/embed?pb=
    !1m10
      !1m4
        !1m3
          !1d5000000
          !2d${lon}
          !3d${lat}
      !3m3
        !1m2
          !1s0x0%3A0x0
          !2z${b64}
      !5e0`.replace(/[\r \t\n]+/g, '')

注释:

!1m10                    id 1,类型为矩阵,值为以下 10
    !1m4                     2级节点,类型为矩阵,值为以下 4
        !1m3                     3级节点 
            !1d5000000           这里是缩放级别,这里设置为 5e7 看着差不多
            !2d${lon}            经度
            !3d${lat}            纬度
    !3m3
        !1m2                     这里的值是 maker 标记的
            !1s0x0%3A0x0
            !2z${b64}            这里的值是上面 base64 编码过后的 GPS 坐标
    !5e0                         这里的值 1 时显示卫星图
<iframe
    width="500"
    height="350"
    frameBorder="0"
    title="GoogleMap"
    src={iframeSrc}>
</iframe>

End

最终效果图

screenshot image.

参考链接: