历经千辛万苦,终于把这地图给做出来了,但是。。。emm,很丑,有很多需要优化的地方,这个地图一开始一直在antv L7的实例中找,没有找到,经过查找资料,参考这篇博客才顿悟,原来可以获取中国地图的数据,做一个图表,以下是我的思路:
html
<div id='map'></div>
css,g2-tooltip和 g2-tooltip-list是官网复制的样式,是当鼠标滑过是显示的div的样式
<style>
.labelclass {
width: 50px;
height: 50px;
border-radius: 50%;
color: #9c0a0d;
text-align: center;
line-height: 50px;
}
.g2-tooltip{
position: absolute;
visibility: hidden;
border: 1px solid #efefef;
background-color: white;
color: #000;
opacity: 0.8;
padding: 5px 15px;
transition: top 200ms,left 200ms;
}
.g2-tooltip-list{
margin: 10px;
}
</style>
引入需要的js文件
<script src="jquery-3.4.1.min.js"></script>
<script src="https://gw.alipayobjects.com/os/lib/antv/g2/3.4.10/dist/g2.min.js"></script>
<script src="https://unpkg.com/@antv/data-set"></script>
为了避免回调地狱混乱思路,我封装了promise类型的ajax
function $get(url) {
return new Promise((resolve, rejected) => {
$.get(url, res => {
resolve(res)
})
})
}
封装getColor函数,判断数据的区域得到不同的颜色
function getColor(v) {
const trend = ['#ffefd7', '#ffd2a0', '#fe8664', '#e64b47', '#c91014', '#9c0a0d',];
return v > 9999
? trend[5]
: v > 999
? trend[4]
: v > 499
? trend[3]
: v > 99
? trend[2]
: v > 9
? trend[1]
: trend[0];
}
先来做地图的框架
let mapData = await $get('https://geo.datav.aliyun.com/areas/bound/100000_full.json')
var chart = new G2.Chart({
container: 'map',
height: 1000,
width: 1000,
padding: [55, 20]
});
chart.scale({
//sync:当 chart 存在不同数据源的 view 时,用于统一相同数据属性的值域范围
//nice:默认为 true,用于优化数值范围,使绘制的坐标轴刻度线均匀分布。例如原始数据的范围为 [3, 97],如果 nice 为 true,那么就会将数值范围调整为 [0, 100]
x: { sync: true, nice: false },
y: { sync: true, nice: false }
})
//chart.coord().reflect('' | 'x' | 'y'): 坐标系转置,将 x 或者 y 的起始、结束值倒置。
chart.coord().reflect();
chart.axis(false);
//处理数据
var ds = new DataSet();
// createView创建并返回一个数据视图实例
var dv = ds.createView('back')
.source(mapData, {
type: 'GeoJSON'
})
.transform({
//geo.projection 地理映射
type: 'geo.projection',
projection: 'geoMercator',
as: ['x', 'y', 'centroidX', 'centroidY']
});
//绘制地图
var bgView = chart.view();
bgView.source(dv);
bgView.polygon()
.position('x*y')
.style({
fill: '#000088',//地图颜色
stroke: '#b1b1b1',//界线颜色
lineWidth: 0.5,//线粗细
fillOpacity: 1
})
好了,地图框架出来了
接下来要将疫情数据导出到图表上,我是从网站上得到的数据,所以还要进行处理
let res = await $get('http://lovebridge.migu.cn:18188/api/map?url=http:%2F%2Fgarnetcdn.migu.cn%2Flovebridge.html')
res = res.data.country[0].province//处理数据,得到一个数组
将疫情数据和地图串联起来,只能通过地名,但是疫情书籍里地名没有显示市、省,所以我用了find和slice方法,找到对应的对象,处理我需要的数据
//处理疫情数据,显示数据
var userData = ds.createView().source(res)
userData.transform({
//数据转换,type相当于数组转换的方法
type: 'map',
//由于我从网上获得的数据中市省都去掉了,所以我通过查找匹配前两个字符一样的得到经纬度
callback: function (obj, index) {
let one = dv.rows.find(item => { return item.name.slice(0, 2) === obj.na.slice(0, 2) })
obj.x = one.centroidX * 1;
obj.y = one.centroidY * 1;
obj.data = parseInt(obj.tn.split(',')[0])
one.data = obj.data
return obj;
}
});
//如下是数据显示及样式
var pointView = chart.view();
pointView.source(userData);
pointView.intervalStack()
.position('x*y').label('na', {
offset: -5,
textStyle: {
fontSize: 10,
fill: '#000',
},
formatter: (text, item) => {
const d = item.point;
return d.na + '\n' + d.data;
}
})
需要按确诊人数的数量来让不同区域显示相应的颜色,我前面已经将数据存在userData上了
bgView.polygon().position('x*y').color('data', getColor)//传入回调函数,使不同的数据显示不一样的背景颜色
当鼠标划过时,显示相应的数据,只有chart有tooltip方法
chart.tooltip({
showTitle: false, // 默认标题不显示
containerTpl:
`<div class="g2-tooltip"><ul class="g2-tooltip-list"></ul>
</div>`,
itemTpl: '<li >确诊{value}例</li>'
})
取消动画,将图表渲染至画布
chart.animate(false)
chart.render();
成品
下面是总的js代码
function $get(url) {
return new Promise((resolve, rejected) => {
$.get(url, res => {
resolve(res)
})
})
}
function getColor(v) {
const trend = ['#ffefd7', '#ffd2a0', '#fe8664', '#e64b47', '#c91014', '#9c0a0d',];
return v > 9999
? trend[5]
: v > 999
? trend[4]
: v > 499
? trend[3]
: v > 99
? trend[2]
: v > 9
? trend[1]
: trend[0];
}
async function aa() {
let mapData = await $get('https://geo.datav.aliyun.com/areas/bound/100000_full.json')
var chart = new G2.Chart({
container: 'map',
// forceFit: true,
height: 1000,
width: 1000,
padding: [55, 20]
});
// // force sync scales
chart.scale({
//sync:当 chart 存在不同数据源的 view 时,用于统一相同数据属性的值域范围
//nice:默认为 true,用于优化数值范围,使绘制的坐标轴刻度线均匀分布。例如原始数据的范围为 [3, 97],如果 nice 为 true,那么就会将数值范围调整为 [0, 100]
x: { sync: true, nice: false },
y: { sync: true, nice: false }
})
//chart.coord().reflect('' | 'x' | 'y'): 坐标系转置,将 x 或者 y 的起始、结束值倒置。
chart.coord().reflect();
chart.axis(false);
//处理数据,绘制地图
var ds = new DataSet();
// createView创建并返回一个数据视图实例
var dv = ds.createView('back')
.source(mapData, {
type: 'GeoJSON'
})
.transform({
//geo.projection 地理映射
type: 'geo.projection',
projection: 'geoMercator',
as: ['x', 'y', 'centroidX', 'centroidY']
});
var bgView = chart.view();
bgView.source(dv);
bgView.polygon()
.position('x*y')
.style({
fill: '#000088',//地图颜色
stroke: '#b1b1b1',//界线颜色
lineWidth: 0.5,//线粗细
fillOpacity: 1
})
.color('data', getColor)//传入回调函数,使不同的数据显示不一样的背景颜色
let res = await $get('http://lovebridge.migu.cn:18188/api/map?url=http:%2F%2Fgarnetcdn.migu.cn%2Flovebridge.html')
res = res.data.country[0].province//处理数据,得到一个数组
//处理疫情数据,显示数据
var userData = ds.createView().source(res)
userData.transform({
//数据转换,type相当于数组转换的方法
type: 'map',
//由于我从网上获得的数据中市省都去掉了,所以我通过查找匹配前两个字符一样的得到经纬度
callback: function (obj, index) {
let one = dv.rows.find(item => { return item.name.slice(0, 2) === obj.na.slice(0, 2) })
obj.x = one.centroidX * 1;
obj.y = one.centroidY * 1;
obj.data = parseInt(obj.tn.split(',')[0])
one.data = obj.data
return obj;
}
});
//如下是数据显示及样式
var pointView = chart.view();
pointView.source(userData);
pointView.intervalStack()
.position('x*y').label('na', {
offset: -5,
textStyle: {
fontSize: 10,
fill: '#000',
},
formatter: (text, item) => {
const d = item.point;
return d.na + '\n' + d.data;
}
})
//图例显示在右边
chart.legend('data', {
position: 'right',
})
//当鼠标划过时,显示相应的数据,只有chart有tooltip方法
chart.tooltip({
showTitle: false, // 默认标题不显示
containerTpl:
`<div class="g2-tooltip"><ul class="g2-tooltip-list"></ul>
</div>`,
itemTpl: '<li >确诊{value}例</li>'
})
chart.animate(false)
chart.render();
}
aa()