- 获取echarts
npm install echarts --save
- 引入echarts
import * as echarts from 'echarts';
- 基于准备好的dom,初始化echarts实例
this.myChart = echarts.init(document.getElementById('main'))
- 注册地图。echarts中注册地图只在 geo 组件或者 map 图表类型中使用,可以选择SVG 格式或者GeoJson格式(编码各种地理数据结构的格式,用来作为地图的轮廓)的数据。这个可以按需选择,该项目使用的GeoJson格式。
提供一个可以获取到国内各区域地理数据的网站:http://datav.aliyun.com/portal/school/atlas/area_selector#&lat=31.769817845138945&lng=104.29901249999999&zoom=4
var geoJson = require('../utils/310106.json')
echarts.registerMap('JINGAN', geoJson);
- 配置飞线和删除撒点按钮
本demo中地图状态分为展示状态、配置状态,通过代码中的isConfig控制。在展示状态中,展示撒好的点以及点到点之间飞线。在配置状态,可以撒点以及删除撒点。
飞线使用eacharts中的路径图系列,用于带有起点和终点信息的线数据的绘制,主要用于地图上的航线,路线的可视化。在这里可以帮助我们实现点到点的飞线效果
// 飞线配置
var lineSeries = {
type:'lines',
name: 'line',
coordinateSystem:'geo',
zlevel: 15,
effect: {
show: true,
period: 5,
trailLength: 0.3,
symbol: 'circle',
color:'#e4dfa9',symbolSize: 5,
},
lineStyle: {
normal: {width: 1.2, opacity: 0.6, curveness: 0.2, color: '#FFB800'}
},
data: []
}
配置删除撒点按钮。这里使用的是eachrts的custom自定义系列,可以自定义系列中的图形元素渲染,从而能扩展出不同的图表
var closeSeries = {
type: 'custom',
id: 'close',
name: 'close',
coordinateSystem: 'geo',
selectedMode: 'single',
datasetIndex: 2,
renderItem: function (params, api) {
return {
type: 'group',
children: [
{
type: 'rect',
invisible: true,
textContent: {
style: {
text: 'X',
font: '1.5em',
fill: '#fff',
x: api.coord([parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].longitude : self.education[0].longitude), parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].latitude : self.education[0].latitude)])[0] + 20,
y: api.coord([parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].longitude : self.education[0].longitude), parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].latitude : self.education[0].latitude)])[1] - 50
}
},
fill: 'rtgba(65,105,225, 1)',
style: {
fill: '#FFC0CB',
x: api.coord([parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].longitude : self.education[0].longitude), parseFloat(self.data[params.dataIndex] ?self.data[params.dataIndex].latitude : self.education[0].latitude)])[0] - 0,
y: api.coord([parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].longitude : self.education[0].longitude), parseFloat(self.data[params.dataIndex] ? self.data[params.dataIndex].latitude : self.education[0].latitude)])[1] - 0,
},
z: 3
}
]}
}
}
- 设置地图配置并绘制。
点位也是用custom系列,主要由三部分组成,区域个数(文字)、点位图片(图片)以及点位名称(文字)。custom 系列需要开发者自己提供图形渲染的逻辑,这个渲染逻辑一般命名为 renderItem,renderItem 函数须返回根据此 dataItem 绘制出的图形元素的定义信息,图形元素可以是图片、文字、图形等等。而group 是唯一的可以有子节点的容器,可以用来整体定位一组图形元素,能满足我们点位元素组成的需求。
this.myChart.setOption({
geo: [{
// 引用注册过的底图
map: 'JINGAN',
zoom: 1,
top: 50,
id: 'jingan',
itemStyle: {
areaColor: self.isConfig
? {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(2,116,159,0.45)'
}, {
offset: 0.2, color: 'rgba(0,140,168,0.24)'
}, {
offset: 0.4, color: 'rgba(0,91,155,0.11)'
},{
offset: 0.6, color: 'rgba(0,129,158,0.28)'
},{
offset: 0.8, color: 'rgba(0,141,159,0.49)'
},{
offset: 1, color: 'rgb(2,147,156,0.45)'
}],
global: false
}
: 'rgba(255,255,255,0)'
},
emphasis: {
itemStyle: {
areaColor: self.isConfig
? {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(2,116,159,0.45)'
}, {
offset: 0.2, color: 'rgba(0,140,168,0.24)'
}, {
offset: 0.4, color: 'rgba(0,91,155,0.11)'
},{
offset: 0.6, color: 'rgba(0,129,158,0.28)'
},{
offset: 0.8, color: 'rgba(0,141,159,0.49)'
},{
offset: 1, color: 'rgb(2,147,156,0.45)'
}],
global: false
}
: 'rgba(255,255,255,0)'
},
label: {
show: false
}
},
backgroundColor: 'rgba(255, 255, 255, 0)'
}],
dataset: [
{
source: []
},
{
source: []
},
{
source: []
},
{
source: []
}],
series: [
{
type: 'custom',
name: 'area',
coordinateSystem: 'geo',
selectedMode: 'single',
datasetIndex: 0,
// geoIndex: 0,
renderItem: function (params, api) {
return {
type: 'group',
children: [
{
type: 'image',
style: {
image: icon,
x: api.coord([parseFloat(self.data[params.dataIndex].longitude), parseFloat(self.data[params.dataIndex].latitude)])[0] - 54,
y: api.coord([parseFloat(self.data[params.dataIndex].longitude), parseFloat(self.data[params.dataIndex].latitude)])[1] -54
}
},
{
type: 'text',
style: {
text: self.data[params.dataIndex].orgName,
fill: 'rgba(255, 255, 255, 0.9)',
x: api.coord([parseFloat(self.data[params.dataIndex].longitude), parseFloat(self.data[params.dataIndex].latitude)])[0] - self.data[params.dataIndex].orgName.length * self.fontSize,
y: api.coord([parseFloat(self.data[params.dataIndex].longitude), parseFloat(self.data[params.dataIndex].latitude)])[1] + 23
}
},
{
type: 'text',
style: {
text: self.data[params.dataIndex].subOrgNum || 0,
fill: 'rgba(255, 255, 255, 0.9)',
x: api.coord([parseFloat(self.data[params.dataIndex].longitude), parseFloat(self.data[params.dataIndex].latitude)])[0] - (self.data[params.dataIndex].subOrgNum || '').toString().length * self.fontSize,
y: api.coord([parseFloat(self.data[params.dataIndex].longitude), parseFloat(self.data[params.dataIndex].latitude)])[1] - 38
}
}
]
}
}
},{
type: 'custom',
id: 'edu',
name: 'edu',
coordinateSystem: 'geo',
datasetIndex: 1,
renderItem: function (params, api) {
return {
type: 'group',
children: [
{
type: 'image',
style: {
image: iconEdu,
x: api.coord([parseFloat(self.education[params.dataIndex].longitude), parseFloat(self.education[params.dataIndex].latitude)])[0] - 46,
y: api.coord([parseFloat(self.education[params.dataIndex].longitude), parseFloat(self.education[params.dataIndex].latitude)])[1] - 60
}
}
]
}
}
}
]
.concat(self.isConfig ? [closeSeries] : [lineSeries])
})
- 拿到后台数据,转化为我们需要的格式后,更新地图。
this.myChart.setOption({
dataset: [
{
source: this.data
},
{
source: this.education
},
{
source: this.data.concat(this.education)
}
],
series:[
{
name: 'area',
datasetIndex: 0
},
{
name: 'edu',
datasetIndex: 1
},
{
name: 'close',
datasetIndex: 2
},
{
name: 'line',
data: line
}]
})
- 获取地图的监听事件,本demo主要用于实现:
1.展示状态,点击点位后,显示点位详情弹框。
2.配置状态,点击地图任意区域,进行撒点功能;点击关闭按钮,删除该点位;
this.myChart.on('click', function(params) {
console.log(params)
let componentType = params.componentType;
if (!self.isConfig) {
if (componentType === 'series' && params.seriesName !== 'edu') {
self.$emit('handleClick', params)
}
} else {
if (componentType === 'geo') {
let offsetX = params.event.offsetX;
let offsetY = params.event.offsetY;
let lonlat = self.myChart.convertFromPixel('geo', [offsetX, offsetY]); // 转换成坐标
self.$emit('handleClick', {type:'add', data: {}, lonlat:lonlat})
}
if (componentType === 'series') {
if (params.seriesName === 'close') {
self.$emit('close', params)
}
if (params.seriesName === 'area' || params.seriesName === 'edu') {
self.$emit('handleClick', {type:'edit', data: params.data})
}
}
}
})