2025-05-19 13:20:29 +08:00

391 lines
9.8 KiB
Vue

<template>
<div class="map-center-warp">
<div class="map-pos">
<custom-echart-maps height="100%" width="100%" :option="chartsData.option" :geo="geoData" :name="mapName" @click="mapClick" />
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue';
import { useRoute } from 'vue-router';
import * as echarts from 'echarts';
import geoJsonData from './china.json'; // 根据实际情况调整路径;
const route = useRoute();
const props = defineProps({
dialogTitle: {
type: String,
default: '首页',
},
});
const isShow = ref(false);
let geoData = geoJsonData;
let mapName = ref('china');
const chinaGeoCoordMap = ref({
云南: [102.9199, 25.4663],
广东: [113.12244, 23.009505],
香港: [114.133834, 22.381374],
四川: [104.063707, 30.658753],
河北: [114.511072, 38.054693],
北京: [116.46, 39.92],
浙江: [120.19, 30.26],
山东: [117, 36.65],
福建: [119.3, 26.08],
上海: [121.48, 31.22],
重庆: [106.54, 29.59],
江西: [115.89, 28.68],
山西: [112.53, 37.87],
黑龙江: [126.63, 45.75],
陕西: [108.95, 34.27],
辽宁: [123.38, 41.8],
海南: [110.35, 20.02],
湖南: [113, 28.21],
宁夏: [106.27, 38.47],
湖北: [114.31, 30.52],
内蒙古: [111.65, 40.82],
天津: [117.2, 39.13],
贵州: [106.71, 26.57],
甘肃: [103.73, 36.03],
江苏: [118.78, 32.04],
吉林: [125.35, 43.88],
河南: [113.65, 34.76],
青海: [101.74, 36.56],
安徽: [117.27, 31.86],
广西: [108.33, 22.84],
西藏: [91.11, 29.97],
新疆: [87.68, 43.77],
});
const chinaDatas = ref([
[{ name: '云南', value: 382 }],
[{ name: '广东', value: 62256 }],
[{ name: '香港', value: 9256 }],
[{ name: '四川', value: 1256 }],
[{ name: '河北', value: 382 }],
[{ name: '北京', value: 88 }],
[{ name: '浙江', value: 87 }],
[{ name: '山东', value: 87 }],
[{ name: '福建', value: 87 }],
[{ name: '上海', value: 87 }],
[{ name: '重庆', value: 87 }],
[{ name: '江西', value: 86 }],
[{ name: '山西', value: 84 }],
[{ name: '黑龙江', value: 83 }],
[{ name: '陕西', value: 83 }],
[{ name: '辽宁', value: 82 }],
[{ name: '海南', value: 82 }],
[{ name: '湖南', value: 82 }],
[{ name: '宁夏', value: 82 }],
[{ name: '湖北', value: 81 }],
[{ name: '内蒙古', value: 81 }],
[{ name: '天津', value: 80 }],
[{ name: '贵州', value: 80 }],
[{ name: '甘肃', value: 80 }],
[{ name: '江苏', value: 80 }],
[{ name: '吉林', value: 80 }],
[{ name: '河南', value: 79 }],
[{ name: '青海', value: 79 }],
[{ name: '广西', value: 78 }],
[{ name: '安徽', value: 77 }],
[{ name: '新疆', value: 76 }],
[{ name: '西藏', value: 76 }],
]);
// 设置扩散中心
const convertData = (data) => {
var res = [];
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
var fromCoord = [102.9199, 25.4663];
var toCoord = chinaGeoCoordMap.value[dataItem[0].name];
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord,
value: dataItem[0].value,
},
{
coord: toCoord,
},
]);
}
}
return res;
};
const getSeries = () => {
let list = [];
[['云南', chinaDatas.value]].forEach(function (item, i) {
list.push(
{
type: 'lines',
zlevel: 1,
effect: {
show: true,
period: 4, //箭头指向速度,值越小速度越快
trailLength: 0.02, //特效尾迹长度[0,1]值越大,尾迹越长重
symbol: 'arrow', //箭头图标
symbolSize: 5, //图标大小
},
lineStyle: {
normal: {
width: 1, //尾迹线条宽度
opacity: 1, //尾迹线条透明度
curveness: 0.3, //尾迹线条曲直度
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#0096FF' },
{ offset: 1, color: '#00FF00' },
]),
},
},
data: convertData(item[1]),
},
{
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
//涟漪特效
period: 4, //动画时间,值越小速度越快
brushType: 'stroke', //波纹绘制方式 stroke, fill
scale: 4, //波纹圆环最大限制,值越大波纹越大
},
label: {
normal: {
show: true,
position: 'right', //显示位置
offset: [5, 0], //偏移设置
formatter: function (params) {
//圆环显示文字
return params.data.name;
},
fontSize: 10,
},
emphasis: {
show: true,
},
},
symbol: 'circle',
symbolSize: function (val) {
return 3 + (val[2] / 2000) * 1; //圆环大小
},
itemStyle: {
normal: {
show: false,
color: '#FFA54F',
},
},
data: item[1].map(function (dataItem) {
return {
name: dataItem[0].name,
value: chinaGeoCoordMap.value[dataItem[0].name].concat([dataItem[0].value]),
};
}),
},
//被攻击点
{
type: 'scatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
period: 4,
brushType: 'stroke',
scale: 4,
},
label: {
normal: {
show: true,
position: 'right',
//offset:[5, 0],
color: '#0f0',
formatter: '{b}',
textStyle: {
color: '#0f0',
},
},
emphasis: {
show: true,
color: '#FFA54F',
},
},
symbol: 'pin',
symbolSize: 50,
data: [
{
name: item[0],
value: chinaGeoCoordMap.value[item[0]].concat([]),
},
],
}
);
});
return list;
};
const chartsData = reactive({
option: {
title: {
text: '地图统计图表',
subtext: '',
x: 'center',
y: 'top',
textStyle: {
color: '#2b7',
fontSize: 20,
fontWeight: 'bold',
},
subtextStyle: {
color: '#C0C4CC',
fontSize: '15',
height: '40',
lineHeight: '40',
},
},
tooltip: {
trigger: 'item',
className: 'custom-tooltip-container', // 自定义父容器类名
backgroundColor: 'rgba(0,0,0,0.5)',
borderColor: '#35d0c0',
showDelay: 0,
hideDelay: 0,
enterable: true,
transitionDuration: 0,
extraCssText: 'z-index:100',
formatter: function (params, ticket, callback) {
let val = 0;
let str = `<div class="custom-echarts-tips"></div>`;
if (typeof params.value == 'number') {
val = params.value;
} else {
val = params.value[params.value.length - 1];
}
//根据业务自己拓展要显示的内容
var res = '';
var name = params.name;
res = `<span style='color:#fff;'> ${name}<br/>数据:${val}</span>`;
return res;
},
},
backgroundColor: 'transparent',
geo: {
map: mapName.value,
zoom: 1.2,
top: 250,
label: {
emphasis: {
show: false,
},
},
roam: false, //是否允许缩放
itemStyle: {
normal: {
color: 'rgba(75,255,180,0.5)', //地图背景色
borderColor: '#4bffb4', //省市边界线00fcff 516a89
borderWidth: 1,
areaColor: {
type: 'radial', // 径向渐变
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{ offset: 0, color: 'rgba(17,217,245,0.2)' },
{ offset: 1, color: 'rgba(10,209,231,0.6)' },
],
},
shadowColor: '#182f68',
shadowOffsetY: 2,
},
emphasis: {
color: 'rgba(10,209,231,0.6)', //悬浮背景
borderWidth: 2,
},
},
},
series: getSeries(),
},
});
let currentMap = reactive({});
const mapClick = (data) => {
// if (props.markerData.length && props.markerData.length > 0) {
// if (data.seriesType == 'effectScatter') {
// isShow.value = true;
// currentMap = data;
// emit('mapclick', currentMap);
// }
// } else {
// isShow.value = true;
// currentMap = data;
// emit('mapclick', currentMap);
// }
};
const handleClose = () => {
isShow.value = false;
};
const emit = defineEmits(['mapclick']);
</script>
<style lang="scss" scoped>
div {
box-sizing: border-box;
}
::v-deep() {
.el-dialog {
background: url(iconUrl) no-repeat left top;
background-repeat: no-repeat;
background-size: cover;
border-radius: 8px !important;
min-height: 200px;
max-height: 500px;
overflow-y: auto;
background-size: 100% 100%;
padding: 16px;
margin-top: 15%;
}
.el-dialog__header {
margin-top: 10px;
text-align: left;
padding-left: 48px;
.el-dialog__title,
i {
color: #fff !important;
}
.el-dialog__headerbtn {
top: 8px !important;
}
}
.map-dialog-my-header {
margin-top: 4px;
display: inline-flex;
justify-content: space-between;
h4 {
font-weight: normal !important;
}
}
}
.map-center-warp {
width: 100%;
text-align: center;
position: relative;
height: 90%;
.map-img {
width: 80%;
height: 80%;
position: absolute;
bottom: 0;
left: 50%;
object-fit: contain;
transform: translateX(-50%);
max-width: 1000px;
max-height: 1000px;
}
.map-pos {
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
}
</style>