使用 AngularJS 和 Mapbox 可视化地理数据

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

使用地理数据集时最好的事情之一就是您可以使用地图。对于我所有的交互式可视化,我一直在使用 LeafletJS 在 Web 浏览器上实现这一点,但最近我在使用 AngularJS 时遇到了一些性能问题。本文介绍了我用来构建应用程序的技术堆栈,以及我如何解决一些性能问题。

基础

对于我构建的任何 Web 应用程序,我总是求助于 NodeJS ,所以首先要确保你的机器上安装了它。接下来,为了快速入门,我将使用 Yeoman 来使用生成器来构建应用程序的基础。使用 npm 全局安装:


 npm install -g yo

Yeoman 是一个 Web 脚手架框架,可以减轻启动 Web 应用程序的痛苦;你每次都做那些无聊的样板文件。话虽如此,它并不适合所有人,因为它会带来很多您可能不会使用的依赖项和代码。就我们的目的而言,Yeoman 很好。

您还需要安装 Grunt ,一个 JavaScript 任务管理器和 Bower ,用于管理客户端依赖项。


 npm install -g yo

接下来,我们将使用一个为我们提供 Express 和 AngularJS 的生成器,称为 generator-angular-fullstack


 npm install -g yo

现在我们已经安装了所需的一切,转到一个新目录以包含您的项目并使用生成器构建一个新应用程序。在命令行类型:


 npm install -g yo

在上面,我使用地图作为应用程序名称。您现在需要做的就是回答适合您的项目的问题。对于此示例,MongoDB 不是必需的,但我已将 Bootstrap 用于我的 UI。同样,这取决于您,与我们的地图示例无关。

您可以使用以下带有 grunt 的命令来运行您的应用程序:


 npm install -g yo

该应用程序默认在端口 9000 上运行,如下所示


创建 API 端点以检索数据

您应该做的下一件事是在您的应用程序中添加一个端点,它将返回您的地理数据。使用生成器创建端点很简单。您需要做的就是提供端点的名称,在我们的例子中是位置:


 npm install -g yo

如果您将浏览器指向 http://localhost:9000/api/locations,您将得到一个空数组。让我们用我们的位置数据填充它。

端点的控制器位于 server/api/location/location.controller.js,你可以看到它只是返回一个空数组作为响应:


 npm install -g yo

我们现在需要做的是读取传回我们的真实位置数据。理想情况下,您将拥有自己的数据,但对于这个示例,我去了斯坦福网络分析项目并获取了他们的一些(匿名的) Gowalla 位置数据 。这提供了大量经度和纬度点以尝试在地图上可视化,但我没有获取整个文件,而是复制了前 5000 条记录。

当我们在 NodeJS 服务器中读取文件时,最简单的做法是将文件放在根目录中。接下来,使用 npm 安装 CSV-streamer 包,为我们提供读取文件并将其转换为 JSON 对象的能力。请注意,我们在这里使用 --save 以便将包信息保存到 package.json 中。


 npm install -g yo

您的控制器现在如下所示,从索引 2 和 3 中的制表符分隔文件中获取纬度和经度,在读取 4999 行后返回数据:


 npm install -g yo

通过我们的 API 返回位置数据,是时候开始真正的工作了。

将 Leaflet 与 AngularJS 一起使用

让我们从在我们的 AngularJS 应用程序中显示一个简单的地图开始。为了以最少的麻烦做到这一点,我们将使用 angular-leaflet-directive

首先,使用 bower 安装包,并将其保存到 bower.json 文件中:


 npm install -g yo

我还安装了 leaflet-plugins 包:


 npm install -g yo

使用 grunt serve 重新启动 grunt 进程以确保加载依赖项。您可以通过打开 index.html 并检查文件末尾是否按如下方式加载脚本来仔细检查:


 npm install -g yo

对于更熟悉的地图,最好在此处也包含 Google Maps API,但在 HTML 的 bower 部分之外


 npm install -g yo

将对 leaflet 指令的依赖添加到您的 app.js 文件中,该文件定义了 Angular 模块:


 npm install -g yo

接下来,移动到主页的 Angular 控制器,位于 client/app/main.controller.js 下。您可以在此处为将要显示的地图设置一些默认值。


 npm install -g yo

上面的代码只是将地图设置为使用 Google Streets 基础图层并将中心点设置为旧金山。现在,要显示一个简单的地图,我们可以将指令添加到 main.html


 npm install -g yo

应用程序终于成型了!

显示位置标记

现在我们需要调用我们的 API 来检索标记并将它们显示在我们的地图上。您可以在 AngularJS 控制器中毫不费力地执行此操作,首先将数据属性添加到我们的范围,以便它可以在页面中共享。


 npm install -g yo

要显示标记集群,您可以考虑使用 Leaflet 的标准 标记集群解决方案 (Leaflet.MarkerCluster),它得到了角度指令的良好支持。但是,如 本示例 所示,当您处理大量标记时,这可能会有点慢。我遇到了这样的限制,但发现了一些关于 PruneCluster 的建议,它在面对大量标记时表现得更好。 10,000 标记测试 使用此库运行得非常快。

问题在于 AngularJS 传单指令中没有对 PruneCluster 的“原生”支持,因此您需要做一些不同的事情才能使其正常工作。

集成 PruneCluster

首先,您需要使用 bower 下载 PruneCluster 依赖项


 npm install -g yo

Bower 不会自动将库添加到我的 HTML 中,所以我必须手动添加。 PruneCluster 的 CSS 样式表需要包含在 index.html 中


 npm install -g yo

并且 JavaScript 需要包含在同一个文件的末尾


 npm install -g yo

现在,因为您无法在我们的指令中访问 PruneCluster,所以您需要直接访问 Leaflet Map 对象。您可以通过在控制器上添加对 leafletData 服务的依赖来完成此操作


 npm install -g yo

加载地图时,将执行 leafletData.getMap 函数。当发生这种情况时,您可以在控制器的范围内存储对地图的引用


 npm install -g yo

通过访问 Map 对象,您可以使用 Leaflet 做任何您想做的事情。让我们使用 PruneCluster 渲染标记来完成。

renderMarkers 函数使用 PruneCluster 创建一个层,分别注册每个标记,并在所有这些完成后处理视图:


 npm install -g yo

现在当我们通过 API 检索地理数据时,我们可以简单地调用 renderMarkers 函数


 npm install -g yo

这导致标记出现得非常快。

您将在 GitHub 页面上找到更多有关如何使用 PruneCluster 的示例,包括使用自定义标记、过滤等的能力。