安装 echarts 和 echarts-gl 依赖 。
npm i echarts echarts-gl -S
assets 下新增 mapdata 资源包(中国个省市区县 json 文件),可以在网上自行查找下载,也可通过本文案例链接,在码云上拉取获得 。 完整示例链接https://gitee.com/wu241617/echarts-map
assets 下新增 config 目录,下新建 map.json 文件。我这里案例中只做了抚州市和荆州市的配置,后续有其他区域需要,新增添加即可 。文件中 coord 字段是对应 name 子区域的经纬度,可以在网上搜索查询,后续这里要进行微调,控制标注的位置 。
区域经纬度https://max.book118.com/html/2021/0507/6030102121003144.shtm
{
"抚州市": {
"geoJson": "/geometryCouties/361000.json",
"qxwz": [
{
"name": "东乡区",
"coord": [116.6, 28.18]
},
{
"name": "临川区",
"coord": [116.35, 27.98]
},
{
"name": "金溪县",
"coord": [116.75, 28]
},
{
"name": "崇仁县",
"coord": [116.05, 27.79]
},
{
"name": "宜黄县",
"coord": [116.25, 27.5]
},
{
"name": "南城县",
"coord": [116.66, 27.65]
},
{
"name": "资溪县",
"coord": [117.05, 27.8]
},
{
"name": "乐安县",
"coord": [115.83, 27.47]
},
{
"name": "南丰县",
"coord": [116.45, 27.24]
},
{
"name": "黎川县",
"coord": [116.85, 27.2]
},
{
"name": "广昌县",
"coord": [116.35, 26.87]
}
]
},
"荆州市": {
"geoJson": "/geometryCouties/421000.json",
"qxwz": [
{
"name": "洪湖市",
"coord": [113.59, 30.02]
},
{
"name": "江陵县",
"coord": [112.49, 30.01]
},
{
"name": "荆州区",
"coord": [112.08, 30.49]
},
{
"name": "沙市区",
"coord": [112.35, 30.41]
},
{
"name": "松滋市",
"coord": [111.62, 30.03]
},
{
"name": "公安县",
"coord": [112.12, 29.87]
},
{
"name": "监利县",
"coord": [112.96, 29.91]
},
{
"name": "石首市",
"coord": [112.51, 29.82]
}
]
}
}
{{selectedText}}
【注意】:地图配置中, geo 数组中有两个子项,渲染两个地图,通过控制 center 属性值配置,形成微错位,视觉上立体, 注意 center 值要处于当前区域经纬度之间,需要微调否则看不到地图渲染 ,其他具体配置请查看官方文档配置项。
官方文档https://echarts.apache.org/zh/option.html#title
import * as echarts from 'echarts';
import 'echarts-gl';
import { mapState } from 'vuex'
export default {
name: 'Main',
data() {
return {
selectCity: '361000',
mapConfigJson: require("../../assets/config/map.json"),
map: '',
mapLoadCity: '',
cityName: [],
mapdataJson: [],
selectedText: ''
}
},
mounted() {
this.cityChange();
},
computed: {
...mapState(['JZtestData', 'FZtestData', 'options'])
},
methods: {
// 下拉框城市区域切换
cityChange() {
this.selectedText = ''
this.cityName = []
this.options.map(item => {
if (item.value === this.selectCity) {
this.mapLoadCity = item.name
this.cityName.push(item.name)
}
})
this.mapChart();
},
//显示地图
mapChart() {
this.map = echarts.init(document.getElementById('mapMain'));
this.initMenu();
this.map.on("click", this.mapClick);
},
//地图点击事件
mapClick(param) {
this.selectedText = `当前选中区域为: ${this.mapLoadCity}--${param.name}`;
},
initMenu() {
this.loadMap(this.mapLoadCity, this.loadData(this.mapLoadCity));
},
loadData(mapLoadCity) {
if (mapLoadCity === '荆州市') {
return this.JZtestData;
}
if (mapLoadCity === '抚州市') {
return this.FZtestData;
}
},
/**
* 加载地图
* @param name
*/
loadMap(name, mapdataJson) {
let markPointData = this.mapConfigJson[name]["qxwz"];
if (!this.mapConfigJson[name].geoJson) {
return;
}
let geoJson = require("../../assets/mapdata" + this.mapConfigJson[name].geoJson);
echarts.registerMap(name, geoJson);
let dataColor = () => {
let colorlist = [];
for (let i = 0; i < mapdataJson.length; i++) {
if (mapdataJson[i].value < 1000) {
colorlist.push("rgb(207,234,254)");
} else if (mapdataJson[i].value >= 1000 && mapdataJson[i].value < 2000) {
colorlist.push("rgb(138,184,252)");
} else if (mapdataJson[i].value >= 2000 && mapdataJson[i].value < 3000) {
colorlist.push("rgb(101,162,249)");
} else if (mapdataJson[i].value >= 3000) {
colorlist.push("rgb(79,132,235)");
}
}
return colorlist;
}
let option = {
geo: [
{
geoIndex: 0,
z: 1,
type: 'map',
map: name,
center: [116.38, 27.56],
zoom: 1,
aspectScale: 1.3, //长宽比
scaleLimit: {
"min": 1.1,
"max": 15
},
label: { //标签样式设置
show: true,
fontSize: 14,
color: 'rgba(255,255,255)',
},
itemStyle: {
normal: {
borderColor: "#fff",
borderWidth: 1,
areaColor: 'rgb(207,234,254)',
fontWeightL: 700,
},
emphasis: {
areaColor: 'rgb(243,215,115)',
borderWidth: 0
}
},
select: {
itemStyle: {
areaColor: 'rgb(243,215,115)',
borderColor: '#fff',
borderWidth: 3,
shadowOffsetX: 0,
shadowOffsetY: 0,
opacity: 1,
}
},
selectedMode: 'multiple',
},
{
geoIndex: 0,
map: name,
z: 0,
zoom: 1,
center: [116.348, 27.58],
aspectScale: 1.3, //长宽比
scaleLimit: {
"min": 1.1,
"max": 15
},
label: { //标签样式设置
show: true,
fontSize: 14,
color: 'rgba(150,181,246,0)',
},
itemStyle: {
normal: {
shadowColor: '#ececec',
shadowOffsetX: 5,
shadowOffsetY: 5,
borderColor: "#fff",
borderWidth: 1,
areaColor: 'rgb(187,217,253)',
},
emphasis: {
areaColor: 'rgb(187,217,253)',
borderWidth: 0
},
}
},
],
visualMap: [{
min: 0,
max: 10,
left: 'left',
top: 'bottom',
text: ['高', '低'],
calculable: true,
show: false,
inRange: {
color: dataColor()
}
}],
color: ['white'],
series: [
{
name: "热力图",
type: "heatmap",
coordinateSystem: "geo",
geoIndex: 0,
markPoint: { //标记点
symbol: 'roundRect',
symbolKeepAspect: true,
symbolSize: [35, 15], //图形大小
label: {
width: 100,
height: 50,
normal: {
color: '#000',
formatter: function (params) {
for (let i = 0; i < mapdataJson.length; i++) {
if (mapdataJson[i].name == params.name) {
return mapdataJson[i].value;
}
}
},
show: true,
},
emphasis: {
show: true,
}
},
itemStyle: {
color: '#fff',
},
data: markPointData
}
},
{
name: '地市',
type: 'map',
geoIndex: 0,
data: this.getMapColor(geoJson)
}
]
};
if (this.mapLoadCity === '荆州市') {
option.geo[0].center = [112.71, 29.71];
option.geo[0].zoom = 1.2;
option.geo[1].center = [112.73, 29.73];
option.geo[1].zoom = 1.2;
}
this.map.setOption(option, true);
},
/**
* 生成地图颜色
* @param geoJson
* @returns {Array}
*/
getMapColor(geoJson) {
let list = [];
for (let i in geoJson.features) {
let feature = geoJson.features[i];
let name = feature.properties.name;
let json = {};
json.name = name;
json.value = i % 11;
if (this.cityName.length == 2) {
if (this.cityName[1] == name) {
json.selected = true;
}
}
list.push(json);
}
return list;
},
}
}
组件内样式
.mapMain {
width: 1000px;
height: 750px;
}
全局样式(在 assets 下新建 CSS 目录,下新增 common.css 文件)
* {
margin: 0;
padding: 0;
}
html,
body {
font-size: 24px;
font-family: '楷体' !important;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.home {
width: 1000px;
height: 800px;
border: 1px solid black;
padding: 10px;
margin: 0 auto;
}
.header {
width: 100%;
height: 50px;
text-align: center;
line-height: 50px;
color: white;
background: black;
}
.main {
width: 100%;
height: 750px;
background: lavender;
position: relative;
z-index: 1;
}
.select {
position: absolute;
top: 20px;
left: 20px;
width: 80px;
height: 30px;
border: 1px solid rgba(0, 0, 0, .4);
cursor: pointer;
text-align: center;
line-height: 30px;
z-index: 999;
}
.selectedText {
border-bottom: 2px solid lightblue;
position: absolute;
top: 20px;
right: 20px;
font-size: 15px;
z-index: 999;
}
使用 vuex 模拟后端请求到的地图数据,存放在 store 下的 index.js 文件中的 state 内 。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
JZtestData: [{
name: "洪湖市",
qxdm: "421083",
value: 654
},
{
name: "江陵县",
qxdm: "421024",
value: 13
},
{
name: "荆州区",
qxdm: "421003",
value: 4222
},
{
name: "沙市区",
qxdm: "421002",
value: 1854
},
{
name: "松滋市",
qxdm: "421087",
value: 1023
},
{
name: "公安县",
qxdm: "421022",
value: 10
},
{
name: "监利县",
qxdm: "421023",
value: 2183
},
{
name: "石首市",
qxdm: "421081",
value: 12
}
],
FZtestData: [{
name: "东乡区",
qxdm: "361029",
value: 654
},
{
name: "临川区",
qxdm: "361002",
value: 13
},
{
name: "金溪县",
qxdm: "361027",
value: 4222
},
{
name: "崇仁县",
qxdm: "361024",
value: 1854
},
{
name: "宜黄县",
qxdm: "361026",
value: 1023
},
{
name: "南城县",
qxdm: "361021",
value: 10
},
{
name: "资溪县",
qxdm: "361028",
value: 2183
},
{
name: "乐安县",
qxdm: "361025",
value: 12
},
{
name: "南丰县",
qxdm: "361023",
value: 10
},
{
name: "黎川县",
qxdm: "361022",
value: 2183
},
{
name: "广昌县",
qxdm: "361030",
value: 12
}
],
options: [{
name: '荆州市',
value: '421000'
}, {
name: '抚州市',
value: '361000'
}]
},
mutations: {},
actions: {},
modules: {}
})
安装 province-city-china 依赖。
npm i province-city-china -S
请求已安装的 province-city-china 依赖包,获取各项数据。
参考链接https://juejin.cn/post/6844903527844675591
const { data, province, city, area, town } = require('province-city-china/data');
// data - 总数据(省/地/县/乡)
// province - 省级(省/直辖市/特别行政区)
// city - 地级(城市)
// area - 县级(区县)
// town - 乡级(乡镇/街)
{{firstTitle}}
{{currentProvince.name}}
{{currentCity.name}}
import * as echarts from 'echarts';
const { province, city } = require('province-city-china/data');
export default {
name: 'ChinaMain',
data() {
return {
firstTitle: '中国',
myChart: '',
currentClick: '',
currentProvince: {},
currentCity: {},
cityState: false,
provinceState: false
}
},
mounted() {
this.initEcharts("china", "中国");
},
methods: {
goBackChina() {
this.initEcharts("china", "中国");
this.currentProvince.name = '';
this.currentCity.name = '';
},
goBackProvince() {
this.initEcharts(this.currentProvince.province, this.currentProvince.name, "1");
this.currentCity.name = '';
},
goBackCity() {
this.initEcharts(this.currentCity.code, this.currentCity.name);
},
initEcharts(pName, Chinese_, state = "0") {
this.myChart = echarts.init(document.getElementById('chinaMap'));
let tmpSeriesData = [];
if (pName === "china") {
let geoJson = require('../../assets/mapdata/china.json');
echarts.registerMap(pName, geoJson);
} else {
if (this.currentClick === 'province' || state === "1") {
let geoJson = require(`../../assets/mapdata/geometryProvince/${pName}.json`);
echarts.registerMap(pName, geoJson);
} else {
let geoJson = require(`../../assets/mapdata/geometryCouties/${pName}.json`);
echarts.registerMap(pName, geoJson);
}
}
let option = {
series: [
{
name: Chinese_ || pName,
type: 'map',
mapType: pName,
roam: false,//是否开启鼠标缩放和平移漫游
itemStyle: {//地图区域的多边形 图形样式
normal: {//是图形在默认状态下的样式
label: {
show: true,//是否显示标签
textStyle: {
color: "#303133",
fontSize: '10px'
}
}
},
emphasis: {//是图形在高亮状态下的样式,比如在鼠标悬浮或者图例联动高亮时
label: {
show: true,
textStyle: {
fontSize: '14px'
}
}
}
},
data: tmpSeriesData,//后端数据
top: "10%"//组件距离容器的距离
}
]
};
this.myChart.setOption(option, true);
this.myChart.off("click");
if (pName === "china") { // 全国时,添加click 进入省级
this.currentClick = 'province'
this.myChart.on('click', this.mapClick);
} else {
this.currentClick = 'city'
this.myChart.on('click', this.mapClick);
}
},
//地图点击事件
mapClick(param) {
this.provinceState = false;
this.cityState = false;
if (this.currentClick === 'province') {
//遍历取到provincesText 中的下标 去拿到对应的省js
for (var i = 0; i < province.length; i++) {
if (param.name === province[i].name) {
this.provinceState = true;
this.currentProvince = { ...province[i] };
this.currentProvince.name = ` -->${this.currentProvince.name} `;
//显示对应省份的方法
this.showProvince(province[i].province, province[i].name);
break;
}
}
!this.provinceState ? alert('暂不支持该区域地图展示!') : '';
} else {
for (var l = 0; l < city.length; l++) {
if (param.name === city[l].name) {
this.cityState = true;
this.currentCity = { ...city[l] };
this.currentCity.name = ` -->${this.currentCity.name} `;
//显示对应城市的方法
this.showProvince(city[l].code, city[l].name);
break;
}
}
!this.cityState ? alert('暂不支持该区域地图展示!') : '';
}
},
showProvince(pName, Chinese_) {
this.initEcharts(pName, Chinese_);
}
}
}
#tool {
height: 30px;
line-height: 30px;
color: deepskyblue;
cursor: pointer;
position: absolute;
top: 10px;
left: 10px;
z-index: 10000;
font-size: 18px;
text-align: left;
}
#chinaMap {
width: 1000px;
height: 750px;
}
完整示例链接https://gitee.com/wu241617/echarts-map
【注意】: 在完整示例中,码云下拉代码到本地后,npm install 安装依赖,npm run serve 启动项目,默认显示 /home 路由页面,中国下钻省市区县页面通过 /cm 路由访问。依赖于 mapdata 资源包和 province-city-china 依赖。