// ./static/js/map-footprint.js
/**
* ECharts 地图足迹模块 (使用本地 GeoJSON)
*/
const MapFootprintModule = (() => {
let myChart = null; // ECharts 实例
const MAP_NAME = 'china_custom'; // 为自定义地图起一个名字
const visitedPlaces = [
{ name: "济南市", value: [117.024961, 36.682788] },
{ name: "青岛市", value: [120.384423, 36.065918] },
{ name: "淄博市", value: [118.055915, 36.813547] },
{ name: "潍坊市", value: [119.162775, 36.705759] },
{ name: "北京市", value: [116.407395, 39.904211] },
{ name: "杭州市", value: [120.153576, 30.287459] },
{ name: "苏州市", value: [120.585316, 31.298886] },
{ name: "扬州市", value: [119.421003, 32.393159] },
{ name: "保定市", value: [115.482331, 38.867657] },
{ name: "石家庄市", value: [114.514891, 38.042309] },
{ name: "衡水市", value: [115.665996, 37.739574] },
{ name: "洛阳市", value: [112.454174, 34.618139] },
{ name: "南京市", value: [118.796877, 32.060255] },
{ name: "无锡市", value: [120.311987, 31.490920] },
{ name: "沧州市", value: [116.838581, 38.308094] },
{ name: "镇江市", value: [119.452753, 32.204402] },
];
/**
* 加载 GeoJSON 地图数据并注册
*/
const loadAndRegisterMap = async () => {
try {
// console.log('开始加载 GeoJSON 地图数据...');
const response = await fetch('./static/js/echarts/china.geojson'); // 确保路径正确
if (!response.ok) {
throw new Error(`加载 GeoJSON 失败: ${response.status} ${response.statusText}`);
}
const geoJsonData = await response.json();
// 注册自定义地图
echarts.registerMap(MAP_NAME, geoJsonData);
// console.log('GeoJSON 地图数据加载并注册成功。');
// 地图注册成功后,初始化图表
const container = document.getElementById(getMapContainerId());
if (container) {
initEChartsMap(container);
} else {
console.error('地图容器 DOM 元素未找到,无法初始化图表。');
}
} catch (error) {
console.error('加载或注册 GeoJSON 地图时出错:', error);
// 可以选择在内容区域显示错误信息
const contentDiv = document.getElementById('footprint-content'); // 假设足迹内容区域ID是这个
if (contentDiv) {
contentDiv.innerHTML = '
加载地图数据失败,请检查网络连接或稍后重试。
';
}
}
};
/**
* 初始化 ECharts 地图
* @param {HTMLElement} container - 图表容器DOM元素
*/
const initEChartsMap = (container) => {
if (!container) {
console.error('地图容器未找到');
return;
}
// 初始化 ECharts 实例
myChart = echarts.init(container);
// ECharts 配置项 (使用注册的地图名称)
const option = {
title: {
text: '',
subtext: '读万卷书,不如行万里路。见多才会识广~',
left: 'center',
textStyle: {
fontSize: 18
},
subtextStyle: {
fontSize: 12
}
},
tooltip: {
trigger: 'item',
formatter: function(params) {
if (params.value && params.value.length >= 2) {
return params.name + '
经度: ' + params.value[0].toFixed(4) + '
纬度: ' + params.value[1].toFixed(4);
}
return params.name; // 如果没有坐标信息,只显示地名
}
},
toolbox: {
show: false,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {}
}
},
visualMap: {
show: false, // 是否显示 visualMap 组件,这里设为 false,因为我们用 symbolSize 控制点大小
min: 0,
max: 100,
left: 'left',
top: 'bottom',
text: ['High', 'Low'], // 文本,默认为数值文本
calculable: true
},
geo: {
map: MAP_NAME, // 使用注册的自定义地图名称
roam: false, // 是否开启鼠标缩放和平移漫游
zoom: 1.1, // 当前视角的缩放比例
center: [104.06, 30],
emphasis: { // 高亮状态下的样式
itemStyle: {
areaColor: '#f0f0f0', // 高亮时省份的颜色
borderColor: '#409EFF', // 高亮时省份的边框颜色
borderWidth: 1
}
},
itemStyle: { // 普通状态下的样式
areaColor: '#eef2ff', // 未选中时省份的颜色
borderColor: '#333' // 未选中时省份的边框颜色
}
},
series: [
{
name: '足迹',
type: 'scatter', // 使用散点图表示标记点
coordinateSystem: 'geo', // 指定坐标系为地理坐标系
data: visitedPlaces, // 使用我们的数据
symbol: 'pin', // 使用内置符号 'pin'
symbolSize: 18, // 标记点的大小
itemStyle: { // 普通状态下的样式
color: '#FF6B6B', // 设置图标颜色
borderColor: '#fff', // 设置图标边框颜色
borderWidth: 1, // 设置图标边框宽度
},
emphasis: { // 高亮状态
itemStyle: {
color: '#dd4444' // 高亮时点的颜色
}
},
tooltip: {
formatter: function(params) {
// 这里可以更精细地控制 tooltip 内容
return ` ${params.data.name}
坐标: [ ${params.data.value[0].toFixed(4)}, ${params.data.value[1].toFixed(4)}]`;
}
}
}
]
};
// 设置配置项并渲染图表
myChart.setOption(option);
// 监听窗口大小变化,自动适配
window.addEventListener('resize', function () {
if (myChart) {
myChart.resize();
}
});
};
/**
* 获取地图容器ID
* @returns {string}
*/
const getMapContainerId = () => {
return 'echarts-map-container'; // 定义一个唯一的ID
};
/**
* 渲染 ECharts 地图内容到指定容器
* @param {HTMLElement} contentDiv - 标签页的内容容器
*/
const renderMap = (contentDiv) => {
// 清空内容区域
contentDiv.innerHTML = '';
// 创建标题
const titleElement = document.createElement('h2');
titleElement.setAttribute('data-i18n', 'footprint_map_h2'); // 假设你在语言文件中有这个键
titleElement.textContent = '历史足迹'; // 默认文本
contentDiv.appendChild(titleElement);
// 创建地图容器
const mapDiv = document.createElement('div');
mapDiv.id = getMapContainerId();
mapDiv.style.width = '100%';
mapDiv.style.height = '600px'; // 设置地图高度,可以根据需要调整
mapDiv.style.marginTop = '20px'; // 可选:添加上边距
contentDiv.appendChild(mapDiv);
// 加载 GeoJSON 并初始化地图
// 使用 setTimeout 确保 DOM 元素已渲染后再加载地图数据
setTimeout(() => {
loadAndRegisterMap();
}, 100); // 延迟一点确保渲染完成
};
/**
* 销毁 ECharts 实例 (可选,用于性能优化或切换时清理)
*/
const destroyMap = () => {
if (myChart) {
myChart.dispose(); // 销毁实例,释放资源
myChart = null;
console.log('ECharts 地图已销毁');
}
};
// 返回公共方法
return {
renderMap,
destroyMap // 导出销毁方法,如果需要的话
};
})();