Echarts --- 中国地图(2D)
0. 环境搭建
1. 所需数据集
2. 包下载
npm i echarts
npm i mathjs
1. 处理数据并传给子组件
map/index.vue
<template>
<div class="mapview">
<!-- 左侧图表 -->
<div class="c-left">
<!-- 设备统计 -->
<div class="total">
<div class="title">产品统计</div>
<div class="card">
<!-- <div class="list" v-for="(item, index) in totalList" :key="index">-->
<!-- <span class="list-num">{{ item.value + '' || '--' }}</span>-->
<!-- <span class="list-name">{{ item.title || '' }}</span>-->
<!-- </div>-->
</div>
</div>
</div>
<mapChina :pointData="pointData" :filterPointArr="filterPointArr"/>
</div>
</template>
<script>
import mapChina from "@/views/map/config/mapChina";
import {subtract} from 'mathjs';
export default {
name: "balerMap",
components: {
mapChina,
},
data() {
return {
originalData: [ // 原始数据
{
"id": 3,
"longitude": "120.335777",
"latitude": "29.744551"
},
{
"id": 4,
"longitude": "108.449715",
"latitude": "21.575615"
},
{
"id": 5,
"longitude": "120.360321",
"latitude": "31.903963"
},
{
"id": 7,
"longitude": "118.490368",
"latitude": "34.929584"
},
{
"id": 8,
"longitude": "118.577217",
"latitude": "31.176367"
},
{
"id": 11,
"longitude": "119.257591",
"latitude": "31.542629"
},
{
"id": 13,
"longitude": "111.371857",
"latitude": "35.587124"
},
{
"id": 19,
"longitude": "121.20354",
"latitude": "30.215174"
},
{
"id": 27,
"longitude": "112.315285",
"latitude": "30.299171"
},
{
"id": 29,
"longitude": "119.725922",
"latitude": "32.518761"
},
{
"id": 33,
"longitude": "112.247955",
"latitude": "37.601864"
}
],
pointData: [],
filterPointArr: [], // 处理后的数据
}
},
mounted() {
this.getPositionData()
},
methods: {
getPositionData() {
// 经纬度整数部分数据相同, 合并散点 地图层级较低时, 利用此数据展示该位置有多少机器数量
const filterPointArr = []
// 经纬度相同的坐标合并 (合并id)
const mergedIDArray = [];
// // 利用集合处理数据
const processedIds = new Set();
this.originalData.forEach((item, index) => {
item.id = item.id + ''
// 经纬度有可能会错位,矫正经纬度
if (Number(item.latitude) > Number(item.longitude)) {
const lgd = item.longitude;
item.longitude = item.latitude;
item.latitude = lgd;
}
if (index === 0) {
filterPointArr.push(item);
} else {
// 经纬度相同的坐标优先级 > 合并ID相同的数据
for (let k = 0; k < filterPointArr.length; k++) {
const subtractLatitude = subtract(item.latitude, filterPointArr[k].latitude);
const subtractLongitude = subtract(item.longitude, filterPointArr[k].longitude);
if (Math.abs(subtractLatitude) < 1 && Math.abs(subtractLongitude) < 1) {
// 查找已处理数据中是否有相同 ID 的数据
const flagg = filterPointArr.filter((fitem) => fitem.id.split(',').includes(item.id));
if (!flagg.length) {
filterPointArr[k].id += `,${item.id}`;
}
}
}
// 等for结束后, 如果此item.id没被捕获, 直接push这条数据
const flag = filterPointArr.filter((fitem) => fitem.id.split(',').includes(item.id));
if (!flag.length) {
filterPointArr.push(item);
}
}
if (!processedIds.has(item.longitude) && !processedIds.has(item.latitude)) {
const matchingItems = mergedIDArray.filter(
(otherItem) => otherItem.longitude === item.longitude && otherItem.latitude === item.latitude
);
if (matchingItems.length > 0) {
const mergedIds = matchingItems.map((matchingItem) => matchingItem.id).join(', ');
mergedIDArray.push({
id: mergedIds,
longitude: item.longitude,
latitude: item.latitude,
});
matchingItems.forEach((matchingItem) => {
processedIds.add(matchingItem.longitude + matchingItem.latitude);
});
} else {
mergedIDArray.push(item);
}
}
})
for (let k of mergedIDArray) {
this.pointData.push({
name: k.id,
value: [k.longitude, k.latitude, k.longitude + ', ' + k.latitude],
});
}
for (let k of filterPointArr) {
this.filterPointArr.push({
name: k.id,
value: [k.longitude, k.latitude, k.longitude + ', ' + k.latitude],
});
}
}
}
}
</script>
<style lang="less" scoped>
.mapview {
width: 100%;
height: calc(100vh - 55px);
background: linear-gradient(to bottom, #122d56 0%, #113d7b 80%, #1d4583 100%);
overflow: hidden;
position: relative;
.c-left {
width: 370px;
height: auto;
padding: 10px 10px;
color: #c7dbfa;
position: absolute;
left: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
z-index: 2;
.total {
width: 100%;
height: 220px;
border: 1px solid #5993ea;
border-radius: 4px;
box-shadow: inset 0px 0px 20px #25679f;
.title {
width: 50%;
height: 30px;
line-height: 30px;
margin: 8px auto;
text-align: center;
font-size: 16px;
border-radius: 5px;
background: #1f5193;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
}
.card {
width: 99%;
height: 78%;
padding: 2px 2px;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
overflow: hidden;
.list {
width: 31%;
height: 44%;
border-radius: 2px;
background-color: #1f5193;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
white-space: nowrap;
span {
white-space: nowrap;
}
.list-num {
font-size: 20px;
font-weight: bold;
}
.list-name {
font-size: 13px;
}
}
}
}
}
}
</style>
map/config/mapChina.vue
<template>
<div style="width: 100%; height: 1080%">
<div id="scatter"></div>
</div>
</template>
<script>
import * as chinaMap from '@/static/map/china.json'
import * as echarts from 'echarts';
export default {
name: "mapChina",
// 接收父组件传递的数据
props: {
pointData: Array,
filterPointArr: Array,
},
}
</script>
<style lang="less" scoped>
</style>
2. 初始化地图
map/config/mapChina.vue
<template>
<div style="width: 100%; height: 1080%">
<div id="scatter"></div>
</div>
</template>
<script>
import * as chinaMap from '@/static/map/china.json'
import * as echarts from 'echarts';
export default {
name: "mapChina",
data() {
return {
option: {
animation: false,
tooltip: {},
geo: {
map: 'china', // 地图类型, 这里是中国地图
zoom: 1.5, // 地图默认缩放等级
center: [98, 34.5], // 地图中心经纬度
roam: true, //是否允许缩放 - 拖拽
// selectedMode: "single", //点击省份高亮 single / multiple
animationDurationUpdate: 0, //地图移动的时候,渲染的点跟着移动,但是会有延迟,值为0,则无需延迟
scaleLimit: {
min: 0.7,
// max: 8.0,
},
label: {
show: true, // 显示省份
color: '#eaeaea',
fontSize: 16,
},
itemStyle: {
areaColor: '#2971c3', //#2971c3 #228fba #3a7fd5
borderColor: '#0299e2', //#0e335e #0299e2
borderWidth: 2,
// shadowBlur: 10,
// shadowOffsetX: 2,
// shadowOffsetY: 2,
// shadowColor: '#0e335e',
},
//hover状态下的多边形和标签样式
emphasis: {
// disabled: true, //是否关闭高亮状态
focus: 'none', //是否淡出其它数据的图形 'self' / 'none'
label: {
show: true,
color: '#eaeaea',
},
itemStyle: {
areaColor: '#39c5cf',
color: '#0066CC',
},
},
tooltip: {
show: false,
},
data: [],
}
},
}
},
mounted() {
// 1. 注册中国地图
echarts.registerMap('china', chinaMap)
// 2. 初始化地图
this.initMap('china')
},
methods: {
/**
* echarts 初始化地图
* @param mapType
*/
initMap(mapType) {
this.mapReset()
this.mapChart = echarts.init(document.getElementById('scatter'))
this.option.geo.map = mapType
// 配置中国地图 或 世界地图的配置
if (mapType === 'china') {
this.option.geo.zoom = 1.5;
this.option.geo.center = ['98', '35'];
this.option.geo.label.show = true;
} else {
this.option.geo.zoom = 1;
this.option.geo.center = '';
this.option.geo.label.show = true;
}
this.mapChart.setOption(this.option, true)
},
/**
* echarts 重置地图配置
*/
mapReset() {
this.mapChart && this.mapChart.dispose()
this.mapChart = null
}
}
}
</script>
<style lang="less" scoped>
#scatter {
width: 1920px;
height: 1080px;
}
.mapBack {
padding: 8px 14px;
font-size: 15px;
color: #bdddfd;
background-color: #1c4c7c;
position: absolute;
left: 425px;
margin-top: 20px;
z-index: 9;
white-space: nowrap;
}
</style>
3. 根据坐标在地图打点
map/config/mapChina.vue
<template>
<div style="width: 100%; height: 1080%">
<div id="scatter"></div>
</div>
</template>
<script>
import * as chinaMap from '@/static/map/china.json'
import * as echarts from 'echarts';
export default {
name: "mapChina",
data() {
return {
isHighLevel: false,
option: {
animation: false,
tooltip: {},
geo: {
map: 'china', // 地图类型, 这里是中国地图
zoom: 1.5, // 地图默认缩放等级
center: [98, 34.5], // 地图中心经纬度
roam: true, //是否允许缩放 - 拖拽
// selectedMode: "single", //点击省份高亮 single / multiple
animationDurationUpdate: 0, //地图移动的时候,渲染的点跟着移动,但是会有延迟,值为0,则无需延迟
scaleLimit: {
min: 0.7,
// max: 8.0,
},
label: {
show: true, // 显示省份
color: '#eaeaea',
fontSize: 16,
},
itemStyle: {
areaColor: '#2971c3', //#2971c3 #228fba #3a7fd5
borderColor: '#0299e2', //#0e335e #0299e2
borderWidth: 2,
// shadowBlur: 10,
// shadowOffsetX: 2,
// shadowOffsetY: 2,
// shadowColor: '#0e335e',
},
//hover状态下的多边形和标签样式
emphasis: {
// disabled: true, //是否关闭高亮状态
focus: 'none', //是否淡出其它数据的图形 'self' / 'none'
label: {
show: true,
color: '#eaeaea',
},
itemStyle: {
areaColor: '#39c5cf',
color: '#0066CC',
},
},
tooltip: {
show: false,
},
data: [],
},
// 3. 添加地图数据的配置项
series: [
{
type: 'scatter', //scatter, effectScatter(涟漪)
coordinateSystem: 'geo',
// zlevel: 2,
// rippleEffect: {
// //涟漪特效
// number: 3, //环数
// period: 4, //动画时间,值越小速度越快
// brushType: 'stroke', //波纹绘制方式 stroke, fill
// scale: 8, //波纹圆环最大限制,值越大波纹越大
// color: '#ffaa00',
// },
symbol: 'circle', //标记的图形
symbolSize: 8,
itemStyle: {
show: false,
color: '#ffaa00',
},
emphasis: {
disabled: true,
},
data: [],
},
{
name: 'pin',
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'pin',
// symbolOffset: [0, '-10%'],
symbolSize: 40,
tooltip: {
show: true,
trigger: 'item',
formatter: function (e) {
// return `设备id: ${e.name}\n经纬度: ${e.value[2]}`
if (e.name.length === 1) {
return `设备数量: 1`;
} else if (e.name.length > 1) {
return `设备数量: ${e.name.split(',').length}`;
}
},
borderColor: '#ffaa00',
backgroundColor: '#fefefe',
},
label: {
show: true,
color: '#fff',
fontSize: 17,
formatter: (e) => {
if (e.name.length === 1) {
return e.name.length;
} else if (e.name.length > 1) {
return e.name.split(',').length;
} else {
return '';
}
},
},
itemStyle: {
color: '#eb9d00', //标志颜色
borderColor: '#fff',
// borderWidth: 2,
opacity: 1,
},
zlevel: 3,
data: [],
},
],
},
}
},
// 2. 监听数据的变化
watch:{
// 当数据发生变化时, 重新在地图上打点
pointData:{
handler(){
if (this.isHighLevel) {
// 地图缩放层级高, 展示精细定位数据
this.option.series[0].data = this.pointData;
this.option.series[1].data = this.pointData;
} else {
this.option.series[0].data = this.filterPointArr;
this.option.series[1].data = this.filterPointArr;
}
this.mapChart.setOption(this.option, true);
},
deep:true
}
},
mounted() {
// 1. 必须使用 $nextTick 获取最新更新的dom
this.$nextTick(() => {
echarts.registerMap('china', chinaMap)
this.initMap('china')
});
},
methods: {
/**
* echarts 初始化地图
* @param mapType
*/
initMap(mapType) {
this.mapReset()
this.mapChart = echarts.init(document.getElementById('scatter'))
this.option.geo.map = mapType
// 配置中国地图 或 世界地图的配置
if (mapType === 'china') {
this.option.geo.zoom = 1.5;
this.option.geo.center = ['98', '35'];
this.option.geo.label.show = true;
} else {
this.option.geo.zoom = 1;
this.option.geo.center = '';
this.option.geo.label.show = true;
}
this.mapChart.setOption(this.option, true)
},
/**
* echarts 重置地图配置
*/
mapReset() {
this.mapChart && this.mapChart.dispose()
this.mapChart = null
}
},
props: {
pointData: Array,
filterPointArr: Array,
},
}
</script>
<style lang="less" scoped>
#scatter {
width: 1920px;
height: 1080px;
}
.mapBack {
padding: 8px 14px;
font-size: 15px;
color: #bdddfd;
background-color: #1c4c7c;
position: absolute;
left: 425px;
margin-top: 20px;
z-index: 9;
white-space: nowrap;
}
</style>
4. 地图缩放、拖拽
``
<template>
<div style="width: 100%; height: 1080%">
<div id="scatter"></div>
</div>
</template>
<script>
import * as chinaMap from '@/static/map/china.json'
import * as echarts from 'echarts';
export default {
name: "mapChina",
data() {
return {
levelData: [],
mapChart: null,
isHighLevel: false,
option: {
animation: false,
tooltip: {},
geo: {
map: 'china', // 地图类型, 这里是中国地图
zoom: 1.5, // 地图默认缩放等级
center: [98, 34.5], // 地图中心经纬度
roam: true, //是否允许缩放 - 拖拽
// selectedMode: "single", //点击省份高亮 single / multiple
animationDurationUpdate: 0, //地图移动的时候,渲染的点跟着移动,但是会有延迟,值为0,则无需延迟
scaleLimit: {
min: 0.7,
// max: 8.0,
},
label: {
show: true, // 显示省份
color: '#eaeaea',
fontSize: 16,
},
itemStyle: {
areaColor: '#2971c3', //#2971c3 #228fba #3a7fd5
borderColor: '#0299e2', //#0e335e #0299e2
borderWidth: 2,
// shadowBlur: 10,
// shadowOffsetX: 2,
// shadowOffsetY: 2,
// shadowColor: '#0e335e',
},
//hover状态下的多边形和标签样式
emphasis: {
// disabled: true, //是否关闭高亮状态
focus: 'none', //是否淡出其它数据的图形 'self' / 'none'
label: {
show: true,
color: '#eaeaea',
},
itemStyle: {
areaColor: '#39c5cf',
color: '#0066CC',
},
},
tooltip: {
show: false,
},
data: [],
},
// 3. 添加地图数据的配置项
series: [
{
type: 'scatter', //scatter, effectScatter(涟漪)
coordinateSystem: 'geo',
// zlevel: 2,
// rippleEffect: {
// //涟漪特效
// number: 3, //环数
// period: 4, //动画时间,值越小速度越快
// brushType: 'stroke', //波纹绘制方式 stroke, fill
// scale: 8, //波纹圆环最大限制,值越大波纹越大
// color: '#ffaa00',
// },
symbol: 'circle', //标记的图形
symbolSize: 8,
itemStyle: {
show: false,
color: '#ffaa00',
},
emphasis: {
disabled: true,
},
data: [],
},
{
name: 'pin',
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'pin',
// symbolOffset: [0, '-10%'],
symbolSize: 40,
tooltip: {
show: true,
trigger: 'item',
formatter: function (e) {
// return `设备id: ${e.name}\n经纬度: ${e.value[2]}`
if (e.name.length === 1) {
return `设备数量: 1`;
} else if (e.name.length > 1) {
return `设备数量: ${e.name.split(',').length}`;
}
},
borderColor: '#ffaa00',
backgroundColor: '#fefefe',
},
label: {
show: true,
color: '#fff',
fontSize: 17,
formatter: (e) => {
if (e.name.length === 1) {
return e.name.length;
} else if (e.name.length > 1) {
return e.name.split(',').length;
} else {
return '';
}
},
},
itemStyle: {
color: '#eb9d00', //标志颜色
borderColor: '#fff',
// borderWidth: 2,
opacity: 1,
},
zlevel: 3,
data: [],
},
],
},
}
},
methods: {
/**
* echarts 初始化地图
* @param mapType
*/
initMap(mapType) {
// ......
// 1. 注册地图拖拽、缩放事件
this.listenerGeoRoam()
},
// 2. 地图拖拽、缩放事件的回调函数
listenerGeoRoam() {
// 注册地图的缩放、拖拽事件及其回调函数
this.mapChart.on('geoRoam', (params) => {
if (params.dy || params.dx) return
const _option = this.mapChart.getOption()
if (params.zoom != null && params.zoom != undefined) {
if (this.levelData.length === 1) {
// 缩放等级大于 1.5
if (_option.geo[0].zoom > 1.5) {
if (this.roamFlag > 1.5 && _option.geo[0].zoom > this.roamFlag) {
return;
}
// 重置数据
this.isHighLevel = true;
this.option.series[0].data = this.pointData;
this.option.series[1].data = this.pointData;
this.option.geo.zoom = _option.geo[0].zoom;
this.mapChart.setOption(this.option, true);
this.roamFlag = _option.geo[0].zoom;
} else {
if (_option.geo[0].zoom <= 1) return;
this.isHighLevel = false;
this.option.series[0].data = this.pointData;
this.option.series[1].data = this.pointData;
this.option.geo.zoom = _option.geo[0].zoom;
this.mapChart.setOption(this.option, true);
this.roamFlag = _option.geo[0].zoom;
}
}
}
})
}
},
props: {
pointData: Array,
filterPointArr: Array,
},
}
</script>
<style lang="less" scoped>
#scatter {
width: 1920px;
height: 1080px;
}
.mapBack {
padding: 8px 14px;
font-size: 15px;
color: #bdddfd;
background-color: #1c4c7c;
position: absolute;
left: 425px;
margin-top: 20px;
z-index: 9;
white-space: nowrap;
}
</style>
5. 地图点击
npm i lodash
<template>
<div style="width: 100%; height: 1080%">
<div id="scatter"></div>
</div>
</template>
<script>
import * as chinaMap from '@/static/map/china.json'
import * as echarts from 'echarts';
import {city, county, province} from '@/utils/map/mapNameList';
import {throttle} from 'lodash'
export default {
name: "mapChina",
data() {
return {
levelData: [],
mapChart: null,
isHighLevel: false,
roamFlag: 0,
option: {
animation: false,
tooltip: {},
geo: {
map: 'china', // 地图类型, 这里是中国地图
zoom: 1.5, // 地图默认缩放等级
center: [98, 34.5], // 地图中心经纬度
roam: true, //是否允许缩放 - 拖拽
// selectedMode: "single", //点击省份高亮 single / multiple
animationDurationUpdate: 0, //地图移动的时候,渲染的点跟着移动,但是会有延迟,值为0,则无需延迟
scaleLimit: {
min: 0.7,
// max: 8.0,
},
label: {
show: true, // 显示省份
color: '#eaeaea',
fontSize: 16,
},
itemStyle: {
areaColor: '#2971c3', //#2971c3 #228fba #3a7fd5
borderColor: '#0299e2', //#0e335e #0299e2
borderWidth: 2,
// shadowBlur: 10,
// shadowOffsetX: 2,
// shadowOffsetY: 2,
// shadowColor: '#0e335e',
},
//hover状态下的多边形和标签样式
emphasis: {
// disabled: true, //是否关闭高亮状态
focus: 'none', //是否淡出其它数据的图形 'self' / 'none'
label: {
show: true,
color: '#eaeaea',
},
itemStyle: {
areaColor: '#39c5cf',
color: '#0066CC',
},
},
tooltip: {
show: false,
},
data: [],
},
// 3. 添加地图数据的配置项
series: [
{
type: 'scatter', //scatter, effectScatter(涟漪)
coordinateSystem: 'geo',
// zlevel: 2,
// rippleEffect: {
// //涟漪特效
// number: 3, //环数
// period: 4, //动画时间,值越小速度越快
// brushType: 'stroke', //波纹绘制方式 stroke, fill
// scale: 8, //波纹圆环最大限制,值越大波纹越大
// color: '#ffaa00',
// },
symbol: 'circle', //标记的图形
symbolSize: 8,
itemStyle: {
show: false,
color: '#ffaa00',
},
emphasis: {
disabled: true,
},
data: [],
},
{
name: 'pin',
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'pin',
// symbolOffset: [0, '-10%'],
symbolSize: 40,
tooltip: {
show: true,
trigger: 'item',
formatter: function (e) {
// return `设备id: ${e.name}\n经纬度: ${e.value[2]}`
if (e.name.length === 1) {
return `设备数量: 1`;
} else if (e.name.length > 1) {
return `设备数量: ${e.name.split(',').length}`;
}
},
borderColor: '#ffaa00',
backgroundColor: '#fefefe',
},
label: {
show: true,
color: '#fff',
fontSize: 17,
formatter: (e) => {
if (e.name.length === 1) {
return e.name.length;
} else if (e.name.length > 1) {
return e.name.split(',').length;
} else {
return '';
}
},
},
itemStyle: {
color: '#eb9d00', //标志颜色
borderColor: '#fff',
// borderWidth: 2,
opacity: 1,
},
zlevel: 3,
data: [],
},
],
},
}
},
methods: {
/**
* echarts 初始化地图
* @param mapType
*/
initMap(mapType) {
this.mapReset()
this.mapChart = echarts.init(document.getElementById('scatter'))
this.option.geo.map = mapType
// 配置中国地图 或 世界地图的配置
if (mapType === 'china') {
this.option.geo.zoom = 1.5;
this.option.geo.center = ['98', '35'];
this.option.geo.label.show = true;
} else {
this.option.geo.zoom = 1;
this.option.geo.center = '';
this.option.geo.label.show = true;
}
this.mapChart.setOption(this.option, true)
// 注册事件
this.listenerClick()
},
/**
* echarts 重置地图配置
*/
mapReset() {
this.mapChart && this.mapChart.dispose()
this.mapChart = null
},
// 地图点击回调函数 ( 使用 lodash 库中的 throttle 来做节流处理)
listenerClick: throttle(
function () {
this.mapChart.on('click', (param) => {
// 如果点击的是地图中的省份, 则展示对应省份的地图
if (param.name in province) {
this.option.series[0].data = this.pointData;
this.option.series[1].data = this.pointData;
this.roamFlag = 0;
let names = param.name
for (let key in province) {
if (names === key) {
this.showProvince(province[key], key)
break
}
}
} else if (param.name in city) { // 如果点击的是地图中的市, 则展示对应市的地图
this.option.series[0].data = this.pointData;
this.option.series[1].data = this.pointData;
this.roamFlag = 0;
// 点击市
let names = param.name;
for (let key in city) {
if (names === key) {
this.showCity(city[key], key);
break;
}
}
} else if (param.name in county) {
// 点击区
this.option.series[0].data = this.filterPointArr;
this.option.series[1].data = this.filterPointArr;
this.roamFlag = 0;
let names = param.name;
for (let key in county) {
if (names === key) {
this.showCounty(county[key], key);
break;
}
}
}
})
},
1000, {
leading: false,
trailing: true
}
),
// 地图中展示对应的省的地图
showProvince(pName) {
let cityJSON = require('@/static/map/province/' + pName + '.json');
this.mapReset()
echarts.registerMap(pName, cityJSON) // 重新注册地图, 地图类型为省级地图, 城市 JSON 文件
this.initMap(pName)
this.levelData = []
this.addLevelData('province', pName);
},
// 地图中展示对应的市的地图
showCity(cName) {
let cityJSON = require('@/static/map/city/' + cName + '.json');
this.mapReset()
echarts.registerMap(cName, cityJSON) // 重新注册地图, 地图类型为省级地图, 城市 JSON 文件
this.initMap(cName)
this.levelData = []
this.addLevelData('city', cName);
},
// 地图中展示对应的区/县的地图
showCounty(cName) {
if (cName === '330205' && this.levelData.length < 2) return; //重庆 - 浙江省宁波市 都有江北区
let cityJSON = require('@/static/map/county/' + cName + '.json');
this.mapReset();
echarts.registerMap(cName, cityJSON);
this.initMap(cName);
},
// 缓存下个层级的地图
addLevelData(level, name) {
if (this.levelData.length === 0) {
this.levelData.push({
level: level,
name: name
})
return
}
let flag = false;
for (let k = 0; k < this.levelData.length; k++) {
if (this.levelData[k].name !== name) {
flag = true;
}
}
if (flag) {
this.levelData.push({
level: level,
name: name,
});
flag = false;
return;
}
}
},
props: {
pointData: Array,
filterPointArr: Array,
},
}
</script>
<style lang="less" scoped>
#scatter {
width: 1920px;
height: 1080px;
}
.mapBack {
padding: 8px 14px;
font-size: 15px;
color: #bdddfd;
background-color: #1c4c7c;
position: absolute;
left: 425px;
margin-top: 20px;
z-index: 9;
white-space: nowrap;
}
</style>
6. 鼠标右键返回上一级地图
<template>
<div style="width: 100%; height: 1080%">
<div id="scatter"></div>
</div>
</template>
<script>
import * as chinaMap from '@/static/map/china.json'
import * as echarts from 'echarts';
import {city, county, province} from '@/utils/map/mapNameList';
import {throttle} from 'lodash'
export default {
name: "mapChina",
data() {
return {
levelData: [],
mapChart: null,
isHighLevel: false,
roamFlag: 0,
option: {
animation: false,
tooltip: {},
geo: {
map: 'china', // 地图类型, 这里是中国地图
zoom: 1.5, // 地图默认缩放等级
center: [98, 34.5], // 地图中心经纬度
roam: true, //是否允许缩放 - 拖拽
// selectedMode: "single", //点击省份高亮 single / multiple
animationDurationUpdate: 0, //地图移动的时候,渲染的点跟着移动,但是会有延迟,值为0,则无需延迟
scaleLimit: {
min: 0.7,
// max: 8.0,
},
label: {
show: true, // 显示省份
color: '#eaeaea',
fontSize: 16,
},
itemStyle: {
areaColor: '#2971c3', //#2971c3 #228fba #3a7fd5
borderColor: '#0299e2', //#0e335e #0299e2
borderWidth: 2,
// shadowBlur: 10,
// shadowOffsetX: 2,
// shadowOffsetY: 2,
// shadowColor: '#0e335e',
},
//hover状态下的多边形和标签样式
emphasis: {
// disabled: true, //是否关闭高亮状态
focus: 'none', //是否淡出其它数据的图形 'self' / 'none'
label: {
show: true,
color: '#eaeaea',
},
itemStyle: {
areaColor: '#39c5cf',
color: '#0066CC',
},
},
tooltip: {
show: false,
},
data: [],
},
// 3. 添加地图数据的配置项
series: [
{
type: 'scatter', //scatter, effectScatter(涟漪)
coordinateSystem: 'geo',
// zlevel: 2,
// rippleEffect: {
// //涟漪特效
// number: 3, //环数
// period: 4, //动画时间,值越小速度越快
// brushType: 'stroke', //波纹绘制方式 stroke, fill
// scale: 8, //波纹圆环最大限制,值越大波纹越大
// color: '#ffaa00',
// },
symbol: 'circle', //标记的图形
symbolSize: 8,
itemStyle: {
show: false,
color: '#ffaa00',
},
emphasis: {
disabled: true,
},
data: [],
},
{
name: 'pin',
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'pin',
// symbolOffset: [0, '-10%'],
symbolSize: 40,
tooltip: {
show: true,
trigger: 'item',
formatter: function (e) {
// return `设备id: ${e.name}\n经纬度: ${e.value[2]}`
if (e.name.length === 1) {
return `设备数量: 1`;
} else if (e.name.length > 1) {
return `设备数量: ${e.name.split(',').length}`;
}
},
borderColor: '#ffaa00',
backgroundColor: '#fefefe',
},
label: {
show: true,
color: '#fff',
fontSize: 17,
formatter: (e) => {
if (e.name.length === 1) {
return e.name.length;
} else if (e.name.length > 1) {
return e.name.split(',').length;
} else {
return '';
}
},
},
itemStyle: {
color: '#eb9d00', //标志颜色
borderColor: '#fff',
// borderWidth: 2,
opacity: 1,
},
zlevel: 3,
data: [],
},
],
},
}
},
// 2. 监听数据的变化
watch: {
// 当数据发生变化时, 重新在地图上打点
pointData: {
handler() {
if (this.isHighLevel) {
// 地图缩放层级高, 展示精细定位数据
this.option.series[0].data = this.pointData;
this.option.series[1].data = this.pointData;
} else {
this.option.series[0].data = this.filterPointArr;
this.option.series[1].data = this.filterPointArr;
}
this.mapChart.setOption(this.option, true);
},
deep: true
}
},
mounted() {
// 1. 必须使用 $nextTick 获取最新更新的dom
this.$nextTick(() => {
echarts.registerMap('china', chinaMap)
this.initMap('china')
});
},
methods: {
/**
* echarts 初始化地图
* @param mapType
*/
initMap(mapType) {
this.mapReset()
this.mapChart = echarts.init(document.getElementById('scatter'))
this.option.geo.map = mapType
// 配置中国地图 或 世界地图的配置
if (mapType === 'china') {
this.option.geo.zoom = 1.5;
this.option.geo.center = ['98', '35'];
this.option.geo.label.show = true;
} else {
this.option.geo.zoom = 1;
this.option.geo.center = '';
this.option.geo.label.show = true;
}
this.mapChart.setOption(this.option, true)
// 注册事件
this.listenerContextmenu(); //监听鼠标右键 (返回中国地图页)
},
/**
* echarts 重置地图配置
*/
mapReset() {
this.mapChart && this.mapChart.dispose()
this.mapChart = null
},
// 监听鼠标右键点击事件, 返回中国地图页
listenerContextmenu() {
// 取消右键单机默认事件
let mapRight = document.querySelector('#scatter');
mapRight.oncontextmenu = function () {
return false;
};
//右键单击返回上一级地图
this.mapChart.on('contextmenu', () => {
this.mapBack();
});
},
// 地图返回中国地图页的回调函数
mapBack() {
this.isHighLevel = false;
this.option.series[0].data = this.filterPointArr;
this.option.series[1].data = this.filterPointArr;
this.roamFlag = 0;
// 当 缓存的地图层级-数组 为空时 => 中国地图, 不再执行返回
if (!this.levelData.length) {
echarts.registerMap('china', chinaMap);
this.initMap('china');
}
if (this.levelData.length === 0 || this.levelData.length === 1) {
this.levelData = [];
this.mapReset();
echarts.registerMap('china', chinaMap);
this.initMap('china');
return;
}
let thisLevelData = this.levelData.pop();
thisLevelData = this.levelData.pop();
let jSON = require('@/static/map/' + thisLevelData.level + '/' + thisLevelData.name + '.json');
this.mapReset();
echarts.registerMap(thisLevelData.name, jSON);
this.initMap(thisLevelData.name);
this.levelData.push(thisLevelData);
},
},
props: {
pointData: Array,
filterPointArr: Array,
},
}
</script>
<style lang="less" scoped>
#scatter {
width: 1920px;
height: 1080px;
}
.mapBack {
padding: 8px 14px;
font-size: 15px;
color: #bdddfd;
background-color: #1c4c7c;
position: absolute;
left: 425px;
margin-top: 20px;
z-index: 9;
white-space: nowrap;
}
</style>
9. 参考博客
https://blog.csdn.net/m0_52539553/article/details/138074255
python防脱发技巧

浙公网安备 33010602011771号