vue 怎样引echaerts_vue-echarts在绘制区域轮廓地图时的应用

最近在工作项目中遇到一个绘制地图轮廓,并且在地图上根据需求里的学校位置打点,从最初的无从下手到最后完成,中间是边看echarts([echarts官网文档][1])文档边尝试,开了一个好头后面越写越顺利,因此谨以此篇文章记录下我本次学习的过程。

首先上图看效果

qAn2Ej.png

然后说说地图的实现思路:

首先需要绘制出地图轮廓;

请求接口数据,然后在地图上打点;

地图上的学校点击时异步加载学校数据

现在开始说正经的:

第一步:绘制地图轮廓

在绘制地图的准备工作中,需要事先准备好需要绘制的地区的json文件(主要是区域轮廓图的一些重要拐点经纬度,地图就是依靠它一个点一个点连线绘制出来滴),大概长这样:

INJ7Vr.png

然后在代码导入并中注册:

import echarts from 'echarts'

var config = require('../../../../static/mock/conf')

var dingnan = require(`../../../../static/mock/${config.map}`)

echarts.registerMap('dingnan', dingnan)

前两句代码基本上可以合并成一句,其意思是说给这个地图Json起了个名字,引入的时候要对号入座(还有其他地域地图)。。。

这一步完成之后,相当于地图已经注册了,但是需要一个载体来呈现它,这时候echarts就出场了:

eY3Ena.png

各种数据初始化准备:

mYnmyu.png

另外我封装了一个方法makeMapOption用来装载echarts图表所需的各种参数(主要为了方便后面接口请求数据后传到这个方法中地图打点):

U7v6rm.png

当程序解析到

mounted() {

this.mapChart = this.$refs.map.chart

this.mapOption = makeMapOption()

},

的时候,地图轮廓已经加载出来了:

aAF7ri.png

第二步:地图打点

这里就需要异步请求接口了,根据后台返回的数据看看该在哪里打点,打点最重要的两个参数就是经度和纬度啦,接口返回的数据大概长这样:

uEjQre.png

这个latitude和longitude就是每个学校的经纬度了,而schoolCode则是我们在第三步需要用到的重要参数,接下来就是拿着这些数据封装成我们地图中所需要的结构:

NjYNjy.png

mAJzYz.png

分别是打点的学校的名字,学校id,经纬度,学校类别…

之后传到刚才说的方法中去,echaerts图表参数主要部分series中其中一个项大概就是这样滴(这个截图对应的是文章开头第一张图中的黄色点学校,该地区高中中职在我们系统中的就这两…,同理小学初中,完全中学,教育局也是一样滴,不同就是经纬度和颜色啦,看到这里如果懵了的话,不要捉急,代码被我截图拆的四零八散,最后我会附上完整代码滴~~~~):

eiArAr.png

到这地图打点算是完成了,效果就是图一的样子,但是只有地图和点,没有其他信息,看官也不知道这些点到底是干嘛滴不是吗,所以再看

第三步:异步获取地图上某个点的信息

其实本来是很简单的一个echarts图表中的tooltip,就是像echarts官网中的许多例子一样,鼠标放上去出现一个小tips,有什么系统名啊,本item的值啊,百分比啊云云,but我们的需求不按常理出牌啊,tips上的文字是自定义滴,需要展示的数据还是需要请求滴,一开始我还是不会滴…

qIJRzi.png

就是图上红框框里那个玩意儿~~

于是我又去看了看echarts官网关于formatter链接描述的部分,

buQNNn.png

划重点aaaaaa

第二个参数 ticket 是异步回调标识,配合第三个参数 callback 使用。 第三个参数 callback 是异步回调,在提示框浮层内容是异步获取的时候,可以通过 callback 传入上述的 ticket 和 html 更新提示框浮层内容。

(感谢官网大大)

然后怎么办?–硬着头皮写啊,异步请求啊,连接字符串啊,显示啊,上代码:

tooltip: {

show: true,

triggerOn: 'click',

backgroundColor: 'rgba(10, 17, 64, 0.8)',

formatter(value, ticket, callback) {

let _this = this

fetchSchoolDeatail({ unitCode: value.data.schoolCode }).then(({ data, headers }) => {

let info = data.data

let str = `

${value.name}

${info.bxTypeName}

在册学生${info.studentNum}

在册职工数${info.teacherNum}

今日到校学生数${info.studentArriveSchoolNum}

今日到校职工数${info.teacherArriveSchoolNum}

`

callback(ticket, str)

}).catch(err => {

console.dir(err)

_this.$message.error(err.message || '获取学校信息失败,请稍后再试')

}).finally(() => {

console.log(1)

})

return '加载中...'

}

},

有几点说明:

为了避免鼠标划过地图点就请求接口导致接口卡顿,触发tooltip的方法改成了click,也就是点击一下学校点才会加载学校信息接口数据;

由于接口请求发送到成功返回需要一点时间,刚一点上去可能是空白或者tips没出来,所以点击那一瞬间tips显示的是“加载中…”,这就是最外层的return;

当数据加载完成之后必须要写callback(ticket, str),这是人家formatter回调函数规定滴,ticket异步标识不能改,否则不返回任何东西。

至此呢,整个地图绘制,打点,加载点信息就完成了,下面补充几个我在写代码时的注意项:

绘制图表的点的样式可以是一般的ciecle圆点或者rect方形,也可以自定义,比如我地图中的教育局图表,就是引入了一张图片

const starImg = require('../../../assets/images/secondBg/star.png')

引入以后vue自己转化成了base64的编码,然后我们在需要使用的地方是“image://http://xxx.xxx.xxx/a/b.png”这种格式,我们自己需要加上’image://’这段字符,

icon: `image://${starImg}`

为了方便操作地图上的点,不和页面上其他部分重叠,我设置了地图鼠标缩放和平移漫游(geo坐标系中的roam),也就是鼠标在地图区域内的时候可以拖拽地图移动位置,也可以通过滑轮放大缩小地图面积,有个小瑕疵是有时候拖拽完之后鼠标已经没有左键右键控制了,但是鼠标一挪动,地图还是会跟着走,只有在地图之外的空白处点一下才会丢下拖拽。。。

本地图series中共有4个不同类型的数据组合,有的点经纬度离得近,地图缩小时会看上去重合,这时候就需要设置好每个类型的zlevel值,这是为了给每个类型绘制canvas时分层,不至于累在一起看不到别的点

最后附上我的全部代码

import { allSchools, fetchSchoolDeatail } from '@/services/showView'

import echarts from 'echarts'

var config = require('../../../../static/mock/conf')

var dingnan = require(`../../../../static/mock/${config.map}`)

const starImg = require('../../../assets/images/secondBg/star.png')

echarts.registerMap('dingnan', dingnan)

const makeMapOption = (data) => {

return {

legend: {

show: true,

orient: 'vertical',

left: '22%',

top: '15%',

symbolKeepAspect: false,

itemWidth: 15,

itemHeight: 15,

data: [

{

name: '小学初中',

icon: 'circle',

textStyle: {

color: '#75eef5'

}

},

{

name: '高中中职',

icon: 'circle',

textStyle: {

color: '#f0ea75'

}

},

{

name: '完全中学',

icon: 'circle',

textStyle: {

color: '#887bff'

}

},

{

name: '县教育局',

icon: `image://${starImg}`,

textStyle: {

color: '#da4800'

}

}

]

},

tooltip: {

show: true,

triggerOn: 'click',

backgroundColor: 'rgba(10, 17, 64, 0.8)',

formatter(value, ticket, callback) {

let _this = this

fetchSchoolDeatail({ unitCode: value.data.schoolCode }).then(({ data, headers }) => {

let info = data.data

let str = `

${value.name}

${info.bxTypeName}

在册学生${info.studentNum}

在册职工数${info.teacherNum}

今日到校学生数${info.studentArriveSchoolNum}

今日到校职工数${info.teacherArriveSchoolNum}

`

callback(ticket, str)

}).catch(err => {

console.dir(err)

_this.$message.error(err.message || '获取学校信息失败,请稍后再试')

}).finally(() => {

console.log(1)

})

return '加载中...'

}

},

geo: {

map: 'dingnan',

label: {

emphasis: {

show: false

}

},

roam: true,

itemStyle: {

normal: {

color: 'rgba(43,58,113, 0.2)',

borderColor: '#0c6cd2'

},

emphasis: {

color: 'rgba(43,58,113, 0.2)'

}

}

},

series: [{

name: '县教育局', // 地图中心点

type: 'scatter',

coordinateSystem: 'geo',

zlevel: 10,

symbol: `image://${starImg}`,

data: [{

name: '县教育局',

value: data[3]

}],

symbolSize: [20, 20],

label: {

normal: {

formatter: '{b}',

position: 'top',

show: false

},

emphasis: {

show: false

}

},

itemStyle: {

normal: {

color: '#96edfe'

},

emphasis: {

show: false

}

}

},

{

name: '高中中职',

type: 'effectScatter', // 涟漪

coordinateSystem: 'geo',

zlevel: 2,

rippleEffect: {

brushType: 'stroke',

scale: 3

},

label: {

normal: {

fontSize: 16,

offset: [12, 0],

show: false,

position: 'right',

formatter: '{b}'

},

emphasis: {

show: false

}

},

symbolSize: 12,

itemStyle: {

normal: {

color: '#f0ea75'

}

},

data: data[1]

},

{

name: '小学初中',

type: 'effectScatter', //带有涟漪特效动画的散点

coordinateSystem: 'geo', // 该系统所使用的坐标系,geo地理坐标系

zlevel: 2, // zlevel用于 Canvas 分层

rippleEffect: {

brushType: 'stroke', // 波纹的绘制方式

scale: 3 // 动画中波纹的最大缩放比例

},

label: {

normal: {

fontSize: 16,

offset: [10, 0],

show: false,

position: 'right',

formatter: '{b}'

},

emphasis: {

show: false

}

},

symbolSize: 10, // 标记的大小

itemStyle: { // 图形样式

normal: {

color: '#75eef5'

}

},

data: data[0]

},

{

name: '完全中学',

type: 'effectScatter', // 涟漪

coordinateSystem: 'geo',

zlevel: 2,

rippleEffect: {

brushType: 'stroke',

scale: 3

},

label: {

normal: {

fontSize: 16,

offset: [10, 0],

show: false,

position: 'right',

formatter: '{b}'

},

emphasis: {

show: false

}

},

symbolSize: 8,

itemStyle: {

normal: {

color: '#887bff'

}

},

data: data[2]

}]

}

}

export default {

name: 'dingnan-map',

data() {

return {

mapname: config.mapname,

mapOption: {

series: [

]

},

mapChart: null,

coordData: {

name: '',

coord: [],

id: '',

children: [],

url3D: ''

},

geoCoordMap: {},

noticeList: [],

searchDeviceList: [],

allSecuityList: [],

isPlay: false,

playInt: '',

playCount: 1,

schoolName: ''

}

},

mounted() {

this.mapChart = this.$refs.map.chart

this.mapChart.showLoading({

text: '正在加载',

color: '#25D7FB',

textColor: '#25D7FB',

maskColor: 'rgba(19, 25, 83, 0.4)'

})

allSchools().then(({ data, headers }) => {

// 地图中的学校

if (data.resultCode === 0) {

let map = new Map()

for (let item of data.data) {

this.coordData.children.push({

schoolName: item.schoolName,

schoolId: item.schoolCode,

url3D: '',

coord: [item.longitude, item.latitude],

showColor: item.showColor

})

this.coordData.name = '定南县教体局'

this.coordData.coord = [115.049, 24.759872]

this.coordData.id = '3607280000'

this.coordData.url3D = ''

map.set(item.schoolName, [item.longitude, item.latitude])

}

this.geoCoordMap = map

this.mapOption = makeMapOption([this.convertEffectData(1), this.convertEffectData(2), this.convertEffectData(3), this.coordData.coord])

}

return { data: null }

}).catch(err => {

console.dir(err)

this.$message.error(err.message || '查询失败,请稍后再试')

}).finally(() => {

this.mapChart.hideLoading()

})

},

methods: {

// 涟漪点

convertEffectData(colorType) {

var res = [];

for (var i = 0; i < this.coordData.children.length; i++) {

var dataItem = this.coordData.children[i];

if (dataItem.showColor === colorType) {

res.push({

name: dataItem.schoolName,

value: dataItem.coord,

schoolCode: dataItem.schoolId

});

}

}

return res;

}

}

}

.map-wrapper {

width: 98%;

height: 100%;

position: absolute;

left: 1%;

right: 1%;

margin: auto;

z-index: 1;

}

最后再啰嗦一下,我的地图小点点是一颗颗闪亮的小星星,这个主要设置好散点的颜色,涟漪点的圈圈数量,闪动的时间,就很好看啦,我的代码里都有注释。

第一次写这么多字,有点小鸡冻,分享就这么多了,如果您有幸看到了我的文章,希望能对您遇到的问题有所帮助,与君共勉,fighting!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值