用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图

eegeo.js是基于流行的映射库Leaflet构建的开源 3D地图API。

有许多贴图库可让您嵌入或构建简单的2D贴图。 尤其是Google Maps 、 Bing Maps 、 HERE 、 Mapbox和OpenStreetMap 。 流行的映射抽象库(例如OpenLayers和Leaflet)还允许您更改地图的“基础层”,而无需更改应用程序逻辑。

随着Google Earth API的使用下降到NPAPI安全性弃用 ,3D map API的选择受到限制。 确实存在替代方案,例如流行的Cesium库。 eegeo.js是另一种,它提供了从空间到室内地图的动态、真正无缝的3D世界地图。 在浏览器中使用WebGL。

入门

在本文中,我将向您展示嵌入精美的伦敦3D地图并使用Transport for London API添加一些基本功能有多么简单。

剧透:3D地图就像使用2D地图一样简单。

免责声明:我是eeGeo的软件开发高级副总裁,我负责eegeo.js的开发。

有很多关于如何使用Leaflet的教程。 eeGeo.js是有意识地基于Leaflet构建的,因此已经熟悉Leaflet的开发人员可以立即启动并运行。 我完全推荐传单示例和文档 。

本文将介绍基本的HTML、CSS、JavaScript和简单的映射概念。

您需要什么

本文将介绍一些关键组件:

  • 传单( 文档 , 示例 )
  • eeGeo.js( 文档 , 示例 )
  • 伦敦运输(TfL)API
  • Python,或用于上传HTML、CSS和JavaScript的位置

显示伦敦的2D地图

首先,让我们使用Leafet和Open Street Map创建伦敦的2D地图。 传单非常简单。 您只需要一点HTML来设置页面,一个

来包含您的地图,以及几行JavaScript来创建和设置初始位置。

创建HTML

让我们用以下标记创建一个HTML文件:



  
    
    Building Gorgeous 3D maps with eegeo.js and Leaflet
  
  
    

包括传单

要包含Leaflet,就像添加Leaflet JavaScript库和CSS一样简单。 将这些包括在标记内:


 

添加传单JavaScript

JavaScript的以下几行初始化Leaflet,并将OpenStreetMap用作图块层。 您可以将其添加为外部JavaScript文件,或者为了简单起见,可以添加到

下面的块中:

var map = L.map('map', {
  center: [51.517327, -0.120005],
  zoom: 15
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap contributors'
}).addTo(map);

该代码以WGS84(十进制纬度,经度51.517327, -0.120005为中心,以Holborn地铁站为中心初始化地图。 您可以通过右键单击并在maps.eegeo.com或Google Maps等数字地图上选择“这里是什么”来获取这些坐标。 稍后您会看到,大多数地理空间API都以标准WGS84十进制度的纬度和经度返回位置,包括TfL API。

启动2D地图

将您的HTML上传到某个地方,或在本地查看。 我建议不要直接从文件系统加载,而要使用本地回送Web服务器。 将HTML保存为index.html ,并在同一文件夹中运行: python -m SimpleHTTPServer 8000然后,您可以在浏览器中访问http://localhost:8000/

您将看到以伦敦的霍尔本地铁站为中心的以下地图:

用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图_第1张图片

显示伦敦的3D地图

由于eeGeo.js是基于Leaflet构建的,因此只需进行很少的更改即可将伦敦的2D地图转换为精美的3D地图。

将上面添加的将var map = L.map ...读取的JavaScript更改为以下内容。 需要免费的eeGeo API密钥 。 您也应该删除不再需要调用L.tileLayer的JavaScript。

JavaScript现在应显示为:

var map = L.eeGeo.map('map', '', {
  center: [51.517327, -0.120005],
  zoom: 15
});

更改我们添加到

就是这样! 通过仅更改几行,您现在将看到Holborn Tube Station的完全相同的视图,但是是以华丽的3D形式显示:

用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图_第2张图片

更改缩放、倾斜和方向

由于eeGeo.js是完全3D的,因此可以旋转和倾斜地图。 支持Leaflet setView函数,具有可选的倾斜和航向参数以支持地图的3D行为。

添加以下JavaScript,10秒钟后,地图将以3D模式从Holborn Tube Station到伦敦的小黄瓜进行无缝动画处理:

setTimeout(function() {
  map.setView([51.514613, -0.081019], 17, {headingDegrees: 204.374, tiltDegrees:15.0});
}, 10000);

用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图_第3张图片

屏幕截图并没有说明交互作用,但是此CodePen展示了实际的动画:

在CodePen上查看带有eeGeo.js的Pen Gorgeous 3D地图过渡和 SitePoint( @SitePoint )的Leaflet 。

上面setView()的其他参数如下:

领域 类型 描述
headingDegrees 小数 顺时针方向从北开始的十进制度,其中0.0是北。
tiltDegrees 小数 以度为单位的倾斜度,其中45.0直接在顶部,而0.0是默认的倾斜视图

与伦敦3D地图互动

现在,让我们为地图添加一些有用的东西。 支持大多数Leaflet图元,例如标记,折线和多边形。

要将Holborn地铁站的标记添加到地图,请调用L.marker()

L.marker([51.517327, -0.120005]).addTo(map);

要在罗素广场添加多边形,请调用L.polygon() 。 多边形由四个顶点按顺时针方向定义,从罗素广场北偏东角的Bernard St&Wolborn Place交界处开始:

L.polygon([[51.522771, -0.125772],
           [51.521520, -0.124192],
           [51.520631, -0.126358],
           [51.521963, -0.127895]]).addTo(map);

要添加一条从布卢姆斯伯里(始于Great James St.到博物馆St.)的路线的折线:

L.polyline([[51.521788, -0.117101],
            [51.520732, -0.116524],
            [51.520430, -0.117641],
            [51.519873, -0.119602],
            [51.519034, -0.120993],
            [51.518784, -0.121537],
            [51.517265, -0.125088],
            [51.516257, -0.124466]]).addTo(map);

刷新后,三个Leaflet基本体现在将显示在地图上:

用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图_第4张图片

您会注意到对L.marker()L.polyline()L.polygon()的调用都是Leaflet API调用。 如果我们将地图从以前的版本还原回OpenStreetMap,则完全相同的调用仍将在2D OSM基本层上起作用:

用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图_第5张图片

伦敦运输(TfL)API

接下来,让我们将来自真实世界API的一些数据添加到伦敦的3D地图中。

伦敦交通运输(TfL)API庞大而复杂。 它涵盖伦敦的所有运输,包括公共汽车、地铁、地面、自行车租赁,并提供实时状态和到达时间数据。

完整的TfL API的范围太大,本文无法涵盖。 我将只关注描述伦敦地铁的极少数API端点,特别是回答:

  • 有哪些可用的管线?
  • 特定的管线在哪站停靠?
  • 特定地铁站的“到达板”是什么?

TfL API可以在没有严格限制速率的API密钥的情况下使用。 如果您在实际的生产部署中使用TfL API,则应注册API密钥 。

有哪些可用的管线?

为了回答“有哪些可用的管线”问题,TfL API 在“管线”资源上提供了一个端点

我们仅对“管状”运输方式感兴趣,因此请进行以下调用:

curl -v https://api.tfl.gov.uk/line/mode/tube

返回带有Line实体数组的JSON响应。 我们只对每个条目的id属性感兴趣:

[{
  "id": "bakerloo",
  "name": "Bakerloo",
  "modeName": "tube",
  "disruptions": [],
  "lineStatuses": [],
  "routeSections": [],
  ...
},...]

为了简化与TfL API的交互,我们将使用jQuery,但是对jQuery的依赖是完全可选的。 以下JavaScript调用Line端点并收集Line ID:

$.getJSON( "https://api.tfl.gov.uk/line/mode/tube", function(data) {
  var lines = [];
  $.each(data, function(k, line) {
    lines.push(line.id);
  });
});

稍后,我将使用这些Line ID来查询其他TfL端点,这些端点描述了沿着特定地下路线的车站。

将伦敦地铁建模为图形

您可以将伦敦地铁视为图表 。 图包含顶点和边。 对于伦敦地铁,我将这些站点视为“顶点”,而这些管线将形成“边缘”。

用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图_第6张图片

将中心线(上方红色)建模为图形,在北阿克顿,西阿克顿和挂车巷处将有顶点。 由于中线从北阿克顿(North Acton)西行有一个分支,因此在北阿克顿(North Acton)和西阿克顿(West Acton)之间以及北阿克顿(North Acton)和Hanger Lane之间也存在一条中线Edge

在中心线以东,是诺丁山门。 诺丁山门地铁站只有一个,但它有三条线的站台:中央(红色)、圆形(黄色)和地区(绿色)。 我们只想为诺丁山门添加一个传单标记,而不是三个。 如果我们将诺丁山门建模为顶点,则将有中心线Edges (至Holland Park和Queens Way), 圆线和区域线Edges至Bayswater和High Street Kensington。

这很重要,因为TfL API将Underground建模为有向图 。

特定地铁线上有哪些车站?

现在,我们有了地下每条线的线号。 我还计划将桩号和线作为Graph中的顶点和边进行松散建模。 给定线路ID,TfL API然后可以告诉我们每条线路停在哪个车站。 TfL API将这些称为StopPoints 。 我们将称为终点的线、路线,包括停靠点的顺序

让我们再次调用TfL API,以描述中心线的出站路由:

curl -v https://api.tfl.gov.uk/line/central/route/sequence/outbound

这将返回一个非常大的JSON有效负载,超过8000条漂亮的印刷行。 幸运的是,我们只对stopPointSequences键感兴趣:

"stopPointSequences": [
  {
    "lineId": "central",
    ...
    "stopPoint": [
      ...
      {
        "id": "940GZZLUNHG",
        "name": "Notting Hill Gate Underground Station",
        ...
        "lat": 51.509128,
        "lon": -0.196104
      },
      {
        "id": "940GZZLUQWY",
        "name": "Queensway Underground Station",
        ...
        "lat": 51.510312,
        "lon": -0.187152
      },
      ...
    ],
  },
  ...
]

此属性是JSON对象的列表,这些对象将行分成连续的部分。 在StopPointSequence中,沿线依次是所有StopPoint。

下面的JavaScript处理唯一的桩号的创建以及折线的创建,因此我们可以为管状线的边缘绘制一条线。

var stopPoints = {};
$.getJSON( "https://api.tfl.gov.uk/line/central/route/sequence/outbound", function( data ) { 
  var lineSegments = [];
  $.each(data.stopPointSequences, function(k, v) { 
    var line = [];
    $.each(v.stopPoint, function(k, sp) {
      line.push([sp.lat, sp.lon]);
      if (!(sp.id in stopPoints)) {
        stopPoints[sp.id] = {"id":sp.id, "name":sp.name, "lat":sp.lat, "lon":sp.lon};
      }
    });
    lineSegments.push(line);
  });
});

现在,我们可以为Underground的每一行调用上述JavaScript。 之后,我们将在stopPoint词典中整理每个唯一的站点。 对于每条线,我们还有一组折线的集合,这些折线表示lineSegments数组中管线的各个lineSegments

稍后,我将展示如何添加传单标记和折线以直观地显示试管桩号和线。

哪些火车到达特定车站?

我们需要的最终TfL API端点是实时到达。 在上一节中,我们可以看到工作站在API中具有唯一标识符。 对于Notting Hill Gate,ID为940GZZLUNHG

{
  "id": "940GZZLUNHG",
  "name": "Notting Hill Gate Underground Station",
  ...
  "lat": 51.509128,
  "lon": -0.196104
}

现在,我们可以调用TfL StopPoint API ,提供一个StopPoint ID:

curl -v https://api.tfl.gov.uk/stoppoint/940GZZLUNHG/arrivals?mode=tube

这将返回一系列到达:

[{
    ...
  "naptanId": "940GZZLUNHG",
  "stationName": "Notting Hill Gate Underground Station",
  "lineId": "central",
  "platformName": "Eastbound - Platform 3",
  "direction": "outbound",
  ...
  "destinationName": "Epping Underground Station",
  "timeToStation": 290,
  "currentLocation": "Between White City and Shepherd's Bush",
  "towards": "Epping",
  ...
},
...]

这表明到埃平的东行火车将在不到5分钟的时间(290秒)内到达3号站台。

把它放在一起

到目前为止,我已经向您展示了如何:

  • 使用Leaflet创建简单的2D OpenStreetMap地图
  • 使用eeGeo.js和Leaflet将简单的2D地图变成华丽的3D地图
  • 以传单标记,折线和多边形的形式向地图添加简单的细节
  • 使用Transport for London API执行基本交互

现在将这些简单的概念整合在一起,以生成伦敦的3D交互式地图,显示伦敦地铁的线路和车站以及所有车站的实时到达时间!

 

添加地铁站标记

在上一个请求https://api.tfl.gov.uk/line/central/route/sequence/outbound $.getJSON()调用中,为每个站点调用L.marker()

$.each(stopPoints, function(k, sp) {
  L.marker([sp.lat, sp.lon], 
    {
      title: sp.name,
      options: {"id":sp.id, "name":sp.name}
    }).addTo(map);
});

我们已通过标记传递了其他“选项”。 如此一来,稍后在处理鼠标悬停事件时,我们便知道我们已经悬停了哪个Station ID和Name。

为地下线添加折线

再次,在请求https://api.tfl.gov.uk/line/central/route/sequence/outbound的上一个Ajax调用中,为每个线段添加一个L.polyline()调用:

$.each(lineSegments, function(k, ls)
{
  L.polyline(ls, {weight:8, color:"#CC3333"}).addTo(map);
});

上面的颜色可能来自按行ID查找。 在这种情况下,根据TfL设计指南 ,我将硬编码的圆线红色

在传单标记上处理鼠标悬停事件

我想显示来自TfL API的实时到达信息。 将Leaflet Marker悬停在鼠标上时,可能会收到回调。 还可以显示一个Leaflet Popup,以显示工作站的名称。

$.each(stopPoints, function(k, sp) {
  var marker = L.marker([sp.lat, sp.lon], 
  {
    title: sp.name,
    options: {"id":sp.id, "name":sp.name}
  }).addTo(map);
  marker.bindPopup(sp.name);
  marker.on('mouseover',_hovercard.overstation);         
  marker.on('mouseout',_hovercard.outstation);  
});

在下面的更复杂的CodePen中,我将展示_hovercard。*回调如何向TfL API发出请求,并使用实时到达车站填充标注卡。

放在一起

通过附加的关注点分离和更好的建模,您可以在此代码笔中看到eegeo.js,Leaflet和TfL API的完整演示:

见笔eeGeo.js和伦敦交通局API由SitePoint( @SitePoint上) CodePen 。

3D地图不必太难

在本文中,我展示了如何使用JavaScript和Leaflet将2D地图添加到您的网站,以及如何添加简单的地图功能(例如标记,折线和多边形)。 然后,我展示了如何轻松地从真实的API(例如,伦敦交通局(TfL)API)中添加数据

我已经强调了针对映射抽象库(例如OpenLayers和Leaflet)进行编码的好处。 地图的视觉效果可能会发生巨大变化,而代码几乎没有变化。 我还展示了使用eegeo.js可以进行简单的3D映射。

如果您对本文有任何意见或疑问,请在下面的评论中告诉我。

原文链接: https://www.sitepoint.com/3d-maps-with-eegeo-and-leaflet/

你可能感兴趣的:(用 eegeo.js 和 Leaflet 构建漂亮的 3D 地图)