PS:使用的是React框架
要實現(xiàn)的效果如下:
需要一張地圖,對地圖進(jìn)行下鉆操作龟糕,地圖的區(qū)域需要顏色標(biāo)記
兩種標(biāo)記方式(氣泡和圓點),且顏色需要不一樣
右邊要有柱狀圖顯示人數(shù)
開始之前我們需要準(zhǔn)備一個獲得地圖json數(shù)據(jù)的網(wǎng)站
需要哪部分的數(shù)據(jù)悔耘,點擊這個按鈕復(fù)制到你的編輯器上就可以了讲岁。
準(zhǔn)備工作做完,我們就開始進(jìn)入正題了:首先我們要一個“地圖畫布”衬以,有了畫布才能折騰數(shù)據(jù)缓艳。
畫一個地圖
引入echarts和相關(guān)的json文件
import Echarts from 'echarts';
import jiangxi from '../../../config/mapJSON/jiangxi.json';
import jiujiang from '../../../config/mapJSON/jiujiang.json';
準(zhǔn)備一個div存放地圖,記得寫div的高度和寬度看峻。
<div id='map' style={{height: '100%', width: '100%'}}></div>
整體的框架(我們先把option放一放阶淘,先別急,現(xiàn)在你的頁面一定是空的)
let myChart = Echarts.init(document.getElementById('map'))
let name = 'jiangxi' //地圖名是jiangxi
let data = jiangxi //地圖的數(shù)據(jù)來自之前引入的json文件
Echarts.registerMap(name, data) //此步不可省略互妓,要想展示一個地圖舶治,先需要注冊,巨坑(官方根本無文檔车猬,全靠瞎猜)
let option = {} //此處先省略,不放入任何數(shù)據(jù)
myChart.setOption(option, true);
現(xiàn)在為option添磚加瓦尺锚,此時你的頁面會有一個小地圖了
let option = {
backgroundColor: '#fff',
title: {
top: 20,
text: '用戶注冊區(qū)域展示',
subtext: '',
x: 'center',
textStyle: {
color: '#000'
}
},
geo: {
type: 'map',
map: name, //'jiangxi'
roam: true,
geoIndex: 1,
zoom: 1.1, //地圖的比例
label: {
normal: {
show: true,
textStyle: {
color: '#000000' //字體顏色
}
},
emphasis: {
textStyle: {
color: '#000000' //選中后的字體顏色
}
}
},
itemStyle: {
normal: {
areaColor: '#EEEEEE',
borderColor: '#8b8b8b',
},
emphasis: {
areaColor: '#ffffff',
}
},
},
}
現(xiàn)在想在地圖上綁定我的數(shù)據(jù)珠闰,應(yīng)該怎么做呢?
//獲得數(shù)據(jù)這一步我就不寫了,用下面的死數(shù)據(jù)
let cityData = [{name:'南昌市',value:47},{name:'九江市',value:22}瘫辩,{name:'新余市',value:4}]
//在geo多配置一行data數(shù)據(jù)
geo:{
...
data:cityData
}
設(shè)置地圖色塊
此時雖然數(shù)據(jù)綁定成功了伏嗜,但是地圖上依舊什么色塊都沒有坛悉。我們繼續(xù)下一步,設(shè)置option中的visualMap參數(shù)和series參數(shù)承绸。
visualMap用來設(shè)置地圖的色塊裸影,series參數(shù)用于標(biāo)記地圖。
visualMap: {
show: true,
//設(shè)置最大值和最小值
min: 0,
max: 50,
//設(shè)置位置
left: '4%',
top: '40%',
text: ['高', '低'], // 文本军熏,默認(rèn)為數(shù)值文本
calculable: true,
seriesIndex: [0], //作用在哪個series上
inRange: {
color: ['#ffcbc5', '#ffd661'] //粉黃
}
},
series:[
{
name: "市報名人數(shù)",
type: "map",
geoIndex: 0,
data: cityData,
},
]
設(shè)置圓點標(biāo)記
下圖是圓點需要的數(shù)組轩猩,為這個數(shù)組命名為areaData
給series新增一個圓點標(biāo)記
{
name: '區(qū)縣報名人數(shù)',
type: 'effectScatter',
coordinateSystem: 'geo',
showEffectOn: 'render',
rippleEffect: {
period: 15,
scale: 4,
brushType: 'fill'
},
hoverAnimation: true,
itemStyle: {
normal: {
color: '#fffd21', //設(shè)置圓點的顏色
shadowBlur: 10,
shadowColor: '#333'
}
},
symbolSize: function (params) {
console.log('paramsparams', params[2])
if (params[2] > 30)
return params[2] / 5
else
return 3
}, //圓點的大小可以自行設(shè)置,這里不贅述
data: areaData,
},
設(shè)置氣泡標(biāo)記
氣泡和圓點的原理是相同的荡澎,他們的數(shù)據(jù)要求是需要經(jīng)緯度以及數(shù)據(jù)均践,你無法知道經(jīng)緯度的時候可以從提前下載好的json數(shù)據(jù)中取。然后繼續(xù)在series中添加氣泡標(biāo)記摩幔。
let geoCoordMap = jiangxi.features.map(item => {
return {
name: item.properties.name,
value: item.properties.center
}
});
let convertData = function (data) {
let res = [];
for (let i = 0; i < data.length; i++) {
if (geoCoordMap.filter(item => item.name === data[i].name).length)
res.push({
name: data[i].name,
value: geoCoordMap.filter(item => item.name === data[i].name)[0].value.concat(data[i].value)
})
}
return res;
}
{
name: 'Top 5',
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'pin',
symbolSize: 40,
label: {
normal: {
show: true,
textStyle: {
color: '#fff',
fontSize: 9,
fontWeight: 'bold'
},
formatter(value) {
return value.data.value[2]
}
}
},
itemStyle: {
normal: {
color: '#F62157', //標(biāo)志顏色
}
},
//使用之前的函數(shù)處理數(shù)據(jù)彤委,為之前的cityData添加經(jīng)緯度,當(dāng)然也可以讓初始數(shù)據(jù)像之前的areaData一樣就有經(jīng)緯度
data: convertData(cityData),
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
hoverAnimation: true,
zlevel: 1
},
現(xiàn)在的效果:
設(shè)置右側(cè)的柱狀圖
為option添加xAxis和yAxis(一定要有或衡,否則在series中新增type為bar的標(biāo)記時會報錯)
柱狀圖中的數(shù)據(jù)需要特殊處理
let barData = cityData.map((item) => {
return [item.value, item.name]
})
//option中的grid表示bar的位置
grid: {
left: '70%',
right: '10%',
// top: '30%',
// bottom:'40%'
},
xAxis: {
type: 'value',
// scale: true,
position: 'top',
min: 0,
boundaryGap: false,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
margin: 1,
textStyle: {
color: '#aaa'
}
},
},
yAxis: {
type: 'category',
inverse: true, //改變數(shù)據(jù)順序
nameGap: 16,
axisLine: {
show: true,
lineStyle: {
color: '#ddd'
}
},
axisTick: {
show: false,
lineStyle: {
color: '#ddd'
}
},
axisLabel: {
interval: 0,
show: true,
textStyle: {
color: '#000000'
}
},
},
地圖下鉆操作※
你需要知道:
- 點擊地圖怎么做到
- 怎么通過點擊地圖進(jìn)行下鉆
- 下鉆后地圖上的標(biāo)記數(shù)據(jù)如何改變(氣泡焦影、圓點、柱狀圖)
你還記得我們給地圖的命名嗎——myChart封断,實現(xiàn)點擊就要為它添加點擊事件斯辰,打印看看這里的e是何方神圣。
myChart.on('click', (e) => {
console.log('click', e)
})
想一想澄港,我們需要根據(jù)點擊城市名的不同下鉆到不同的城市椒涯。那么需要的就是點擊這塊區(qū)域的name了。
還記得我們是怎么使用地圖的嗎回梧?注冊地圖時废岂,有一個地圖名和地圖名對應(yīng)的json,由于我們獲得的name是中文狱意,無法和json數(shù)據(jù)對應(yīng)湖苞,選擇switch語句進(jìn)行調(diào)整地圖名,下面的thisMap相當(dāng)于最開始初始化地圖時的name详囤,thisData相當(dāng)于最開始初始化地圖時的data财骨。
//得到加載地圖時的地圖名
switch (e.name) {
case '九江市':
thisMap = 'jiujiang';
break
case '南昌市':
thisMap = 'nanchang';
break
case '撫州市':
thisMap = 'fuzhou';
break
case '贛州市':
thisMap = 'ganzhou';
break
case '吉安市':
thisMap = 'jian';
break
case '景德鎮(zhèn)市':
thisMap = 'jingdezhen';
break
case '萍鄉(xiāng)市':
thisMap = 'pingxiang';
break
case '上饒市':
thisMap = 'shangrao';
break
case '新余市':
thisMap = 'xinyu';
break
case '宜春市':
thisMap = 'yichun';
break
case '鷹潭市':
thisMap = 'yingtan';
break
}
//得到加載地圖時的地圖json
let area = {
'九江市': require('../../../config/mapJSON/jiujiang.json'),
'南昌市': require('../../../config/mapJSON/nanchang.json'),
'撫州市': require('../../../config/mapJSON/fuzhou.json'),
'贛州市': require('../../../config/mapJSON/ganzhou.json'),
'吉安市': require('../../../config/mapJSON/jian.json'),
'景德鎮(zhèn)市': require('../../../config/mapJSON/jingdezhen.json'),
'萍鄉(xiāng)市': require('../../../config/mapJSON/pingxiang.json'),
'上饒市': require('../../../config/mapJSON/shangrao.json'),
'新余市': require('../../../config/mapJSON/xinyu.json'),
'宜春市': require('../../../config/mapJSON/yichun.json'),
'鷹潭市': require('../../../config/mapJSON/yingtan.json')
}
thisData = area[e.name]
如何動態(tài)的把thisMap和thisData傳遞給Echarts,告訴Echarts我需要換一個地圖進(jìn)行注冊呢藏姐?可以寫一個函數(shù)loadMap(可以還有別的方法隆箩,不贅述)。先打個框架羔杨。
let loadMap = (name,data) =>{
//現(xiàn)在是否是下鉆狀態(tài)=>通過name是否為'jiangxi'判斷
//如果是下鉆:過濾areaData,barData中的其他區(qū)域數(shù)據(jù)捌臊,
//如果不是下鉆狀態(tài):之前在jiangxi時的數(shù)據(jù)全部存入state,現(xiàn)在取出并賦值還原兜材。
let option = {}
}
總結(jié)
最后重新整理一下整體框架
showMap(cityData, areaData){
//cityData理澎,areaData 這里的數(shù)據(jù)需要你自己獲得
let myChart = Echarts.init(document.getElementById('map'))
//默認(rèn)地圖:江西省
let thisMap = 'jiangxi'
let thisData = jiangxi
let loadMap = (name, data) => {
//地圖名轉(zhuǎn)回中文逞力,為了方便過濾數(shù)據(jù)
if (name !== 'jiangxi') {
let key = ''
switch (name) {
case 'jiujiang' :
key = '九江市';
break
//... 不贅述
}
//在areaData中找到對應(yīng)市的區(qū)和縣
let array = areaData.filter(item => item.city === key)
let cd = array.map(item => {
return {
name: item.name,
value: item.value[2]
}
})
barData = array.map(item => {
return [item.value[2], item.name]
})
areaData = []
cityData = cd
} else {
areaData = this.state.areaData
cityData = this.state.cityData
barData = cityData.map((item) => {
return [item.value, item.name]
})
}
Echarts.registerMap(name, data) //注冊地圖
let option = {}
myChart.setOption(option, true);
}
loadMap(thisMap, thisData)
myChart.on('click', (e) => {
switch (e.name) {
case '九江市':
thisMap = 'jiujiang';
break
//...不贅述
}
thisData = area[e.name]
//下鉆
if (thisData) {
loadMap(thisMap, thisData)
} else {
//不繼續(xù)下鉆返回上一層
loadMap('jiangxi', jiangxi)
}
})
}