使用 Wijmo Bubble Maps 映射 JSON 数据集





5.00/5 (1投票)
如何使用 Wijmo、GrapeCity 提供的 100 多个动态 JavaScript UI 组件及其气泡地图功能,快速构建带有有用覆盖数据的地图
几个世纪以来,人类一直在地图上叠加信息,从最佳的军队营地位置到城市里最好的酒吧。如今,这些地图通常是数字化的、基于网络的,显示着从天气信息到病毒热点,再到城市里最好的酒吧等各种信息。今天,我们将探索如何使用 Wijmo、GrapeCity 提供的 100 多个动态 JavaScript UI 组件及其气泡地图功能,快速构建带有有用覆盖数据的地图。
我们的教程将使用 Wijmo React 库,但也提供 Vue、Angular 和纯 JavaScript (JS) 库。首先,我们将设置一个入门级 React 应用,然后使用来自 API 的静态 GeoJSON 创建一个 Wijmo 地图。
最后,我们将介绍如何使用来自实时 API 的数据添加工具提示。我们的应用程序将绘制加拿大谷物电梯的固定位置,然后绘制实时 COVID-19 信息,但重要的是要认识到可能性是无限的。
本教程使用 Wijmo 的 30 天免费试用版。要在生产环境中使用这些库,您需要 购买 Wijmo 许可证密钥 并将其提供给您的安装。要遵循本教程,您应该熟悉 npm 和 React,尽管我们会展示构建我们简单应用程序的所有步骤。
设置 React 页面
我们将首先使用 Create React App 来设置一个骨架 React 应用。
npx create-react-app wijmo-geomaps
接下来,我们将切换到 Create React App 设置的目录。
cd wijmo-geomaps
从这里,我们安装 Wijmo 和用作开发服务器的 serve 包。
npm install @grapecity/wijmo.react.all # Installs all wijmo packages
npm install serve # Simple dev server
npm install bootstrap react-bootstrap # Bootstrap
虽然这是您从 npm 安装 Wijmo 的方式,但我们下载了 Wijmo 开发包 并使用 npm ln 将下载文件夹链接到我们的 node_modules 文件夹。然后我们可以从那里导入文件。
现在我们构建我们的骨架应用程序。
npm run build
最后,我们可以在浏览器中查看我们的入门级 React 应用程序。
serve -s build
上面的命令会在您的本地计算机上一个免费端口上提供应用程序。在浏览器中查看 https://:5000 以查看应用程序的 React 徽标。
现在我们已经创建了入门级应用程序并安装了 Wijmo,我们可以使用 Wijmo 气泡地图来构建地图。
使用静态 GeoJSON 创建 Wijmo 地图
让我们开始向我们的应用程序添加内容。首先,更改目录到您的 React 应用程序的源目录。
cd src
现在,在您喜欢的文本编辑器中打开 App.js 文件。删除除最后一行之外的所有行。
export default App;
我们将重写 App
类以使用 Wijmo 气泡地图,因此请按以下方式设置您的 App.js 文件。
import 'bootstrap/dist/css/bootstrap.min.css';
import * as React from ‘react’;
class App extends React.Component
{
constructor(props)
{
super(props);
}
render()
{
return(
<div>Hello, world!</div>
);
}
}
export default App;
当您重新加载页面时,您应该会看到“Hello, World
”文本。
现在让我们开始制作一个基本的静态地图。添加以下 JS 和 CSS 导入,以便您可以使用 Wijmo 的库。
/* Wijmo */
import { FlexMap, GeoMapLayer, ScatterMapLayer } from '@grapecity/wijmo.react.chart.map';
import { Rect } from "@grapecity/wijmo";
import '@grapecity/wijmo.styles/wijmo.css';
现在我们用一个容器替换我们的占位符来容纳我们的 Wijmo 地图。我们使用 React Bootstrap 的 container-fluid 类来确保地图看起来不错。返回以下 JavaScript XML (JSX)。
<div className="container-fluid">
</div>
我们可以添加 Wijmo 地图组件了。Wijmo 地图使用一系列图层,您可以添加任意数量的图层,在 JSX 中稍后声明的图层将覆盖之前的图层。
让我们在刚刚创建的地图中声明地图。
<FlexMap>
</FlexMap>
您可以为 FlexMap
添加许多属性,包括 header
来设置地图标题,以及 tooltipContent
,它可以传递一个函数来返回一个 string
,该字符串将在地图点处的工具提示中显示。现在我们使用 header
属性,稍后设置 tooltipContent
属性。
我们的地图标题指的是我们稍后将添加的谷物电梯数据源。
<FlexMap header="Grain Elevators in Canada">
</FlexMap>
此数据集可通过公共 REST API 获取,该 API 返回 Wijmo 地图使用的格式 GeoJSON。
现在,让我们向我们的应用程序添加一张加拿大地图。我们可以将此轮廓添加为 FlexMap
内的 GeoMapLayer
。
<FlexMap header="Grain Elevators in Canada">
<GeoMapLayer
url="[https://raw.githubusercontent.com/johan/world.geo.json/master/countries/CAN.geo.json]
(https://raw.githubusercontent.com/johan/world.geo.json/master/countries/CAN.geo.json)"
style={{ fill: "transparent", stroke: "black" }}
/>
</FlexMap>
我们将 GeoJSON
数据作为 URI 提供给我们的 GeoMapLayer
,并添加一些最小的 CSS 样式。当您重建应用程序并重新加载时,您应该会在地图上看到加拿大的轮廓。
轮廓在那里,但看起来很小,因为地图没有足够放大。我们将使用回调来修复这个问题。Wijmo 气泡地图支持 itemsSourceChanged
事件,该事件在地图的 GeoJSON
源更改时触发。在我们的例子中,这只发生一次,当地图加载时,所以我们将处理该事件时放大。为此,请在构造函数中添加以下行。
this.canadaBB = new Rect(-80, 30, 80, 80);
这使用了我们之前导入的 Rect
类来定义一个聚焦于加拿大轮廓的边界矩形。矩形的左上角将在 (-80, 30) 处,我们将两侧的长度都设置为 80 个单位。
接下来,我们为 itemsSourceChanged
事件添加一个处理程序方法。
itemsSourceChanged(layer)
{
layer.map.zoomTo(this.canadaBB);
}
此处理程序将我们的侦听器传入图层,并在 GeoJSON
数据加载时调用。它使用该图层获取地图,然后使用我们之前定义的边界框放大加拿大轮廓。不要忘记在构造函数中绑定此处理程序,以便在将其传递给 GeoMapLayer
时能够正常工作。
this.itemsSourceChanged = this.itemsSourceChanged.bind(this);
最后,我们在 GeoMapLayer
中添加一个属性来设置我们图层的处理程序。
itemsSourceChanged={this.itemsSourceChanged}
构建您的应用程序并重新加载。由于处理程序在 GeoJSON
数据加载时放大,加拿大现在应该看起来更大了。
现在我们有了加拿大的轮廓,我们可以添加加拿大政府的 GeoJSON
数据集作为第二个 GeoMapLayer
来显示加拿大谷物电梯的位置。访问 加拿大政府网站,点击“GeoJSON
”按钮,然后复制该页面的 URL。我们需要将该 URL 传递给我们的 GeoMapLayer
。
我们还将使用橙色样式化这些位置,以使其脱颖而出。总而言之,我们完整的 Flexmap
如下所示。
<FlexMap header=”Grain Elevators in Canada”>
<GeoMapLayer
url="[https://raw.githubusercontent.com/johan/world.geo.json/master/countries/CAN.geo.json]
(https://raw.githubusercontent.com/johan/world.geo.json/master/countries/CAN.geo.json)"
style={{ fill: "transparent", stroke: "black" }}
/>
<GeoMapLayer
url="[https://www.agr.gc.ca/atlas/data_donnees/agr/cgcElevators/geoJSON/cgcElevators2018.geojson]
(https://www.agr.gc.ca/atlas/data_donnees/agr/cgcElevators/geoJSON/cgcElevators2018.geojson)"
style={{ fill: "transparent", stroke: "orange" }}
/>
</FlexMap>
重建并重新加载。您现在应该可以看到 2018 年加拿大谷物电梯位置周围的橙色轮廓。
就这样,我们创建了一个显示可识别的背景和 API 数据的地图。放大后,您还可以看到加拿大大部分谷物电梯都位于草原省份,如果您放大。
当然,您可以通过添加更多图层和附加数据来轻松地使设计更加复杂。您只需提供指向 GeoJSON 资源的 URL,例如本地文件或 API,然后该信息就会显示在您的地图上。
添加实时数据
通过添加更多组件和一些方法,我们可以轻松地包含来自实时 API 的数据。我们使用 一个 API 来提供有关加拿大 COVID-19 情况的数据。
我们将把这些实时数据转换为热图可视化,显示前一天每个省份的报告病例数。我们从以下 URI 获取数据:https://api.opencovid.ca/timeseries?stat=cases&loc=prov&after={prev-DD-MM-YYYY}&before={cur-DD-MM-YYYY}
我们选择获取每个省的总病例数。占位符表示我们通过为 after
参数传递前一天的日期,为 before
参数传递当天的日期来获取前一天的数据。
让我们先在构造函数中添加一个日期格式化对象。
this.dtFormatter = new Intl.DateTimeFormat("en-CA",
{
year: "numeric",
month: "2-digit",
day: "2-digit"
}
);
这会创建一个对象来获取日期的各个部分。这些参数确保我们将获得四位数的年份和两位数的月份和日期值,这正是我们创建要传递给 API 的日期所需要的。让我们为类添加一个方法,该方法将昨天和今天的日期转换为正确的格式的字符串。
getDates()
{
return {
"today": this.dtFormatter.formatToParts(new Date()).reverse().map
(part => part.value).join(""),
"yesterday": this.dtFormatter.formatToParts((new Date()).setDate
((new Date()).getDate() - 1)).reverse().map(part => part.value).join("")
};
}
此方法返回一个包含两个键的对象,一个用于今天,一个用于昨天。代码如下:获取昨天的日期或今天的日期,将其传递给格式化程序以返回年份、月份和日期作为整数,将列表反转为 DD-MM-YYYY 的顺序,提取列表中每个日期时间对象的数字,并将它们连接在一起。
幸运的是,日期格式化程序为我们插入了连字符,这正是 OpenCOVID
API 所期望的。如果将 getDates
的输出记录到控制台,您应该会看到类似以下的 string
。
现在我们有了日期,我们可以添加另一个方法,该方法向 OpenCOVID
API 发送请求并将响应解析为我们的地图可以使用的数据。
async getData(dates)
{
const url = "https://api.opencovid.ca/timeseries?stat=cases&loc=prov&after=" +
dates.yesterday + "&before=" + dates.today;
const resp = await fetch(url);
if (!resp.ok)
{
throw new Error(resp.statusText);
}
const json = await resp.json();
return json;
}
getData
接受 getDates
返回的日期对象,并使用它来构造 URL。然后我们等待服务器的响应,接收响应后将其转换为 JSON,然后返回转换后的响应。如果响应无效,我们也会抛出错误。
获取数据的最后一步是在生命周期方法 componentDidMount
中调用 getData
。
async componentDidMount()
{
const dates = this.getDates();
try
{
let apiDat = await this.getData(dates);
this.setState({
covidData:apiDat
});
}
catch (e)
{
console.log("componentDidMount: error occurred\nError: %o", e);
}
}
由于我们正在获取前一天的 COVID 数据,因此我们的应用程序仅在组件首次加载时调用此方法。如果您记录数据,您会看到它具有以下结构。
为了简单起见,我们将仅显示累计病例数。
为了显示数据,首先在构造函数中创建一个隐藏的“数据映射”,将病例数映射到省份。
this.state = {
dataMap: new Map(),
loadedData: false
};
我们添加一个布尔变量来确保我们的热图仅在数据加载后渲染。
接下来,让我们回到 componentDidMount
并添加一些代码,将每个省份的累计病例数与该省份关联起来。
apiDat.cases.forEach(report => {
this.dataMap.set(report.province, report.cumulative_cases);
});
this.setState({
covidData: apiDat,
loadedData: true
});
一旦我们将数据映射到省份,我们就告诉 React 使用新的 COVID 数据重新渲染我们的页面,并设置一个布尔值允许我们的热图图层显示。接下来,我们添加一个方法,在我们的热图图层请求数据时,该方法从我们的隐藏映射中获取数据。
必要时,此方法还会将省份名称从隐藏数据映射中使用的较长名称转换为 COVID-19 数据集中使用的缩写。我们还添加了一个方法,该方法反转病例百分比,以便病例数较高的省份颜色更深。
binding(o)
{
let nameConv = {
// Format: GeoJSON
name : COVID data name
"Newfoundland and Labrador": "NL",
"British Columbia": "BC",
"Northwest Territories": "NWT",
"Prince Edward Island": "PEI",
"Yukon Territory": "Yukon"
};
var dataMapName = o.properties.name;
if (o.properties.name in nameConv)
{
dataMapName = nameConv[o.properties.name];
}
return this.state.dataMap.get(dataMapName);
}
scale(v)
{
return 1 - v;
}
让我们还在构造函数中绑定这些新方法,以确保它们作为回调正常工作。
this.binding = this.binding.bind(this);
this.scale = this.scale.bind(this);
现在我们使用绑定方法添加一个 ColorScale
元素。让我们先将其与其他的 Wijmo React 图表元素一起导入。我们还将导入一些调色板来显示我们的热图,以及一个颜色比例尺来告知用户每种颜色的含义。
import { FlexMap, GeoMapLayer, <u>ColorScale</u> } from '@grapecity/wijmo.react.chart.map';
import { Palettes } from "@grapecity/wijmo.chart";
import { FlexChartLegend } from "@grapecity/wijmo.react.chart";
我们还将 GeoMapLayer
从单个元素更改为带有开始和结束标签的元素,以包含 ColorScale
,并且我们将在图层之后添加一个 FlexChartLegend
以在地图左侧显示比例尺。
<GeoMapLayer
url="https://raw.githubusercontent.com/codeforamerica/click_that_hood/
master/public/data/canada.geojson"
style={{ fill: "transparent", stroke: "black" }}
itemsSourceChanged={this.itemsSourceChanged}
>
{this.state.loadedData &&
<ColorScale
colors={Palettes.Diverging.RdYlBu}
binding={this.binding}
scale={this.scale}
/>
}
</GeoMapLayer>
<FlexChartLegend position="left"></FlexChartLegend>
我们使用布尔值来确保颜色比例尺仅在我们加载 COVID 数据后显示。地图将在受影响更严重的区域显示更红的颜色。
现在您有了一个显示来自 API 的实时数据的地图。
后续步骤
使用 Wijmo 气泡地图和标准的 GeoJSON 格式创建地图非常容易。您可以快速包含您的静态 JSON 文件或将地图指向 URL。
当您的静态底图准备就绪后,Wijmo 的组件和 JavaScript 钩子可以轻松地以自定义格式显示数据或显示实时数据。它们支持 React、Vue、Angular 或纯 JavaScript,您可以从 npm 安装包或下载完整的开发包、源 TypeScript、尝试示例等等。
既然您已经了解了如何轻松地将 Wijmo 气泡地图与公开可用的数据分层,您就可以在您的应用程序或网站中添加有用的地图:君主蝶栖息地改善、佛蒙特州的无线下载速度、弗吉尼亚州的社区游泳池、学区收入、水位,或者,是的,城市酒吧。
要开始创建下一个地图,或在您的应用程序中添加一百多种用户界面组件之一,请 探索 Wijmo。
历史
- 2021 年 9 月 17 日:初始版本