大数据展示全国各省份信息,绘制地图,并在每个省份上叠加图表。
需要做的就是
1、绘制全国地图(不同省份根据数据的不同而颜色不同)
2、每个省份都需要单独叠加一个图表(饼图)
3、地图缩放、图表的大小跟随比例一起缩放
4、地图拖拽,图表根据一起移动
这里面有一些坑
let obj ={
}
export default {
geo: {
map: 'china',
show: false,
roam: false,
label: {
emphasis: {
show: false
}
},
layoutSize: "100%",
itemStyle: {
normal: {
}
}
},
visualMap: {
min: 0,
max: 1000,
left: 100,
bottom: 45,
showLabel: !0,
backgroundColor:"#fff",
text: ["高", "低"],
pieces: [],
},
series: [
{
type: 'map',
zoom:1.1,
aspectScale: 0.9,
layoutCenter: ["50%", "60%"], //地图位置
layoutSize: "100%",
zlevel: 3,
scaleLimit: {
//滚轮缩放的极限控制
min: 1,
max: 1.5,
},
geo: {
show: true,
map: 'china',
label: {
normal: {
show: false
},
emphasis: {
show: false,
}
},
roam: false,
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#3B5077',
},
emphasis: {
areaColor: '#2B91B7',
}
}
},
roam: true, // 是否开启鼠标缩放和平移漫游
selectedMode: 'false', // 是否允许选中多个区域
emphasis:{
label:{
show:true,
color:'#ffffff',
}
},
label: {
show: true,
color: "#FFFFFF",
fontSize: 12,
},
itemStyle: {
normal: {
areaColor: "#0c3653",
borderColor: "#1cccff",
borderWidth: 2,
},
emphasis: {
areaColor:"rgb(12,76,107)", //鼠标悬停/选中颜色
label: {
show: true,
color: "#fff",
borderColor:"rgb(2,241,177)",
},
},
},
data: [],
},
]
};
<template>
<div class="chart pt-10">
<el-button type="primary" size="mini" @click="options.id=1">模式1</el-button>
<el-button type="primary" size="mini" @click="options.id=11">模式2</el-button>
<div id="mapChart" class="mapChart"></div>
</div>
</template>
<script>
import mapOption from './echarts/map'
import chinaData from '@/assets/china.json'
import liaoningPro from './echarts/liaoning.json'
import shenyangCity from './echarts/shenyang.json'
export default {
data(){
return{
myChart: null,
chinaCode:100000,
curMapName:'china', // 当前地图名
selectedMaps:[
{
name:'china',
code:'100000',
}
],
//地图散点数据
mapDotData:{
input:{
value:{}
},
output:{
value:{
rows:[]
}
}
},
typeIndex:1,
//上一次的缩放层级
lastZoomLevel:0,
// 图例
options:{
id:1
}
}
},
props:{
},
async mounted(){
await this.getMapData('china');
window.addEventListener('resize',this.resizeCharts);
// //这里是做地图下钻 预留一下吧 以后需要直接放开继续写逻辑目前也算是实现了下钻的操作
// this.myChart.on('click', (params) => {
// console.log('空间',params)
// const map = params.name;
// if(map){
// this.curMapName = params.name;
// this.getMapData(map);
// // 为地图标题菜单存入(过滤同一地图多次点击情况)点击地图信息
// let selectedCodes = [];
// this.selectedMaps.forEach( item => selectedCodes.push(item.code));
// if(!selectedCodes.includes(map)){
// this.$set(this.selectedMaps,this.selectedMaps.length,{name: this.curMapName, code: map});
// }
// console.log(selectedCodes)
// }else{
// this.$message({message: '暂无地图数据',type: 'warning',showClose: true});
// }
// });
window.addEventListener("resize", (params)=> {
if(Number(this.options.id)<10){
this.resetDot(this.myChart, params);
}else{
this.resetPie(this.myChart, params);
}
})
},
beforeDestroy() {
window.addEventListener('resize',this.resizeCharts);
},
watch:{
"options.id":{
async handler(v){
if(v){
this.myChart.dispose()
this.getMapData('china')
}
}
},
},
methods:{
// 绘制地图
async drawMapChart(mapName,mapJSON){
if (this.myChart != null && this.myChart != "" && this.myChart != undefined) {
this.myChart.dispose();
}
this.myChart = this.$echarts.init(document.getElementById('mapChart'));
this.$echarts.registerMap(mapName,mapJSON);
let seriesData = this.initMapData(mapJSON)
//然后调用接口查询地图信息
await this.getMapDotData()
let arr = this.mapDotData.output.value.rows
for(var i =0;i<seriesData.length;i++){
arr.forEach((item,index)=>{
if(seriesData[i].name==item.xzqmc){
seriesData[i].value = item.total
}
})
}
mapOption.series[0].map = mapName
mapOption.series[0].data = seriesData
//图例是配置的
mapOption.visualMap.pieces =[{
gt: 100,
color: "#7f1100"
}, {
gte: 60,
lte: 80,
color: "#ff5428"
}, {
gte: 20,
lt: 60,
color: "#ff8c71"
}, {
gt: 0,
lt: 20,
color: "#ffd768"
}],
//先有个地图底图
this.myChart.setOption(mapOption,true);
if(Number(this.options.id)<10){
//然后再叠加图表上去
this.addPieToMap(this.myChart, this.mapDotData.output.value.rows );
}else{
this.addPartPieToMap(this.myChart, this.mapDotData.output.value.rows )
}
/*饼图跟着地图移动:pie*/
this.myChart.on('georoam', (params)=> {
if(Number(this.options.id)<10){
this.resetDot(this.myChart, params);
}else{
this.resetPie(this.myChart, params);
}
});
},
initMapData(mapJson) {
let mapData = [];
for (let i = 0; i < mapJson.features.length; i++) {
mapData.push({ name: mapJson.features[i].properties.name });
}
return mapData;
},
// 浏览器窗口大小改变时,重新加载图表以自适应
resizeCharts(){
this.$echarts.init(document.getElementById('mapChart')).resize()
},
// 获取地图数据
async getMapData(map){
if(map=='china'){
await this.drawMapChart(this.curMapName,chinaData[0]);
}else if(map=='辽宁省'){
this.drawMapChart(this.curMapName,liaoningPro);
}else{
this.drawMapChart(this.curMapName,shenyangCity);
}
},
//接口获取散点数据
async getMapDotData(){
//接口获取数据
let rows = []
if(Number(this.options.id)<10){
rows =[
{
"xzqmc": "四川省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "辽宁省",
"total": 482.99,
"dw": "万亩",
"xzqdm": "540000"
},
{
"xzqmc": "湖南省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "湖北省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "贵州省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "云南省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "青海省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "陕西省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "山西省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "新疆维吾尔自治区",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "西藏自治区",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "宁夏回族自治区",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "甘肃省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "河南省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "安徽省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "山东省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "江苏省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "江西省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
{
"xzqmc": "福建省",
"total": 9088.51,
"dw": "万亩",
"xzqdm": "510000"
},
]
}else{
rows=[
{
"xzqmc":"辽宁省",
"xzqdm":"xxx",
"total":5.3,
"rows":[
{
"name":"五等地",
"value":"26",
},
{
"name":"一等地",
"value":"12",
},
{
"name":"四等地",
"value":"45",
},
{
"name":"三等地",
"value":"5",
},
]
},
{
"xzqmc":"四川省",
"xzqdm":"xxx",
"total":5.3,
"rows":[
{
"name":"五等地",
"value":"26",
},
{
"name":"一等地",
"value":"12",
},
{
"name":"四等地",
"value":"45",
},
{
"name":"三等地",
"value":"5",
},
]
}
]
}
this.mapDotData.output.value.rows = rows
},
//添加散点图
addPieToMap(chart,data){
var sd = [];
for (var i = 0; i < data.length; i++) {
var randomValue = 20;
var radius = randomValue;
// var geoCoord = geoCoordMap[data[i].name];
let geoCoord = chinaData[0].features.find((item)=>{
return item.properties.name==data[i].xzqmc
}).properties.center
if (geoCoord) {
var vr = [];
//饼图的数据不进行映射
vr.push({
name: data[i].xzqmc,
value: data[i].total,
visualMap: false
});
var p = chart.convertToPixel({
seriesIndex: 0
}, geoCoord);
sd.push({
name: data[i].xzqmc,
type: 'pie',
// roseType: 'radius',
// tooltip: {
// formatter: function(params) {
// // return params.seriesName + "
" + params.name + " : " + params.value + ' 亿元';
// return params.total + ' 亩';
// }
// },
radius: radius,
center: p,
data: vr,
zlevel: 4,
roam:false,
tooltip: {
formatter: '{a}
{b}: {c}亿元 ({d}%)'
},
label: {
normal: {
show: true,
position: 'inside',
formatter: '{value|{c}}',
padding:[0,0,radius,0],
rich: {
value: {
fontSize: 12,
color:'#ffffff',
},
},
}
},
labelLine: {
normal: {
show: false
}
},
});
}
}
//因为这个组件公用,发现配置项的series不能进行重置,所以在这里以这种方式手动重置
mapOption.series = [ mapOption.series[0]]
mapOption.series = mapOption.series.concat(sd)
this.myChart.setOption(mapOption,true);
return sd;
},
//重置散点图
resetDot(chart, params) {
var op = chart.getOption();
var ops = op.series;
var currentZoom = this.myChart.getOption().series[0].zoom
let that = this
ops.forEach(function(v, i) {
if (i > 0) {
let geoCoord = chinaData[0].features.find((item)=>{
return item.properties.name==v.name
}).properties.center
var p = chart.convertToPixel({
seriesIndex: 0
}, geoCoord);
v.center = p;
v.label = {
normal: {
show: true,
position: 'inside',
formatter: '{value|{c}}',
padding:[0,0,v.radius * params.zoom||v.radius,0],
rich: {
value: {
fontSize: 12,
color:'#ffffff',
},
},
}
}
//超过地图的最大最小层级 这个图表就不要再伸缩了
if (params != 0 && params.zoom &¤tZoom!=1.5&¤tZoom!=1) {
v.radius = v.radius * params.zoom;
that.lastZoomLevel = params.zoom
return
}
}
});
chart.setOption(op, true);
},
//添加饼图
addPartPieToMap(chart,data){
var sd = [];
for (var i = 0; i < data.length; i++) {
var randomValue = Math.round(Math.random() * 30);
var radius = randomValue <= 10 ? 10 : randomValue;
let geoCoord = chinaData[0].features.find((item)=>{
return item.properties.name==data[i].xzqmc
}).properties.center
if (geoCoord) {
var vr = [];
//饼图的数据不进行映射
// vr.push({
// name: data[i].xzqmc,
// value: data[i].total,
// visualMap: false
// });
var p = chart.convertToPixel({
seriesIndex: 0
}, geoCoord);
sd.push({
name: data[i].xzqmc,
type: 'pie',
//clockWise: false,
itemStyle: {
normal: {
label: {
show: false
},
labelLine: {
show: false
},
shadowBlur: 20,
shadowColor: '#203665',
opacity:1,
}
},
tooltip: {
formatter: function(params) {
console.log('哈哈',params)
// return params.seriesName + "
" + params.name + " : " + params.value + ' 亿元';
return params.value + ' 亩';
}
},
radius: [20, 30],
// center: ['15%', '50%'],
hoverAnimation: false,
// radius: radius,
center: p,
zlevel: 4,
data: data[i].rows
});
}
}
//因为这个组件公用,发现配置项的series不能进行重置,所以在这里以这种方式手动重置
mapOption.series = [ mapOption.series[0]]
mapOption.series = mapOption.series.concat(sd)
this.myChart.setOption(mapOption,true);
return sd;
},
//重置饼图
resetPie(chart, params){
var op = chart.getOption();
var ops = op.series;
ops.forEach(function(v, i) {
if (i > 0) {
let geoCoord = chinaData[0].features.find((item)=>{
return item.properties.name==v.name
}).properties.center
var p = chart.convertToPixel({
seriesIndex: 0
}, geoCoord);
v.center = p;
if (params != 0 && params.zoom) {
v.radius = v.radius * params.zoom;
}else if (params != 0 && params.selected) {
var rangeFirstNumber = params.selected[0];
var rangeSecondNumber = params.selected[1];
var pd = v.data[this.typeIndex].value;
if (pd < rangeFirstNumber || pd > rangeSecondNumber) {
// v.itemStyle.normal.opacity = 0;
v.itemStyle = {
normal: {
label: {
show: false
},
labelLine: {
show: false
},
shadowBlur: 20,
shadowColor: '#203665',
opacity:0,
}
}
} else {
// v.itemStyle.normal.opacity = 1;
v.itemStyle = {
normal: {
label: {
show: false
},
labelLine: {
show: false
},
shadowBlur: 20,
shadowColor: '#203665',
opacity:1,
}
}
}
}else{
let zoomVal = chart.getOption().series[0].zoom
let arr = [10, 15]
for(var j = 0;j<arr.length;j++){
arr[j] = arr[j] * zoomVal
}
v.radius = arr
}
}
});
chart.setOption(op, true);
}
},
}
</script>
<style lang="scss" scoped>
.chart{
background-size: 100% 100%;
#mapChart{
width: 100%;
height: 1000px;
}
.mapChoose {
color: #eee;
.title {
padding: 5px;
border-top: 1px solid rgba(132, 219, 233, 0.8);
border-bottom: 1px solid rgba(147, 235, 248, 0.8);
cursor: pointer;
}
.icon {
font-family: 'simsun';
font-size: 25px;
margin: 0 11px;
}
}
}
</style>