目录
第1关:Vue+Echarts 实现数据接口绘制疫情地图
任务描述
本关任务:编写一个完成 Vue+Echarts 使用数据接口绘制的地图的程序。
相关知识
为了完成本关任务,你需要掌握:
-
寻找数据接口;
-
设置代理;
-
发送请求提取数据;
-
数据处理;
-
海外疫情地图数据处理绘制;
-
jsonp 方法。
寻找数据接口
http://interface.sina.cn/news/wap/fymap2020_data.d.json?_=1580892522427
大家打开这个链接就会看到我们的疫情数据,但是因为最近疫情数据都不继续更新了,所以数据可能不是实时的,也不影响。其次就是因为疫情地图的例子最为广泛,所以我们就以疫情数据地图为例,采用 Vue+Echarts 进行数据接口模式下的绘图。具体网页打开,我们可以看到数据如下:
设置代理
用 axios 请求这些数据如果出现跨域问题(之前的课程中讲到过),就设置本地代理,在根目录下创建 vue.config.js 文件:
module.exports = {devServer: {proxy: {"/api": {target: "https://www.ncovchina.com/data",changeOrigin: true,pathRewrite: {"^/api": ""}},"/aki": {target: "http://api.fanyi.baidu.com/api/trans/vip",changeOrigin: true,pathRewrite: {"^/aki": ""}}},host: "0.0.0.0",port: 8083,clientLogLevel: "info"}};
api 是中国疫情网数据; aki 是百度翻译接口,但是本次不用,因为百度翻译标准版返回的不准,用的爱翻译的谷歌翻译。
发送请求提取数据
提取数据 axios.post(/api/getDisease.html)
获得数据:
国内疫情数据获取并提取:
this.isLoading = true;axios.post(`/api/getDisease.html`).then(res => {let data = JSON.parse(res.data.data);console.log(data);let dss = data.areaTree[0].children;this.datas = dss;this.chinaTotal = data.chinaTotal.confirm;this.chinaAdd = data.chinaAdd.confirm;this.chinaNow = data.chinaTotal.nowConfirm;this.lastTime = data.lastUpdateTime;this.isLoading = false;});
分别提取了新增,总确诊,现存确诊在绘制中国疫情地图时需要
axios.post(“https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist”)
获取海外疫情这里获取了185个国家的数据,海外疫情数据获取并提取:
this.isLoading = true;axios.post("https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist").then(res => {let data = res.data.data;let names = [];data.forEach(item => {names.push(item.name);});this.worldData = data;this.test(names).then(res => {console.log(res.data.dst);let ss = res.data.dst;console.log(ss);let namess = ('"' + ss.replace(/, /g, '","') + '"').split(",");this.worldNames = namess;this.setEc(this.check);this.isLoading = false;});});
test 函数封装了爱翻译的谷歌翻译,setEc 是绘制地图函数。
test(content) {return axios.post("http://api.aifanyi.net/google.php",`content=${content}&from=zh-CN&fromtxt=中文&to=英文&totxt=英语`);},
为什么要这样提取数据,因为 echarts 地图数据是英文匹配,直接翻译即可:
-
namess为提取翻译后的国家数组赋值给worldName -
worldData为海外疫情数据 -
names.push是提取国家名以便于翻译
数据处理
假如百度翻译,腾讯翻译,有道翻译会导致翻译不准数据减少,185个国家名字,返回了174或者多点 Push 改变原格式,所有我们先 push 字符串再把字符串赋值给地图数据,见下面:
let min = 0;let max = 100;let title = " 地图";//地图标题(总,现存,新增)let data = [];//疫情数据let names = [];//提取省级名字let values = [];//提取城市疫情数据this.check = check;//获取选择(总,现存,新增)if (check === 0) {title = "国内现存确诊地图";this.datas.forEach((item, index) => {names.push(item.name);values.push(item.total.confirm - item.total.dead - item.total.heal);data.push({ name: names[index], value: values[index] });});min = 0;max = 100;}if (check === 1) {title = "国内总确诊地图";this.datas.forEach((item, index) => {names.push(item.name);values.push(item.total.confirm);data.push({ name: names[index], value: values[index] });});min = 0;max = 3000;}if (check === 2) {title = "国内新增确诊地图";this.datas.forEach((item, index) => {names.push(item.name);values.push(item.today.confirm);data.push({ name: names[index], value: values[index] });});min = 0;max = 5;}echarts.registerMap("china", china);let myChart = echarts.init(this.$refs.chart);myChart.clear();let option = {title: {text: title,left: "center"},tooltip: {trigger: "item",showDelay: 0,transitionDuration: 0.2},//工具visualMap: {left: "right",min: min,max: max,inRange: {color: ["#f9f9fa",// "#bfbfc0",// "#74add1",// "#abd9e9",// "#e0f3f8",// "#ffffbf","#fee090","#fdae61","#f46d43","#d73027","#a50026"]//颜色梯度},text: ["High", "Low"], // 文本,默认为数值文本 见地图calculable: true},toolbox: {show: true,//orient: 'vertical',left: "left",top: "top",feature: {dataView: { readOnly: false },restore: {},saveAsImage: {}}//工具功能},series: [{name: "数据",type: "map",roam: true,map: "china",//地图emphasis: {label: {show: true}},itemStyle: {normal: {label: {show: true//显示城市名}}},data: data}]};myChart.setOption(option);//绘图this.isChina = true;//控制地图选择是否显示myChart.on("click", function(params) {console.log(params);});
解析 check 控制选择地图类型(总,新增,现存),min 和 max 还有 color 数组 对应最大最小和颜色梯度:
点击地图触发事件
myChart.on(“click”, function(params) {console.log(params);});
海外疫情地图数据处理绘制
let datas = [];let title = "";this.isChina = false;this.check = check;let min = 0;let max = 100;echarts.registerMap("world", world);let values = [];if (check === 0) {this.worldData.forEach((item, index) => {values.push(item.nowConfirm);let sss = this.worldNames[index];sss = sss.substring(1, sss.length - 1);if (sss === "USA") {sss = "United States";}datas.push({name: sss,value: values[index]});});datas.push({ name: "China", value: this.chinaNow });title = "世界疫情现存地图";min = 1000;max = 100000;}if (check === 1) {this.worldData.forEach((item, index) => {values.push(item.confirm);let sss = this.worldNames[index];sss = sss.substring(1, sss.length - 1);if (sss === "USA") {sss = "United States";}datas.push({name: sss,value: values[index]});});datas.push({ name: "China", value: this.chinaTotal });title = "世界疫情总确诊地图";min = 100000;max = 1000000;}if (check === 2) {this.worldData.forEach((item, index) => {values.push(item.confirmAdd);let sss = this.worldNames[index];sss = sss.substring(1, sss.length - 1);if (sss === "USA") {sss = "United States";}datas.push({name: sss,value: values[index]});});datas.push({ name: "China", value: this.chinaAdd });title = "世界疫情新增确诊地图";min = 10;max = 1000;}let myChart = echarts.init(this.$refs.chart);myChart.clear();let option = {title: {text: title,left: "center"},tooltip: {trigger: "item",showDelay: 0,transitionDuration: 0.2},visualMap: {left: "right",min: min,max: max,inRange: {color: ["#f9f9fa",// "#bfbfc0",// "#74add1",// "#abd9e9","#e0f3f8","#ffffbf","#fee090","#fdae61","#f46d43","#d73027","#a50026"]},text: ["High", "Low"], // 文本,默认为数值文本见地图calculable: true},toolbox: {show: true,//orient: 'vertical',left: "left",top: "top",feature: {dataView: { readOnly: false },restore: {},saveAsImage: {}}},series: [{name: "数据",type: "map",roam: true,map: "world",emphasis: {label: {show: true}},itemStyle: {normal: {label: {show: false}}},data: datas}]};myChart.setOption(option);let vm = this;myChart.on("click", function(params) {console.log(params);if (params.name === "China") {console.log(1111);vm.setEcs(vm.check);}});
进入中国地图,关键参数:
myChart.on(“click”, function(params) {console.log(params);if (params.name === “China”) {console.log(1111);vm.setEcs(vm.check);}
jsonp 方法
关于获取疫情各城市的数据需要访问处理 json 数据,重点在是 jsonp ,在终端用 npm 下载引入即可: import jsonp from "jsonp";
具体的方法这里再举一个例子: 可以发现,对新浪疫情数据网站网址访问返回的 json 数据的形式是这样的:
所有的城市数据都在 list 中 item.city 中,但由于存在地级市所以对 list 中的 item 的 name 也要全部获取到,所以最终 getData() 的代码如下:
getData() {// 项目中用到的疫情实时动态接口数据来自本地文件axios.get('/data.json').then(data => {console.log(data);console.log(data.data)var lists = data.data.map(item => {return {//取出 name 以及 value,并将 name 中的省字替换掉name: item.name.replace("省",''),value: item.value}})console.log(lists)option.series[0].data = lists;this.mychart.setOption(option); // 执行的前提是demo已经渲染完成,只有demo渲染完成才能够执行echarts初始化}).catch(error => {console.error(error);});}
编程要求
根据提示,在右侧编辑器补充代码,完成 Vue+Echarts 使用数据接口绘制的地图程序。
- 补充代码文件;
-
在图形化界面打开终端,并进入
Desktop/workspace/myshixun目录下; -
采用
npm install命令安装依赖;
-
采用命令
npm install axios安装 axios 模块; -
采用命令
npm run serve命令运行项目;
- 打开平台浏览器输入
localhost:8080即可查看效果。
测试说明
平台会对你编写的代码进行测试,具体的运行截图如下:
注意:平台会先验证环境是否启动,然后模拟 HTTP 请求访问页面,最后再验证绘图结果,如果图像对比一致,则通关。
预期输出:
{"step":"正在验证环境是否启动"}Vue 程序启动成功!{"step":"模拟HTTP请求访问页面localhost:8080"}{"step":"正在验证绘图结果"}图像对比一致,恭喜通关!
开始你的任务吧,祝你成功!
代码文件
<template>
<div class="hello">
<!-- 初始化echarts 需要个有宽高的盒子 -->
<div ref="mapbox" class="box">
</div>
</div>
</template>
<script>
import axios from 'axios';
import echarts from 'echarts'
import 'echarts/map/js/china.js'
const option = {
title: {
text: '疫情地图', // 主标题
line: '', // 链接
subtext: '', // 副标题
sublink: '',
},
series: [{ // 图表类型
name: '确诊人数', //对应的是鼠标触摸后的内容
type: 'map', //告诉echarts 渲染地图
map: 'china',
label: {
show: true, //显示各个省份名称
fontSize: 8,
},
itemStyle: {
areaColor: '#fff' //区域的背景颜色
},
emphasis: {
//控制鼠标滑过时的高亮样式
itemStyle: {
areaColor: '#c7fffd'
}
},
roam: true, // 鼠标滚轮控制地图放大缩小,可拖拽
zoom: 1.2, //控制地图的大小
}],
visualMap: [{ // 视觉映射组件
type: 'piecewise',
show: true,
splitNumber: 6, // 分成几条
pieces: [{ // 手动分几条
min: 10000
}, // 不指定 max,表示 max 为无限大(Infinity)。
{
min: 1000,
max: 9999
},
{
min: 100,
max: 999
},
{
min: 10,
max: 99
},
{
min: 1,
max: 9
},
{
min: 0,
max: 0
}
],
//align:'right' // 默认是left
inRange: { // 地图颜色
symbol: 'rect', // 图元的图形类别 图标的形状,还可以设置circle
color: ['#fff', '#ffaa85', '#ff7b69', '#cc2929', '#8c0d0d', '#660208']
},
itemHeight: 10,
itemWidth: 20
}],
tooltip: { // 鼠标触摸显示
trigger: 'item'
// position: function (pos, params, dom, rect, size) {
// // 鼠标在左侧时 tooltip 显示到右侧,鼠标在右侧时 tooltip 显示到左侧。
// var obj = {top: 60};
// obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 5;
// return obj;
// }
},
toolbox: { // 可下载地图
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: { // 数据视图
readOnly: false
},
restore: {}, // 刷新
saveAsImage: {} // 保存图片
}
},
};
export default {
name: 'Map',
mounted() {
this.getData();
this.mychart = echarts.init(this.$refs.mapbox); //获取mapbox盒子
this.mychart.setOption(option);
},
methods: {
getData() {
// 项目中用到的疫情实时动态接口数据来自本地文件
/********** begin **********/
axios.get('/data.json')
.then(data => {
console.log(data);
console.info("================")
console.log(data.data)
var lists = data.data.map(item => {
return {
//取出 name 以及 value,并将 name 中的“省”字替换掉
name:_______________
value: _______________
}
})
console.log(lists)
option.series[0].data = lists;
this.mychart.setOption(option); // 执行的前提是demo已经渲染完成,只有demo渲染完成才能够执行echarts初始化
})
.catch(error => {
console.error(error);
});
}
/********** end **********/
}
}
</script>
<style scoped>
.box {
width: 750px;
height: 650px;
margin: auto;
/* border: 2px solid aquamarine; */
}
</style>
3670

被折叠的 条评论
为什么被折叠?



