往期文章目录:

完成疫情地图绘制

在上一篇 React 17 + Vite + ECharts 实现疫情数据可视化「05 获取疫情数据」中我们获取到了最重要的疫情数据并对其结构进行了处理。

那么,本篇我们来介绍用于绘制地图的 Echarts 以及 echarts-for-react,在下一篇我们将进行地图的绘制,也将是系列文章的最终篇了,也代表着本项目基本版本就快要结束了,后续会推出 Pro 版本,尽情期待吧。

非常高兴能与大家在第 6 篇相见,我们进入正文吧!

子组件获取数据

有了 上一篇 传递数据给了子组件,现在我们就要在子组件获取父组件传递过来的值。

打开 components/Map 目录下的 Map.jsx 文件,编写如下代码:

import React from "react";
import s from './style.module.css'

const Map = (props) => {
const {mapList} = props;
console.log('从父组件获取得到的 mapList', mapList);
return(
<>
<div>CSDN:一百个Chocolate</div>
</>
)
}

export default Map

在子组件 Map.jsx 中通过 props 接受父组件传递过来的值,我们在控制台来打印一下,看看结果:

介绍 Echarts

老规矩,先附上 Apache ECharts 官方中文文档,小伙伴们最好是结合官方文档一起学习哈。

「04 初始化项目」这一篇文章中,我们介绍的是 Echarts 是 v4 版本,可以看到上述的官方文档是最新 v5 版本了。

因此,在这里附上 v4 版本的文档: Apache ECharts v4 官方中文文档

Echarts 特性

文档 所述:

ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。

  • 丰富的可视化类型
  • 多种数据格式无需转换直接使用
  • 千万数据的前端展现
  • 移动端优化
  • 多渲染方案,跨平台使用!
  • 深度的交互式数据探索
  • 多维数据的支持以及丰富的视觉编码手段
  • 动态数据
  • 绚丽的特效
  • 通过 GL 实现更多更强大绚丽的三维可视化

绘制中国地图

现在,正式开始绘制地图了。

这里就要打开新的文档了 echarts-api 文档

另外还有一个很重要的 github 地址:echarts-for-react

现在我们来到 Echarts v4 文档处,本次疫情地图绘制就是通过 registerMap 这个方法来实现。

可以看到必须填写的两个参数为 mapName 和 geoJson,mapName 这里我们就填写 china 就好了,对于 geoJson 我们还需要获取中国地图的 JSON 文件,并且文档中提及了 geoJson 格式的数据,具体格式见 https://geojson.org/

GeoJSON is a format for encoding a variety of geographic data structures.

{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}

因此,我们需要比较特殊的 JSON 文件,接下来就是来获取我们的地图 JSON 文件。

获取地图 JSON 文件

本项目 JSON 文件来自于网络,地址如下,仅供学习之用。

https://raw.githubusercontent.com/huanent/vue-echarts-map-demo/master/map/china.json

首先,打开 api/getCovid19Data.js 文件,新增一个请求中国地图 JSON 文件的函数,取名就叫 getChinaJSON。

// 获取中国地图 JSON 文件
export function getChinaJSON() {
return axios({
method: "get",
url: `https://raw.githubusercontent.com/huanent/vue-echarts-map-demo/master/map/china.json`,
})
}

请求获取地图 JSON

打开 components/Map 目录下的 Map.jsx,编写如下代码:

import React, {useEffect } from "react";
import s from './style.module.css'
import { getChinaJSON } from './../../api/getCovid19Data'

const Map = (props) => {
const {mapList} = props;

useEffect(() => {
const getData = async () => {
const chinaMapJSON = await getChinaJSON();
console.log('chinaMapJSON', chinaMapJSON)
}
getData();
}, [])

return(
<>
</>
)
}

export default Map

启动服务,打开控制台,看看打印结果:

展开 features 之后的效果图:

对于一下 GeoJSON 需要的格式,没错,要的就是这个格式。

{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [125.6, 10.1]
},
"properties": {
"name": "Dinagat Islands"
}
}

导入 echarts 包,注册地图组件

下面,我们开始导入 echarts 相关的包。打开 components/Map 目录下的 Map.jsx,在头部添加如下代码:

import echarts from 'echarts/lib/echarts'
import 'echarts/lib/chart/map'
import 'echarts/lib/component/visualMap'
import 'echarts/lib/component/tooltip'

接着,编写注册方法:

echarts.registerMap("china", chinaMapJSON.data);

为了让小狮子们方便学习,在这里贴上目前 Map.jsx 的完整代码。

import React, { useEffect } from "react";
import s from "./style.module.css";
import { getChinaJSON } from "./../../api/getCovid19Data";
import echarts from "echarts/lib/echarts";
import "echarts/lib/chart/map";
import "echarts/lib/component/visualMap";
import "echarts/lib/component/tooltip";

const Map = (props) => {
const { mapList } = props;

useEffect(() => {
const getData = async () => {
const chinaMapJSON = await getChinaJSON();
echarts.registerMap("china", chinaMapJSON.data);
};
getData();
}, []);

return <></>;
};

export default Map;

使用 ReactEcharts

由于本项目是 React 技术栈,为了更方便使用 Echarts,采用

全网开发者下载量最高的 ECharts 的 React 组件封装

echarts-for-react

使用的话也是比较方便,跟着 Chocolate 一步一步搭建实现最后的地图绘制吧。

导入 echarts-for-react 包

打开 components/Map 目录下的 Map.jsx,在头部添加如下代码:

import ReactEcharts from 'echarts-for-react/lib/core'

之后,使用 ReactEcharts:

return (
<>
<ReactEcharts echarts={echarts} />
</>
);

yarn dev 打开服务,首先看看控制台有没有 error。

发现 error

果然,有一个 error,但问题不大,有问题就来解决就好了。
、
这里贴下完整的 error 信息,如果小伙伴同样遇到问题的话可以复制搜一搜了解一下具体是怎么肥事。

Uncaught SyntaxError: The requested module '/node_modules/axios/index.js' does not provide an export named 'default'

最后,我是找到了这个 error:

react-for-echarts Could not resolve “prop-types”

这个就比较好解决,安装这个 prop-types 包就好了。

npm 安装:

npm install prop-types --save

yarn安装:

yarn add prop-types

目前我安装的版本如下图所示, 15.7.2(可能你学习的时候会有版本变化,应该不影响,用最新的就好了)

传入 option

为了展示数据,我们还需要向 ReactEcharts 传入 option,而这个 option 也需要一些特定的字段和数据,现在来介绍一下。

这里就要打开文档了 echarts-api 文档

开门见山,我们本次需要传入三个参数,分别是 tooltip、visualMap、series。

具体的参数细节这里就不一一解释了,对于每一个字段名官方文档已经说明很详细了,如果逐一解释文章篇幅会很长,在这里就给大家提供本项目源码,先出现疫情地图数据之后,大家可以根据提供的字段名和数据自定义样式。

当然,如果有任何不懂得地方,可以联系博主或者评论区留言。

tooltip 参数

tooltip 参数详情页面

关于 tooltip,就是提示框组件。下面我先将代码给大家展示一下,然后再说明具体做法。

tooltip: {
show: true,
formatter: function (params) {
let tip = ""
if (params.data) {
tip =
params.name +
":<br>确诊:" +
params.data["value"] +
"例<br>死亡:" +
params.data["died"] +
"例<br>治愈:" +
params.data["heal"] +
"例"
}
return tip
},
},

show 这个字段很好理解,就是是否显示提示框组件。

formatter

提示框浮层内容格式器,支持字符串模板和回调函数两种形式。在这里,我们采用的是字符串模板形式。

visualMap 参数

visualMap 是视觉映射组件,用于进行『视觉编码』,也就是将数据映射到视觉元素(视觉通道)。

附上完整代码:

visualMap: {
show: true,
type: "piecewise",
min: 0,
max: 2000,
align: "right",
top: "2%",
right: 0,
left: "center",
inRange: {
color: ["#ffc0b1", "#ff8c71", "#ef1717", "#9c0505"],
},
pieces: [
{ min: 1000 },
{ min: 500, max: 999 },
{ min: 100, max: 499 },
{ min: 10, max: 99 },
{ min: 1, max: 9 },
],
orient: "horizontal",
showLabel: true,
padding: 5,
text: ["高", "低"],
itemWidth: 10,
itemHeight: 10,
textStyle: {
fontSize: 10,
},
},

最终会在我们项目中绘制如下效果:

series 参数

series-map 以下引用官方文档:

地图。
地图主要用于地理区域数据的可视化,配合 visualMap 组件用于展示不同区域的人口分布密度等数据。
多个地图类型相同的系列会在同一地图上显示,这时候使用第一个系列的配置项作为地图绘制的配置。

Tip: 在 ECharts 3 中不再建议在地图类型的图表使用 markLine 和 markPoint。如果要实现点数据或者线数据的可视化,可以使用在地理坐标系组件上的散点图和线图。

series: [
{
left: "center",
type: "map",
name: "确诊人数",
label: {
show: true,
position: "inside",
fontSize: 6,
},
mapType: "china",
data: mapList,
zoom: 1.2,
roam: false,
showLegendSymbol: false,
rippleEffect: {
show: true,
brushType: "stroke",
scale: 2.5,
period: 4,
},
},
],

写成 getOption 函数

ReactEcharts 需要传入 option,在这里将上述参数写成一个获取函数,如下代码所示:

const getOption = () => {
const option = {
tooltip: {
show: true,
formatter: function (params) {
let tip = "";
if (params.data) {
tip =
params.name +
":<br>确诊:" +
params.data["value"] +
"例<br>死亡:" +
params.data["died"] +
"例<br>治愈:" +
params.data["heal"] +
"例";
}
return tip;
},
},
visualMap: {
show: true,
type: "piecewise",
min: 0,
max: 2000,
align: "right",
top: "2%",
right: 0,
left: "center",
inRange: {
color: ["#ffc0b1", "#ff8c71", "#ef1717", "#9c0505"],
},
pieces: [
{ min: 1000 },
{ min: 500, max: 999 },
{ min: 100, max: 499 },
{ min: 10, max: 99 },
{ min: 1, max: 9 },
],
orient: "horizontal",
showLabel: true,
padding: 5,
text: ["高", "低"],
itemWidth: 10,
itemHeight: 10,
textStyle: {
fontSize: 10,
},
},
series: [
{
left: "center",
type: "map",
name: "确诊人数",
label: {
show: true,
position: "inside",
fontSize: 6,
},
mapType: "china",
data: mapList,
zoom: 1.2,
roam: false,
showLegendSymbol: false,
rippleEffect: {
show: true,
brushType: "stroke",
scale: 2.5,
period: 4,
},
},
],
};
return option;
};

通过以下方式进行引入:

<ReactEcharts echarts={echarts} option={getOption()} />;

最后,给组件一个高度,大概 600 px,如下:

<ReactEcharts
style={{ height: "600px" }}
echarts={echarts}
option={getOption()}
/>;

Map.jsx 源码

提供 Map.jsx 文件的源码:

import React, { useEffect } from "react";
import s from "./style.module.css";
import { getChinaJSON } from "./../../api/getCovid19Data";
import ReactEcharts from "echarts-for-react/lib/core";
import echarts from "echarts/lib/echarts";
import "echarts/lib/chart/map";
import "echarts/lib/component/visualMap";
import "echarts/lib/component/tooltip";

const Map = (props) => {
const { mapList } = props;

useEffect(() => {
const getData = async () => {
const chinaMapJSON = await getChinaJSON();
echarts.registerMap("china", chinaMapJSON.data);
};
getData();
}, []);

const getOption = () => {
const option = {
tooltip: {
show: true,
formatter: function (params) {
let tip = "";
if (params.data) {
tip =
params.name +
":<br>确诊:" +
params.data["value"] +
"例<br>死亡:" +
params.data["died"] +
"例<br>治愈:" +
params.data["heal"] +
"例";
}
return tip;
},
},
visualMap: {
show: true,
type: "piecewise",
min: 0,
max: 2000,
align: "right",
top: "2%",
right: 0,
left: "center",
inRange: {
color: ["#ffc0b1", "#ff8c71", "#ef1717", "#9c0505"],
},
pieces: [
{ min: 1000 },
{ min: 500, max: 999 },
{ min: 100, max: 499 },
{ min: 10, max: 99 },
{ min: 1, max: 9 },
],
orient: "horizontal",
showLabel: true,
padding: 5,
text: ["高", "低"],
itemWidth: 10,
itemHeight: 10,
textStyle: {
fontSize: 10,
},
},
series: [
{
left: "center",
type: "map",
name: "确诊人数",
label: {
show: true,
position: "inside",
fontSize: 6,
},
mapType: "china",
data: mapList,
zoom: 1.2,
roam: false,
showLegendSymbol: false,
rippleEffect: {
show: true,
brushType: "stroke",
scale: 2.5,
period: 4,
},
},
],
};
return option;
};
return (
<>
<ReactEcharts
style={{ height: "600px" }}
echarts={echarts}
option={getOption()}
/>
</>
);
};

export default Map;

完成地图绘制

执行如下命令:

yarn dev

最终可以看到地图绘制成功了!

联系 & 期待下一篇

博主 21 届本科毕业,可以称呼我 Chocolate,喜欢就给个赞吧,我们下去再见。

学如逆水行舟,不进则退