/**
* ECharts 地图足迹模块 (支持钻取功能 - 点击省份查看下一级, 点击按钮返回)
*/
const MapFootprintModule = (() => {
let myChart = null; // ECharts 实例
let currentMapLevel = "country"; // 当前地图层级 ('country', 'province')
let currentProvinceCode = null; // 当前显示的省份编码 (如果有的话)
// --- 配置 ---
const COUNTRY_MAP_NAME = "china_custom";
const COUNTRY_GEOJSON_PATH = "./static/js/echarts/china.geojson";
const PROVINCE_GEOJSON_BASE_PATH = "./static/js/echarts/province/"; // 假设省份 GeoJSON 存放在这个目录
// --- 数据 ---
// 注意:这里的坐标可能需要根据你实际访问的城市进行微调
const visitedPlaces = [
{
name: "济南市",
province: "山东省",
value: [117.024961, 36.682788],
desc:'正在这里努力打工!',
imgList: [
"./static/img/location/jinan/1.jpg",
"./static/img/location/jinan/2.jpg",
"./static/img/location/jinan/3.jpg",
"./static/img/location/jinan/4.jpg",
],
},
{
name: "青岛市",
value: [120.384423, 36.065918],
province: "山东省" ,
desc:'这是我人生第一次看见海,我永远不会忘记。同样的还有你们。',
imgList: [
"./static/img/location/qingdao/1.jpg",
"./static/img/location/qingdao/2.jpg",
"./static/img/location/qingdao/3.jpg",
],
},
{
name: "淄博市",
desc:'也算是吃上淄博烧烤了。',
value: [118.055915, 36.813547],
province: "山东省"
},
{
name: "潍坊市",
desc:'风筝节!不错不错!',
value: [119.162775, 36.705759],
province: "山东省"
},
{
name: "保定市",
desc:'大学四年,那是最自由的时候。',
value: [115.482331, 38.867657],
province: "河北省"
},
{ name: "衡水市",
desc: '生我养我的地方,也是埋葬我的地方',
value: [115.665996, 37.739574], province: "河北省" },
{ name: "沧州市",
desc: 'hei !你一定要幸福啊!带着我们几个的祝福,走下去啊!',
value: [116.838581, 38.308094], province: "河北省" },
{
name: "廊坊市",
value: [116.704374, 39.523949],
province: "河北省" ,
desc:'五一寻友,一起夜间烧烤,宿醉到天明',
imgList: [
"./static/img/location/langfang/1.jpg",
"./static/img/location/langfang/2.jpg",
"./static/img/location/langfang/3.jpg",
],
},
{ name: "石家庄市",
desc: '我曾经来过。',
value: [114.514891, 38.042309], province: "河北省" },
{ name: "张家口市",
desc: '三个准大学生,傻傻的做七八个小时的绿皮火车来到这里,只为某人一份未知的爱情。',
value: [114.886714, 40.811943], province: "河北省" },
{ name: "洛阳市",
province: "河南省",
value: [112.454174, 34.618139],
desc:'群山巍峨,银装素裹,不虚此行',
imgList: [
"./static/img/location/luoyang/1.jpg",
"./static/img/location/luoyang/2.jpg",
"./static/img/location/luoyang/3.jpg",
],
},
{ name: "昌平区", value: [116.235904, 40.218086], province: "北京市" },
{ name: "杭州市",
desc: '细雨朦胧的西湖才是最美的。',
value: [120.153576, 30.287459], province: "浙江省" },
{ name: "苏州市", value: [120.585316, 31.298886], province: "江苏省" },
{ name: "扬州市", value: [119.421003, 32.393159], province: "江苏省" },
{ name: "镇江市", value: [119.452753, 32.204402], province: "江苏省" },
{ name: "南京市", value: [118.796877, 32.060255], province: "江苏省" },
{ name: "无锡市", value: [120.311987, 31.49092], province: "江苏省" },
];
// 省份名称到其 GeoJSON 文件名的映射 (需要根据你的文件名调整)
const provinceNameToGeoFile = {
北京市: "北京市.geojson",
山东省: "山东省.geojson",
河北省: "河北省.geojson",
河南省: "河南省.geojson",
浙江省: "浙江省.geojson",
江苏省: "江苏省.geojson",
};
// --- 工具函数 ---
/**
* 根据省份中文名获取其对应的 GeoJSON 文件完整路径
* @param {string} provinceName - 省份中文名
* @returns {string|null} - 文件路径或 null
*/
const getProvinceGeoPath = (provinceName) => {
const fileName = provinceNameToGeoFile[provinceName];
if (fileName) {
return ` ${PROVINCE_GEOJSON_BASE_PATH}${fileName}`;
}
console.warn(`未找到省份 " ${provinceName}" 对应的 GeoJSON 文件。`);
return null;
};
/**
* 根据地图层级和可选的省份编码生成 ECharts 配置
* @param {string} level - 地图层级 ('country' or 'province')
* @param {string} [provinceCode] - 省份编码 (当 level='province' 时使用)
* @returns {Object} - ECharts 配置对象
*/
const getEChartsOption = (level, provinceCode = null) => {
let geoMapName, roamSetting, zoomLevel, centerCoord, titleText;
let filteredVisitedPlaces = []; // 用于过滤足迹点
let seriesConfig = []; // 存储所有 series
let visualMapConfig = null; // 存储 visualMap 配置 (仅省份需要)
if (level === "country") {
geoMapName = COUNTRY_MAP_NAME;
roamSetting = false; // 启用缩放和平移
zoomLevel = 1.1;
centerCoord = [104.06, 32]; // 中国中心
titleText = "";
filteredVisitedPlaces = visitedPlaces; // 显示所有足迹
// 国家地图:保持原有的 geo 和 scatter 配置
seriesConfig = [
{
name: "足迹",
type: "scatter",
coordinateSystem: "geo",
data: filteredVisitedPlaces,
symbol: "pin",
symbolSize: 18,
itemStyle: {
color: "#FF6B6B",
borderColor: "#fff",
borderWidth: 1,
},
emphasis: {
itemStyle: {
color: "#dd4444",
},
},
tooltip: {
// --- 核心修改:Formatter 函数 ---
formatter: function (params) {
// 确保 params.data 存在
if (!params.data) {
return params.name || "未知地点"; // 如果没有数据,至少显示名称或默认文字
}
// 获取地点名称和坐标
const name = params.data.name || "未知地点";
const longitude =
params.data.value && params.data.value[0]
? params.data.value[0].toFixed(4)
: "N/A";
const latitude =
params.data.value && params.data.value[1]
? params.data.value[1].toFixed(4)
: "N/A";
// 初始化 tooltip 内容字符串
let tooltipHtml = `${name}
坐标: [${longitude}, ${latitude}]
`; // 添加一些换行和分割
// 如果还需要显示其他描述信息(例如可以从 params.data 中获取),可以在此处添加
const description = params.data.desc || "博主也不知道说啥了。。。";
if (description) {
tooltipHtml += `描述: ${description}
`;
}
// 获取图片列表
const imageList = params.data.imgList; // 直接从数据对象获取 imgList
// 检查是否有图片列表且不为空
if (Array.isArray(imageList) && imageList.length > 0) {
// 添加标题
tooltipHtml += "照片:
";
// 遍历图片列表,生成 HTML 图像标签
imageList.forEach((imgSrc) => {
tooltipHtml += ``;
});
} else {
// 如果没有图片或 imgList 不存在/为空,则显示提示
tooltipHtml += "照片: 看来博主不是很爱拍照~";
}
return tooltipHtml; // 返回构建好的 HTML 字符串
},
},
},
];
} else if (level === "province" && provinceCode) {
geoMapName = `province_ ${provinceCode}`; // 为省份地图创建唯一名称
roamSetting = false; // 省份地图也启用缩放平移
zoomLevel = 1.0; // 可以根据需要调整
// 可以根据省份动态设置中心点,这里暂时固定
// centerCoord = [118.5, 36.5]; // 示例:山东中心
// 从 visitedPlaces 中找一个城市作为中心点,如果没有,则使用默认
const firstPlaceInProvince = visitedPlaces.find(
(place) => place.province === provinceCode,
);
centerCoord = firstPlaceInProvince
? firstPlaceInProvince.value
: [118.5, 36.5];
if (provinceCode == "山东省") {
centerCoord = [118.5, 36.5];
} else if (provinceCode == "河北省") {
centerCoord = [115.482331, 40];
} else if (provinceCode == "浙江省") {
centerCoord = [120.153576, 29.4];
} else if (provinceCode == "江苏省") {
centerCoord = [119, 32.9];
} else if (provinceCode == "河南省") {
centerCoord = [114, 34];
} else if (provinceCode == "北京市") {
centerCoord = [116.407395, 40.3];
}
titleText = ` ${provinceCode} - “印迹”`;
// 过滤出属于当前省份的足迹点
filteredVisitedPlaces = visitedPlaces.filter(
(place) => place.province === provinceCode,
);
// 构造 map 系列的数据,访问过的城市 value 设为 1,未访问的可以设为 0
// 为了实现高亮,我们只需要列出访问过的城市即可,未访问的城市会使用默认颜色
const provinceMapData = filteredVisitedPlaces.map((city) => ({
name: city.name,
desc: city.desc || "",
imgList: city.imgList || [],
value: 1, // 值为 1 表示访问过,用于 visualMap 区分
}));
// --- 配置 visualMap ---
visualMapConfig = {
show: false, // 通常不显示 visualMap 组件条
min: 0, // 最小值
max: 1, // 最大值
inRange: {
color: ["#FF6B6B"], // 高亮颜色 (访问过的城市)
},
calculable: true,
};
// --- 创建省份地图系列 (用于高亮城市) ---
const provinceMapSeries = {
// name: "访问过的城市",
type: "map",
map: geoMapName, // 指向当前省份的 GeoJSON
roam: roamSetting,
zoom: zoomLevel,
center: centerCoord,
silent: false, // 设置为 false,允许响应鼠标事件以显示 tooltip
label: {
show: true, // 可以选择是否显示城市名称标签
color: "#000", // 标签颜色
fontSize: 10,
},
emphasis: {
label: {
// 悬停时标签效果
show: true,
fontWeight: "bold",
},
itemStyle: {
// 悬停时区域效果
opacity: 0.8, // 降低透明度
// areaColor: '#ffcccc', // 也可以设置悬停颜色,但会受 visualMap 影响
},
},
// 数据驱动颜色
data: provinceMapData,
// 默认样式(未在 data 中定义的区域将使用此样式)
itemStyle: {
areaColor: "#eef2ff", // 未访问区域的默认颜色
borderColor: "#333",
borderWidth: 0.5,
},
// 添加 tooltip 配置到 series 级别
tooltip: {
trigger: 'item',
formatter: function(params) {
// 检查是否有数据
if (!params.data) {
return params.name || "未知城市";
}
const cityName = params.data.name || params.name || "未知城市";
let tooltipHtml = `