一. 地圖數(shù)據(jù)獲取
- 全國及省市地圖可以直接在[阿里云數(shù)據(jù)可視化平臺](https://datav.aliyun.com/portal/school/atlas/area_selector)獲取
- 工業(yè)園/學(xué)校等自定義地圖可以在數(shù)據(jù)編輯器模塊自己繪制, 并導(dǎo)出GeoJSON地圖數(shù)據(jù)
二. 地圖注冊
- 1. 地圖JSON數(shù)據(jù)保存到j(luò)s文件
```
export const xiangaoxin = {...}
```
- 2. 地圖注冊
- 全國及省市地圖可以直接注冊到echarts
```
import { chinaData } from '@/assets/js/china.js';
import * as echarts from "echarts";
// 注冊中國地圖
echarts.registerMap('china', chinaData);
```
- 自制地圖只注冊面數(shù)據(jù), 點(diǎn)和線通過后期echarts渲染添加
```
import { xiangaoxin } from '@/assets/js/xiangaoxin.js';
import * as echarts from "echarts";
// 拆分面數(shù)據(jù)
const polygonsData = transformedGeoJSON.features
.filter(f => f.geometry.type === 'Polygon').map(p => {
return {
"type": "Feature",
"properties": { "name": "北京" },
"geometry": {
"type": "Polygon",
"coordinates": p.geometry.coordinates
}
};
});
// 注冊園區(qū)地圖
echarts.registerMap('xiangaoxin1', {
"type": "FeatureCollection",
"features": polygonsData
});
```
三. 地圖渲染完整代碼如下
```
<template>
<div class="content-container" :style="{ backgroundImage: `url(${DashboardBg})` }">
<div ref="mapChartRef" style="width: calc(100% - 15px); height: calc(100vh - 15px);">
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from 'vue';
import * as echarts from "echarts";
import { getVisitorMapStatsInfo } from '@/services/statsService';
import DashboardBg from '@/assets/img/dashboard/bg.jpg';
import { xiangaoxin1 } from '@/assets/js/xiangaoxin1.js';
import { gcj02towgs84 } from 'coordtransform';
/**
* 園區(qū)中心點(diǎn)經(jīng)緯度
* 各個門崗點(diǎn)加字段
* RegionId
* RegionName
*/
// 地圖綁定對象
let mapChartObj = null;
// 點(diǎn)位數(shù)據(jù)
let pointData = null;
// 線條數(shù)據(jù)
let lineData = null;
// 面數(shù)據(jù)
let polygonsData = null;
// 圖表依賴元素
const mapChartRef = ref();
onMounted(() => {
// 監(jiān)聽窗口大小變化,自適應(yīng)調(diào)整圖表
window.addEventListener('resize', () => {
if (mapChartObj) {
mapChartObj.resize();
}
});
// 地圖數(shù)據(jù)初始化
mapDataInit();
// 注冊園區(qū)地圖
echarts.registerMap('xiangaoxin1', {
"type": "FeatureCollection",
"features": polygonsData
});
// 圖表渲染
renderChart();
});
// 地圖數(shù)據(jù)初始化
const mapDataInit = () => {
const transformedGeoJSON = JSON.parse(JSON.stringify(xiangaoxin1));
transformedGeoJSON.features.forEach(feature => {
feature.geometry.coordinates = transformCoordinates(feature.geometry.coordinates);
});
// 地圖點(diǎn)位
pointData = transformedGeoJSON.features
.filter(f => f.geometry.type === 'Point').map(f => {
return {
name: f.properties.ElementName,
value: f.geometry.coordinates, // [經(jīng)度, 緯度]
}
});
// 地圖線條
lineData = transformedGeoJSON.features
.filter(f => f.geometry.type === 'LineString').map(feature => {
return {
name: feature.properties.name,
coords: feature.geometry.coordinates, // 線的坐標(biāo)數(shù)組
lineStyle: {
width: 5, // 線寬
color: '#3C9BE5',
opacity: 0.8
},
// 可根據(jù)屬性設(shè)置線的視覺效果
effect: {
show: true,
symbol: 'arrow',
symbolSize: 6,
trailLength: 0.5
}
}
});
// 地圖面
polygonsData = transformedGeoJSON.features
.filter(f => f.geometry.type === 'Polygon').map(p => {
return {
"type": "Feature",
"properties": { "name": "北京" },
"geometry": {
"type": "Polygon",
"coordinates": p.geometry.coordinates
}
};
});
};
// 遞歸轉(zhuǎn)換GeoJSON中的所有坐標(biāo)
const transformCoordinates = (coords) => {
if (Array.isArray(coords[0])) {
return coords.map(coord => transformCoordinates(coord));
} else {
// coords格式:[經(jīng)度, 緯度]
const [lon, lat] = gcj02towgs84(coords[0], coords[1]);
return [lon, lat];
}
}
const renderChart = () => {
setTimeout(() => {
if (!mapChartObj) {
mapChartObj = echarts.init(mapChartRef.value);
mapChartObj.on('click', function (param) {
console.log(param);
if (param.componentType == 'series' &&
param.componentSubType == 'effectScatter') {
console.log(param.data.name);
console.log(param.data.value);
}
});
let option = getOption();
mapChartObj.setOption(option);
setMapData();
}
}, 50);
}
const getOption = () => {
// 平面地圖配置
// let option = {
// visualMap: {
// type: "piecewise",
// show: false,
// min: 0,
// max: 1000000,
// left: "28%",
// bottom: "25%",
// showLabel: true,
// textStyle: {
// color: "#AAAAAA",
// },
// },
// geo: {
// map: "xiangaoxin1",
// // 默認(rèn)縮放比
// zoom: 0.8,
// top: "30%",
// // 縮放拖拽
// roam: true,
// scaleLimit: {
// min: 0.8, // 最小縮放比例(0.5倍)
// max: 1 // 最大縮放比例(3倍)
// },
// label: {
// // 正常情況是否顯示
// normal: {
// show: false,
// fontSize: "14",
// color: "#00D9A9",
// },
// // 鼠標(biāo)懸停是否顯示
// emphasis: {
// show: false
// }
// },
// // 設(shè)置視角中心點(diǎn)
// center: [108.841, 34.175],
// // 設(shè)置地圖樣式
// itemStyle: {
// // 地圖區(qū)域顏色
// areaColor: '#00254C',
// // 分界線顏色
// borderColor: '#00B0C4',
// borderWidth: '2',
// emphasis: {
// areaColor: '#006A83',
// }
// }
// },
// series: [
// {
// // 有擴(kuò)散效果的散點(diǎn)圖
// type: 'scatter',
// coordinateSystem: 'geo',
// // 標(biāo)記位置, value 前兩個值為經(jīng)緯度, 第三個值為渲染值
// data: [
// { name: '東門', value: [108.8458, 34.1806, 300] }
// ],
// // data: pointData,
// // 小紅旗
// symbol: "image://data:image/png;base64,iVBOR...EdkKMAAAAASUVORK5CYII=",
// symbolSize: (value, params) => {
// // console.log(value);
// return 30; // 根據(jù)第三個數(shù)值調(diào)整尺寸
// },
// // 標(biāo)記label顏色
// itemStyle: { color: '#FFFFFF' },
// label: {
// // 直接顯示
// show: true,
// position: 'top',
// formatter: function(params) {
// // 自定義顯示內(nèi)容,例如顯示名稱和坐標(biāo)值
// return `${params.name}\n設(shè)備數(shù) ${params.value[2]}`;
// },
// // 鼠標(biāo)懸浮顯示
// emphasis: {
// show: true
// },
// color: '#67DDFF'
// }
// }
// ],
// };
const option = {
// 3D 地圖配置
geo3D: {
show: true,
map: 'xiangaoxin1', // 'xiangaoxin1',
// 調(diào)整地圖顯示角度和大小
boxWidth: 60,
// 整個3D盒子高度
boxHeight: 15,
boxDepth: 80,
// 地圖區(qū)域高度
regionHeight: 2,
// ### environment 1 環(huán)境光('auto' 自動適應(yīng))
environment: 'auto',
instancing: false,
// 三維地理坐標(biāo)系組件 中三維圖形的視覺屬性,包括顏色,透明度,描邊等
itemStyle: {
color: '#00254C',
opacity: 0.3,
borderWidth: 1,
borderColor: '#00B0C4',
},
viewControl: {
autoRotate: false, // 自動旋轉(zhuǎn)
rotateSensitivity: 1, // 旋轉(zhuǎn)靈敏度
zoomSensitivity: 0, // 縮放靈敏度
panSensitivity: 0,
projection: 'perspective',
distance: 180,
alpha: 45,
beta: 3,
minDistance: 80,
maxDistance: 120,
minAlpha: -100,
maxAlpha: 100,
minBeta: -100,
maxBeta: 100
},
emphasis: {
label: {
show: false,
fontSize: "12",
distance: 10,
color: "#00254C",
textStyle: {
borderWidth: 1,
borderColor: '#000000',
fontSize: 12,
// normal bold bolder lighter
fontWeight: 'normal'
}
},
itemStyle: {
color: '#006A83',
opacity: 0.3
}
},
shading: 'lambert',
},
// 3D線條
series: [{
type: 'lines3D', // 3D線條類型
coordinateSystem: 'geo3D', // 關(guān)聯(lián)3D地理坐標(biāo)系
polyline: true, // 是否為直線
data: lineData, // 線條數(shù)據(jù)
// 線條樣式
lineStyle: {
width: 4,
color: '#469EF7',
opacity: 1
},
// 線條特效
// effect: {
// show: true,
// symbol: 'circle',
// symbolSize: 6,
// period: 3,
// trailLength: 0.4
// },
// 鼠標(biāo)交互
emphasis: {
lineStyle: {
width: 5,
color: '#00B0C4'
}
}
// 3D點(diǎn)位
}, {
type: 'scatter3D', // 3D點(diǎn)類型
coordinateSystem: 'geo3D', // 關(guān)聯(lián)3D地理坐標(biāo)系
data: pointData, // 點(diǎn)數(shù)據(jù)
// 點(diǎn)的樣式
symbol: 'circle', // 點(diǎn)形狀(circle, diamond, triangle等)
symbolSize: 12, // 基礎(chǔ)大小(會被數(shù)據(jù)中的symbolSize覆蓋)
// 點(diǎn)的顏色映射(也可通過itemStyle單獨(dú)設(shè)置)
colorBy: 'data',
itemStyle: {
color: '#10FCB0',
// borderWidth: '0.1',
// borderColor: '#FFFFFF'
},
// 鼠標(biāo)交互效果
emphasis: {
itemStyle: {
color: '#FFCC00',
shadowBlur: 10
},
scale: true // 懸停時放大
},
label: {
show: true,
formatter: ''
},
// 點(diǎn)的動畫效果
animationDurationUpdate: 1000,
animationEasingUpdate: 1000,
animationEasing: 'elasticOut',
// 閃爍配置
blink: {
enable: true,
speed: 500, // 閃爍周期(ms):快/慢
minOpacity: 0.3, // 最小透明度
maxOpacity: 1 // 最大透明度
}
}]
};
return option;
}
// 3. 計(jì)算地圖中心坐標(biāo)(用于定位)
const getMapCenter = (geoJSON) => {
let lonSum = 0, latSum = 0, count = 0;
function collectCoords(coords) {
if (typeof coords[0] === 'number') {
lonSum += coords[0];
latSum += coords[1];
count++;
} else {
coords.forEach(coord => collectCoords(coord));
}
}
geoJSON.features.forEach(feature => {
collectCoords(feature.geometry.coordinates);
});
return [lonSum / count, latSum / count];
}
// 設(shè)置地圖數(shù)據(jù)
const setMapData = () => {
// getVisitorMapStatsInfo({}, (result: ResultModel) => {
// const dataList = result.Data.map((item) => {
// return {
// name: item.WorkPlacename,
// value: [item.Longitude, item.Latitude, item.Amount]
// };
// });
// if (mapChartObj) {
// mapChartObj.setOption({
// series: [{
// data: dataList
// }]
// });
// }
// });
};
// 組件卸載時銷毀圖表
onUnmounted(() => {
if (mapChartObj) {
mapChartObj.dispose();
mapChartObj = null;
}
});
onUnmounted(() => {
clearInterval(intervalId);
});
defineExpose({
renderChart
});
</script>
<style lang="less" scoped>
.content-container {
min-width: 1450;
height: 100vh;
background-color: #FFFFFF;
position: relative;
.map {
position: absolute;
z-index: 1;
}
.l1 {
position: absolute;
z-index: 2;
top: 20px;
left: 20px;
}
.r1 {
position: absolute;
z-index: 2;
top: 20px;
right: 20px;
}
}
.global-tabs {
::v-deep(.el-tabs__nav-scroll) {
padding: 20px 0 0 20px;
}
::v-deep(.el-tabs__item) {
// --el-font-size-base: 16px;
font-weight: 600;
}
}
::v-deep(.el-tabs__nav-wrap:after) {
background: none;
}
::v-deep(.el-tabs__item.is-active, .el-tabs__item:hover) {
color: #00CEFF;
}
::v-deep(.el-tabs__item) {
color: #0095B8;
}
::v-deep(.el-tabs__nav) {
padding-left: 10px;
}
</style>
```