数据可视化大屏项目开发中,客户要求实现飞线图,但是这个图片的地图并不精确,只是一个大概的效果,只不过客户对动画效果比较执着。自己写飞线图动画又不会,使用echarts来绘制地图的话,又因为数据不准确没办法定位,因为客户对地图数据并不在意,所以这里我们假数据来实现。
绘制echarts
首先我们绘制一个echarts地图来盖在图片上,类似下图,让echarts有足够大的区域可以遮挡在图片上
然后我们使用echarts方法点击echarts地图获取经纬度用来定位圆点,经纬度并非真实需要的经纬度,而是我们需要用来在图片上绘制圆点和飞线需要。
myChart.on('click', function (params) {
that.left = params.event.event.offsetX;
that.top = params.event.event.offsetY;
let data = myChart.convertFromPixel('geo', [that.left, that.top])
console.log(data)
})
获取到经纬度构建飞线和圆点
我们将获取到的坐标用来绘制圆点和飞线
var datamap = {
type: 'scatter',
name: '宁波',
coordinateSystem: 'geo',
symbol: 'image://' + mapTag,
symbolSize: [96, 96],
symbolOffset: [0, 0],
label: {
normal: {
show: true,
position: 'top',
offset: [30, 80],
formatter: function (params) {
console.log(params)
var text = `{name|宁波}`
return text
},
color: '#fff',
rich: {
name: {
padding: [0, 0],
color: '#FEFEFE',
fontSize: 17,
fontWeight: 500,
fontFamily: 'YouSheBiaoTiHei'
},
},
},
},
z: 6,
data: [{
"value": [109.63739894661572, 28.697517162125386],
"id": 0,
"name": '宁波',
"num": 10
}]
}
serverdata.push(datamap)
var fData = []
var geoCoordMap = {
'宁波': [109.63739894661572, 28.697517162125386],
'地址': [87.13306805244875, 47.41702876954609],
'地址2': [89.49858010666516, 40.205413642097135],
'地址3': [76.83989397869624, 38.05727296583574],
'地址4': [83.48890083379104, 30.64107301207617],
'地址5': [118.20438854837246, 33.14723713438113],
}
for (var key in geoCoordMap) {
if (key != '宁波') {
var datamap = {
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'image://' + dot,
symbolSize: [24, 24],
symbolOffset: [0, 0],
label: {
show: false,
},
z: 6,
data: [{
"value": geoCoordMap[key],
"id": 0,
"name": key,
"num": 10
}]
}
serverdata.push(datamap)
}
}
for (var key in geoCoordMap) {
for (var key1 in geoCoordMap) {
if (key1 != key) {
fData.push({
coords: [
geoCoordMap[key1],
geoCoordMap[key],
],
fromName: key1,
toName: key,
})
break
}
}
}
fData.splice(0, 1)
最后将地图设置为透明
飞线和圆点都绘制好以后,将图片设置为透明,这样一个图片上的飞线图就搞定了。
完整代码
<template>
<div class="centerMap" id="centerMap">
</div>
</template>
<script>
import echarts from "echarts";
import data from './data.json'
import mapTag from './assets/mapicon.png'
import dot from './assets/dot.png'
export default {
name: "item1",
data() {
return {
data,
height: 0,
width: 0,
popShow: false,
left: 0,
top: 0,
address: '',
num: 10,
}
},
components: {},
watch: {},
mounted() {
var that = this;
setTimeout(() => {
this.getMap()
}, 500)
},
methods: {
getMap() {
this.$nextTick(() => {
this.getEcharts()
})
},
getEcharts() {
var that = this;
var chartDom = document.getElementById('centerMap');
var myChart = echarts.init(chartDom);
var nameMap = '地图数据';
var serverdata = []
echarts.registerMap(nameMap, this.data);
var mapFeatures = echarts.getMap(nameMap).geoJson.features;
var datamap = {
type: 'scatter',
name: '宁波',
coordinateSystem: 'geo',
symbol: 'image://' + mapTag,
symbolSize: [96, 96],
symbolOffset: [0, 0],
label: {
normal: {
show: true,
position: 'top',
offset: [30, 80],
formatter: function (params) {
console.log(params)
var text = `{name|宁波}`
return text
},
color: '#fff',
rich: {
name: {
padding: [0, 0],
color: '#FEFEFE',
fontSize: 17,
fontWeight: 500,
fontFamily: 'YouSheBiaoTiHei'
},
},
},
},
z: 6,
data: [{
"value": [109.63739894661572, 28.697517162125386],
"id": 0,
"name": '宁波',
"num": 10
}]
}
serverdata.push(datamap)
var fData = []
var geoCoordMap = {
'宁波': [109.63739894661572, 28.697517162125386],
'地址': [87.13306805244875, 47.41702876954609],
'地址2': [89.49858010666516, 40.205413642097135],
'地址3': [76.83989397869624, 38.05727296583574],
'地址4': [83.48890083379104, 30.64107301207617],
'地址5': [118.20438854837246, 33.14723713438113],
}
for (var key in geoCoordMap) {
if (key != '宁波') {
var datamap = {
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'image://' + dot,
symbolSize: [24, 24],
symbolOffset: [0, 0],
label: {
show: false,
},
z: 6,
data: [{
"value": geoCoordMap[key],
"id": 0,
"name": key,
"num": 10
}]
}
serverdata.push(datamap)
}
}
for (var key in geoCoordMap) {
for (var key1 in geoCoordMap) {
if (key1 != key) {
fData.push({
coords: [
geoCoordMap[key],
geoCoordMap[key1],
],
fromName: key,
toName: key1,
})
break
}
}
}
fData.splice(0, 1)
var optionMap = {
geo: {
map: nameMap,
show: true,
aspectScale: 0.8,
layoutCenter: ["50%", "86%"],
layoutSize: '125%',
roam: false,
itemStyle: {
normal: {
borderColor: 'rgba(147, 235, 248, 0)',
borderWidth: 0.5,
areaColor: 'rgba(147, 235, 248, 1)',
opacity: 0,
},
emphasis: {
borderColor: 'rgba(147, 235, 248, 0)',
borderWidth: 0.5,
areaColor: 'rgba(147, 235, 248, 0)',
opacity: 0,
}
},
z: 0,
label: {
normal: {
show: false
},
emphasis: {
show: false
}
}
},
series: [
{
type: 'lines',
zlevel: 10000,
effect: {
show: true,
period: 4, //箭头指向速度,值越小速度越快
trailLength: 0.1, //特效尾迹长度[0,1]值越大,尾迹越长重
symbol: 'arrow', //箭头图标
symbolSize: 4, //图标大小
},
tooltip: {
trigger: 'item',
},
label: {
show: false,
color: '#fff',
emphasis: {
color: 'white',
show: true
}
},
lineStyle: {
normal: {
color: '#ffcd00',
type: 'dashed',
width: 0.5, //尾迹线条宽度
opacity: 0.5, //尾迹线条透明度
curveness: 0.3 //尾迹线条曲直度
}
},
data: fData,
},
...serverdata,
]
};
myChart.setOption(optionMap);
myChart.off('click')
myChart.on('click', function (params) {
console.log(params)
that.left = params.event.event.offsetX;
that.top = params.event.event.offsetY;
that.popShow = false
that.$nextTick(() => {
that.popShow = true
})
that.address = params.name
let data = myChart.convertFromPixel('geo', [that.left, that.top])
console.log(data)
})
const viewElem = document.body;
const resizeObserver = new ResizeObserver(() => {
console.log('变化')
// 此处放 当窗口大小发生变化时,想要让宽高自适应的图表的.resize(),除此处外其余都是固定写法,举例如下
if (myChart) {
setTimeout(() => {
myChart.resize();
}, 300)
}
});
resizeObserver.observe(viewElem);
}
},
}
</script>
<style lang="scss" scoped>
.centerMap {
width: 100%;
height: 100%;
position: absolute;
z-index: 1;
top: 0;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
}
</style>