背景
这个月做的项目的统计分析模块需要用到echats,其中包括地图,将网站浏览用户的ip转成可视化地图,只显示中国地图。
但是有很多代理IP是国外的,这个部分ip没办法显示到地图上,于是想到自定义图片、自定义图案、自定义地图。前两种方案可以用Echarts的 graphic 实现,这里采用自定义地图的方式,顺便学习Echarts地图。
查看API
https://echarts.baidu.com/api.html#echarts.registerMap 从官网API可以看出Echarts用的是GeoJson格式的数据,可以去 http://geojson.org/ 生成。
假设已经有一个GeoJson的辽宁省地图,起名为LiaoNingJson,那么注册方法就是:
echarts.registerMap('LiaoNing', LiaoNingJson)注意: 这里的
echarts是全局对象,在 script 标签引入 echarts.js 文件后获得,或者在 AMD 环境中通过 require('echarts') 获得。而不是实例化对象。
如何生成GeoJson数据
1. 进入网址 http://geojson.org/
2. 下载中国地图GeoJson文件
https://github.com/hzhqk/echarts/tree/master/map-geojson
3. 导入文件
导入后如下图
4. 添加、修改、删除自定义区域
选择右侧工具栏,分别是:线段、多边形、矩形、标记。 点击矩形图标,在地图右下角画一个四边形
左键单击画好的区域,会弹出信息框
添加如下信息: "name":"其他" // 名称,用于显示到地图上 "id":100 // 编号 "size":1000 "cp":[128.9999,24.206] // 中心点 "childNum":1 // 子节点数量
5. 保存导出文件
压缩一下代码:http://www.bejson.com/
在VueJs中使用
将json文件放在Vue项目根目录的public目录下
(Vue2.*是static目录)
- 项目名
- node_modules
- public
- map
- china.json
- map
初始化 echarts
将options写在计算属性中
computed: {
opt () {
return {
title: {
text: '地域分布',
x: 'center'
},
tooltip: {},
dataRange: { // 热力图等级
show: true,
orient: 'horizontal',
max: 0,
min: 0,
text: ['高', '低'],
color: ['#5fa0e3', '#c7def5', '#ebf3fc'],
calculable: true,
splitNumber: 0,
seriesIndex: [1]
},
geo: {
map: 'vinseaChina', // 注册时的名称
roam: true, // 可以放大缩小拖拽
label: {
normal: {
show: true, // 是否显示对应地名
textStyle: { // 地名文字颜色
color: 'rgba(0,0,0,.5)'
}
}
},
itemStyle: {
normal: { // 地图边界
borderColor: 'rgba(0, 0, 0, 0.2)',
},
emphasis: { // 鼠标悬浮样式
areaColor: null,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
zoom: 1.2, // 默认缩放大小
scaleLimit: {
min: 1, // 缩小最小等级
max: 4 // 放大最大等级
},
},
series: [
{
type: 'map',
coordinateSystem: 'geo', // 对应上方配置
},
{
name: 'xxxx平台2018年用户访问频次', // 浮动框的标题
type: 'map',
geoIndex: 0, // 使用上方geo属性的配置
data: []
},
],
};
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
获取刚才生成的地图数据
mounted () {
// 自定义地图数据
Artery.ajax.get('/map/china.json').then(vChinaJson => {
echarts.registerMap('vinseaChina', vChinaJson );
this.chart = echarts.init(this.$refs.vMapChart);
this.chart.setOption(this.opt);
// 从后台获取数据
this.requestChartData();
});
},2
3
4
5
6
7
8
9
10
更新数据
methods: {
updateData () {
this.chart.setOption({
dataRange: {
max: this.maxValue
},
series: [
{
name: 'xxxx平台2018年用户访问频次',
data: this.dataList
}
]
});
},
requestChartData () {
const params = {
xxx: xxx,
xx: '0'
};
this.$axois.post(this.$url.statistics,params).then(result => {
this.dataList = result.data;
this.maxValue = result.max;
});
},
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
最终
可以看到右下角多了一个“其他”地区,并且交互形式和地图上省份的交互一样,鼠标悬浮效果也一样。
其他
Echarts自带的地图
自带的地图在 ode_modules\echarts\map\js\china.js 该js最下面一行:
echarts.registerMap('china', {"type":"Feature.........})可以看到registerMap的第二个参数就是地图GeoJson数据,也就是: \node_modules\echarts\map\json\china.json
编码
将该GeoJson数据复制出来并格式化,可以发现“坐标”属性被编码为其他格式。 经过一番查找,找到了代码:\node_modules\echarts\src\coord\geo\parseGeoJson.js
function decode(json) {
if (!json.UTF8Encoding) {
return json;
}
var encodeScale = json.UTF8Scale;
if (encodeScale == null) {
encodeScale = 1024;
}
var features = json.features;
for (var f = 0; f < features.length; f++) {
var feature = features[f];
var geometry = feature.geometry;
var coordinates = geometry.coordinates;
var encodeOffsets = geometry.encodeOffsets;
for (var c = 0; c < coordinates.length; c++) {
var coordinate = coordinates[c];
if (geometry.type === 'Polygon') {
coordinates[c] = decodePolygon(
coordinate,
encodeOffsets[c],
encodeScale
);
}
else if (geometry.type === 'MultiPolygon') {
for (var c2 = 0; c2 < coordinate.length; c2++) {
var polygon = coordinate[c2];
coordinate[c2] = decodePolygon(
polygon,
encodeOffsets[c][c2],
encodeScale
);
}
}
}
}
// Has been decoded
json.UTF8Encoding = false;
return json;
}
function decodePolygon(coordinate, encodeOffsets, encodeScale) {
var result = [];
var prevX = encodeOffsets[0];
var prevY = encodeOffsets[1];
for (var i = 0; i < coordinate.length; i += 2) {
var x = coordinate.charCodeAt(i) - 64;
var y = coordinate.charCodeAt(i + 1) - 64;
// ZigZag decoding
x = (x >> 1) ^ (-(x & 1));
y = (y >> 1) ^ (-(y & 1));
// Delta deocding
x += prevX;
y += prevY;
prevX = x;
prevY = y;
// Dequantize
result.push([x / encodeScale, y / encodeScale]);
}
return result;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66