复制
| import * as echarts from '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}) |
| } |
| } |
| } |
| }) |
复制