数据可视化大屏项目要求渲染中国地图,并且点击地图后可以下钻到对应的省市地图,这里我们通过高德地图查询地图数据,通过echarts渲染地图效果实例.
引入高德地图api
渲染步骤
1.使用 ECharts 的地图组件,将地图的 JSON 数据转换成 ECharts 可以识别的格式,加载到页面上。
2.为地图添加点击事件,在点击某个区域时触发,获取该区域的 ID 或其他需要展示的信息。
3.根据获取到的信息,动态生成需要展示的图表或数据,并将其添加到页面上。
4.可以使用 ECharts 的“返回”按钮,实现从下钻页面返回到上一级页面的功能。
5.需要注意的是,ECharts 的地图组件和高德地图 API 使用的坐标系不一样,需要进行坐标系的转换。
渲染地图效果截图
![中国地图](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)
下钻后地图
![下钻后地图](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E)
完整代码
返回
返回
import * as echarts from "echarts"
import prevIcon from '../../assets/icon_leftjt.png'
import nextIcon from '../../assets/icon_rightjt.png'
import {GetRandomNum} from "../../utils/utils";
export default {
name: 'echarts1',
components: {},
data() {
return {
geoJson: {},
parentInfo: [{cityName: '全国', code: 100000}],
currentIndex: 0,
myChart: null,
//监听时间切换事件
timeTitle: ['5日', '6日', '7日', '8日', '9日'],
north: [
{name: '山东', total: 46.76, l: 17.23, z: 10.87, g: 10.58, x: 8.08},
{name: '河南', total: 41.33, l: 11.32, z: 10.38, g: 11.17, x: 8.45},
{name: '辽宁', total: 39.25, l: 6.95, z: 14.92, g: 7.70, x: 9.68},
{name: '河北', total: 41.69, l: 8.28, z: 13.12, g: 10.88, x: 9.41},
{name: '北京', total: 49.64, l: 15.91, z: 15.97, g: 8.24, x: 9.53},
{name: '山西', total: 42.76, l: 14.76, z: 9.64, g: 9.97, x: 8.39},
{name: '吉林', total: 40.28, l: 13.10, z: 8.51, g: 10.06, x: 8.60},
{name: '内蒙古', total: 50.20, l: 15.12, z: 14.74, g: 12.52, x: 7.82},
{name: '黑龙江', total: 52, l: 10.15, z: 12.03, g: 6.45, x: 6.30},
{name: '天津', total: 59.23, l: 17.14, z: 19.12, g: 13.86, x: 9.11},
],
south: [
{name: '广东', total: 47.21, l: 14.71, z: 14.61, g: 8.66, x: 9.25},
{name: '浙江', total: 40.24, l: 11.48, z: 11.14, g: 8.63, x: 8.98},
{name: '江苏', total: 45.76, l: 13.57, z: 10.60, g: 10.19, x: 11.40},
{name: '重庆', total: 50.94, l: 16.11, z: 13.24, g: 9.35, x: 12.24},
{name: '湖南', total: 47.65, l: 13.64, z: 14.51, g: 10.69, x: 8.81},
{name: '上海', total: 49.63, l: 15.21, z: 12.68, g: 11.19, x: 10.55},
{name: '四川', total: 42.39, l: 11.54, z: 12.09, g: 11.08, x: 7.69},
{name: '新疆', total: 39.37, l: 14.21, z: 15.94, g: 8.60, x: 8.02},
{name: '福建', total: 42.20, l: 14.10, z: 9.99, g: 8.62, x: 9.48},
{name: '湖北', total: 51.27, l: 16.02, z: 14.04, g: 12.52, x: 8.69},
{name: '贵州', total: 48.79, l: 14.07, z: 13.91, g: 11.36, x: 9.44},
{name: '安徽', total: 46.71, l: 13.17, z: 15.37, g: 11.13, x: 7.03},
{name: '陕西', total: 41.30, l: 13.94, z: 12.88, g: 9.64, x: 4.84},
{name: '广西', total: 46.62, l: 12.13, z: 14.59, g: 10.12, x: 9.79},
{name: '宁夏', total: 53.85, l: 14.07, z: 13.81, g: 13.13, x: 12.83},
{name: '青海', total: 51.06, l: 17.24, z: 12.26, g: 8.91, x: 12.65},
{name: '西藏', total: 39.37, l: 9.13, z: 11.75, g: 7.43, x: 11.05},
{name: '云南', total: 26.48, l: 5.26, z: 11.26, g: 6.61, x: 3.35},
{name: '海南', total: 52.51, l: 15.71, z: 16.91, g: 10.97, x: 8.91},
{name: '甘肃', total: 40.50, l: 11.05, z: 11.75, g: 10.49, x: 7.22},
{name: '江西', total: 39.84, l: 10.27, z: 11.72, g: 8.95, x: 8.90},
],
allObj: {},
southObj: {},
northObj: {},
}
},
watch: {},
mounted() {
var that = this;
that.north.forEach(i => {
that.northObj[i.name] = i;
})
that.south.forEach(i => {
that.southObj[i.name] = i;
})
that.allObj = {...that.northObj, ...that.southObj};
var viewIndex = 0;
var isOverview = [0].indexOf(viewIndex) > -1;
that.myChart = echarts.init(this.$refs.echarts);
window.onresize = function () {
that.myChart && that.myChart.resize();
}
that.$store.commit('isOverview', isOverview);
that.init(100000)
},
methods: {
init(adcode) {
var that = this;
that.getGeoJson(adcode).then(data => {
that.geoJson = data
that.getMapData()
})
},
//这里封装了,直接可以拿过来用
getGeoJson(adcode, childAdcode = '') {
var that = this;
return new Promise((resolve, reject) => {
function insideFun(adcode, childAdcode) {
AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {
var districtExplorer = new DistrictExplorer();
districtExplorer.loadAreaNode(adcode, function (error, areaNode) {
if (error) {
console.error(error);
reject(error);
return;
}
let Json = areaNode.getSubFeatures();
if (Json.length === 0) {
let parent = areaNode._data.geoData.parent.properties.acroutes;
insideFun(parent[parent.length - 1], adcode);
return;
}
if (childAdcode) {
Json = Json.filter(item => {
return item.properties.adcode == childAdcode;
});
}
let mapJson = {
features: Json
};
resolve(mapJson);
});
});
}
insideFun(adcode, childAdcode);
});
},
//获取数据
getMapData() {
var that = this;
let mapData = [],
pointData = [],
sum = 0
that.geoJson.features.forEach(item => {
let value = Math.random() * 100
let d = that.allObj[item.properties.name.replace(/(省|市|自治区|回族|维吾尔|壮族|特别行政区)/g, '')];
mapData.push({
name: item.properties.name,
value: d?.total || GetRandomNum(40, 50),
l: d?.l || GetRandomNum(40, 50),
z: d?.z || GetRandomNum(40, 50),
g: d?.g || GetRandomNum(40, 50),
x: d?.x || GetRandomNum(40, 50),
cityCode: item.properties.adcode
})
pointData.push({
name: item.properties.name,
value: [item.properties.center[0], item.properties.center[1], value.toFixed(0)],
cityCode: item.properties.adcode,
ranking: 0
})
sum += value
})
mapData = mapData.sort(function (a, b) {
return b.value - a.value
});
that.$store.commit('mapData', mapData);
that.initEchartMap(mapData, sum, pointData)
},
//渲染echarts
initEchartMap(mapData, sum, pointData) {
var that = this;
var labels = [],
values = [],
l = [],
z = [],
g = [],
x = [],
southLabels = [],
southValues = [],
southL = [],
southZ = [],
southG = [],
southX = [];
var min = mapData[mapData.length - 1].value
var max = mapData[0].value
if (mapData.length === 1) {
min = 0
}
mapData.forEach((c, i) => {
c.ranking = i + 1;
var name = c.name.replace(/(省|市|自治区|回族|维吾尔|壮族|特别行政区)/g, '')
if (that.isOverview) {
labels.unshift(name);
values.unshift(c.value);
l.unshift(c.l);
z.unshift(c.z);
g.unshift(c.g);
x.unshift(c.x);
} else {
if (that.northObj[name] !== undefined) {
labels.unshift(name);
values.unshift(c.value);
l.unshift(c.l);
z.unshift(c.z);
g.unshift(c.g);
x.unshift(c.x);
} else if (that.southObj[name] !== undefined) {
southLabels.unshift(name);
southValues.unshift(c.value);
southL.unshift(c.l);
southZ.unshift(c.z);
southG.unshift(c.g);
southX.unshift(c.x);
}
}
})
mapData.forEach((type) => {
pointData.forEach((type2) => {
if (type2.name == type.name) {
type2.ranking = type.ranking
}
});
});
//这里做个切换,全国的时候才显示南海诸岛 只有当注册的名字为china的时候才会显示南海诸岛
echarts.registerMap(that.parentInfo.length === 1 ? 'china' : 'map', that.geoJson);
var option = {
// 正下方时间自动轮播
timeline: {
data: that.timeTitle,
axisType: 'category',
autoPlay: true,
playInterval: 5000,
left: '10%',
right: '10%',
bottom: '2%',
width: '60%',
label: {
normal: {
textStyle: {
color: 'rgba(51, 51, 51, 1)'
}
},
emphasis: {
textStyle: {
color: '#fff'
}
}
},
currentIndex: that.currentIndex,
symbolSize: 10,
lineStyle: {
color: '#e7e7e7',
width: 10,
},
itemStyle: {
color: '#fff',
borderWidth: 2,
borderColor: '#e7e7e7'
},
progress: {
lineStyle: {
color: '#e54949'
},
itemStyle: {
color: '#fff'
}
},
checkpointStyle: {
borderColor: '#eb595a',
color: '#eb595a',
borderWidth: 2,
},
controlStyle: {
showNextBtn: true,
showPrevBtn: true,
prevIcon: 'image://' + prevIcon,
nextIcon: 'image://' + nextIcon,
normal: {
color: 'rgba(218, 46, 46, 1)',
borderColor: 'rgba(218, 46, 46, 1)'
},
emphasis: {
color: '#ed5d5d',
borderColor: '#ed5d5d'
}
},
},
baseOption: {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'none'// 默认为直线,可选为:'line' | 'shadow'
},
formatter: p => {
let content = '' + p[0]?.name.replace(/(省|市|自治区|回族|维吾尔|壮族|特别行政区)/g, '') + '';
p.forEach(i => {
let val = i.value;
if (window.isNaN(val)) {
val = 0;
}
content += `
``{i.marker}``{i.seriesName}:${val}分
`
})
return content;
}
},
toolbox: {
feature: {
restore: {
show: false
},
dataView: {
show: false
},
saveAsImage: {
show: false,
name: that.parentInfo[that.parentInfo.length - 1].cityName + '销售额统计图'
},
// dataZoom: {
// show: false
// },
magicType: {
show: false
}
},
iconStyle: {
normal: {
borderColor: '#e74e4d' //右上角下载的颜色
}
},
top: 15,
right: 35
},
geo: {
map: that.parentInfo.length === 1 ? 'china' : 'map',
zoom: 1,
roam: false,
aspectScale: 0.7,
left: 'center',
layoutSize: that.parentInfo.length === 1 ? 800 : 600,
layoutCenter: that.parentInfo.length === 1 ? ['50%', '63%'] : ['50%', '50%'],
tooltip: {
trigger: 'item',
formatter: (p) => {
let val = p.value[2];
if (window.isNaN(val)) {
val = 0;
}
let txtCon = "" + p.name + ":单数:" + val.toFixed(2) + "单销售额:" + val.toFixed(2) + '万';
return txtCon;
}
},
label: {
normal: {
show: false,
color: "#f9f9f9", //省份标签字体颜色
formatter: p => {
switch (p.name) {
case '内蒙古自治区':
p.name = "内蒙古"
break;
case '西藏自治区':
p.name = "西藏"
break;
case '新疆维吾尔自治区':
p.name = "新疆"
break;
case '宁夏回族自治区':
p.name = "宁夏"
break;
case '广西壮族自治区':
p.name = "广西"
break;
case '香港特别行政区':
p.name = "香港"
break;
case '澳门特别行政区':
p.name = "澳门"
break;
}
return p.name;
}
},
emphasis: {
show: true,
color: '#f75a00',
}
},
itemStyle: {
normal: {
areaColor: '#eece7c',
borderColor: '#feffff',
borderWidth: 2,
},
emphasis: {
areaColor: '#8dd7fc',
borderWidth: 1.6,
shadowBlur: 0,
}
},
},
visualMap: { //右下角
min: min,
max: max,
left: '3%',
bottom: '5%',
calculable: true,
seriesIndex: [0],
inRange: {
color: [
'#ff9601',
'#f58770',
'#eece7c',
'#94d5bc',
'#44e8ac'
].reverse()
},
textStyle: {
color: 'rgba(51, 51, 51, 1)'
}
},
series: [
{ //最外层鼠标经过显示的黑框
name: that.timeTitle[that.currentIndex] + '年销售额度',
type: 'map',
geoIndex: 0,
map: that.parentInfo.length === 1 ? 'china' : 'map',
roam: false,
zoom: 2,
aspectScale: 0.7,
left: 'center',
layoutSize: that.parentInfo.length === 1 ? 800 : 600,
layoutCenter: that.parentInfo.length === 1 ? ['50%', '63%'] : ['50%', '50%'],
itemStyle: {
normal: {
// shadowColor: '#013C62',
shadowBlur: 0,
shadowOffsetX: 0,
shadowOffsetY: 0,
}
},
tooltip: {
trigger: "item",
formatter: (p) => {
console.log(p)
console.log(32323223)
let val = p.value;
if (p.name == '南海诸岛') return
if (window.isNaN(val)) {
val = 0;
}
let txtCon = `${p.name.replace(/(省|市|自治区|回族|维吾尔|壮族|特别行政区)/g, '')}
分数:${val}分
排名:${p.data.ranking}名 `;
return txtCon;
}
},
label: {
normal: {
formatter: function (data) {
return '4';
},
show: false,
position: 'right',
distance: 5,
color: 'white',
backgroundColor: '#1D3039',
padding: 10,
borderRadius: 20
// show: false,
},
emphasis: {
show: false,
}
},
data: mapData,
},
{ //最外层鼠标经过显示的黑框
name: that.timeTitle[that.currentIndex] + '年销售额度',
type: 'map',
map: that.parentInfo.length === 1 ? 'china' : 'map',
roam: false,
zoom: 1,
z: -10,
aspectScale: 0.7,
left: 'center',
layoutSize: that.parentInfo.length === 1 ? 800 : 600,
layoutCenter: that.parentInfo.length === 1 ? ['50%', '63%'] : ['50%', '50%'],
itemStyle: {
normal: {
shadowColor: '#888',
shadowBlur: 25,
shadowOffsetX: 0,
shadowOffsetY: 0,
}
},
},
{
name: '散点',
type: 'effectScatter',
coordinateSystem: 'geo',
itemStyle: {
normal: {
color: 'rgba(140, 55, 55, 0)',
shadowColor: "red",
shadowBlur: 20,
shadowOffsetX: -5,
shadowOffsetY: 15,
}
},
label: {
normal: {
show: true,
formatter: function (params) {
console.log(params)
console.log(212121212121)
if (params.data.ranking < 4) {
return '{num|' + params.data.ranking + '}\n{title|' + params.name.replace(/(省|市|自治区|回族|维吾尔|壮族|特别行政区)/g, '') + '}'
} else {
return '{num2|' + params.data.ranking + '}\n{title|' + params.name.replace(/(省|市|自治区|回族|维吾尔|壮族|特别行政区)/g, '') + '}'
}
},
position: 'top',
padding: [0, 0],
offset: [0, 30],
color: '#00BCFF',
rich: {
num: {
width: 30,
height: 30,
align: 'center',
borderColor: '#fff',
backgroundColor: '#ffcd00',
borderWidth: 2,
color: '#ffffff',
borderRadius: 30
},
num2: {
width: 30,
height: 30,
align: 'center',
backgroundColor: 'rgba(176,92,92,1)',
color: '#ffffff',
borderRadius: 30
},
title: {
padding: [5, 0, 0, 0],
color: '#333',
align: 'center'
}
}
},
emphasis: {
show: true
}
},
data: pointData
}
]
},
}
that.myChart.setOption(option, true)
//点击前解绑,防止点击事件触发多次
that.myChart.off('click');
that.myChart.on('click', that.echartsMapClick);
//监听时间切换事件
that.myChart.off('timelinechanged');
that.myChart.on('timelinechanged', params => {
console.log('触发')
that.currentIndex = params.currentIndex;
that.getMapData();
});
},
//echarts点击事件
echartsMapClick(params) {
var that = this;
if (!params.data) {
return
} else {
//如果当前是最后一级,那就直接return
if (that.parentInfo[that.parentInfo.length - 1].code == params.data.cityCode) {
return
}
let data = params.data
that.parentInfo.push({
cityName: data.name,
code: data.cityCode
})
that.init(data.cityCode)
}
},
goBack() {
var that = this;
if (that.parentInfo.length === 1) {
return;
}
that.parentInfo.pop()
that.init(that.parentInfo[that.parentInfo.length - 1].code)
}
}
}
.echarts1 {
position: relative;
width: 100%;
height: 100%;
}
.goback {
position: absolute;
top: 30px;
right: 30px;
font-size: 14px;
font-family: PingFang;
font-weight: 800;
color: #DA2E2E;
z-index: 10000;
}
.disabled {
color: rgba(#DA2E2E, 0.5);
cursor: default;
}
.ecPop {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
p:nth-child(1) {
font-size: 18px;
font-family: PingFang;
font-weight: 800;
color: #333333;
}
p {
font-size: 16px;
font-family: PingFang;
font-weight: bold;
color: #818386;
line-height: 30px;
span {
font-size: 16px;
font-family: PingFang;
font-weight: bold;
color: #DA2E2E;
}
}
}
渲染效果实例
vue2 数据可视化大屏 宽带综合评分
演示demo
喜欢 (0)
|