添加历史足迹

This commit is contained in:
DelLevin-Home
2026-01-27 00:08:18 +08:00
parent cdeff57e2c
commit 4484646f48
18 changed files with 1190 additions and 479 deletions

File diff suppressed because one or more lines are too long

45
static/js/echarts/echarts.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,74 +1,143 @@
// static/js/game_my.js
// ========== 游戏配置数据 ==========
const gamesData = [
{ id:0, name: "《永劫无间》", desc: "我身无拘,武道无穷" },
{ id:1, name: "《我的世界》", desc: "这个小盒才是我的永远的家" },
{ id:2, name: "《鬼谷八荒》", desc: "当互动版的修仙小说看了,很好玩." },
{ id:3, name: "《江城创业记》", desc: "缝合怪,但是全缝了。很喜欢的一款游戏" },
{ id:4, name: "《中国式家长》", desc: "我承认我做不好一个孩子,也做不好一个家长" },
{ id:5, name: "《王者荣耀》", desc: "买了好多皮肤,和朋友玩才是真快乐(已退坑)" },
{ id:6, name: "《QQ飞车手游》", desc: "氪了好多,有些后悔了,太耗注意力了(已退坑)" },
{ id:7, name: "《龙族幻想》", desc: "因为龙族入坑的,江南老贼!(已退坑)" },
{ id:8, name: "《洛克王国》", desc: "还记得小时候拿压岁钱偷偷买点卡(已退坑)" },
{ id:9, name: "《造梦西游》", desc: "造梦3从小学玩到大学现在还时不时的回味一下已退坑" },
{ id: 0, name: "《永劫无间》111", desc: "我身无拘,武道无穷" },
{ id: 1, name: "《我的世界》", desc: "这个小盒才是我的永远的家" },
{ id: 2, name: "《鬼谷八荒》", desc: "当互动版的修仙小说看了,很好玩." },
{
id: 3,
name: "《江城创业记》",
desc: "缝合怪,但是全缝了。很喜欢的一款游戏",
},
{
id: 4,
name: "《中国式家长》",
desc: "我承认我做不好一个孩子,也做不好一个家长",
},
{
id: 5,
name: "《王者荣耀》",
desc: "买了好多皮肤,和朋友玩才是真快乐(已退坑)",
},
{
id: 6,
name: "《QQ飞车手游》",
desc: "氪了好多,有些后悔了,太耗注意力了(已退坑)",
},
{ id: 7, name: "《龙族幻想》", desc: "因为龙族入坑的,江南老贼!(已退坑)" },
{
id: 8,
name: "《洛克王国》",
desc: "还记得小时候拿压岁钱偷偷买点卡(已退坑)",
},
{
id: 9,
name: "《造梦西游》",
desc: "造梦3从小学玩到大学现在还时不时的回味一下已退坑",
},
{
id:10,
name:'《Street Fighter 6》',
desc: "街霸6超级炎炎舞outfit3是真好看。",
},
{
id:11,
name:'《WorldBox》',
desc: "世界盒子,无意间发现的一款游戏,可惜价格太贵了。",
},
{
id:12,
name:'《无人深空》',
desc: "难以想象的开放遨游!这次,我的目标是星辰大海!",
},
{
id:13,
name:'《戴森球计划》',
desc: "没有蓝图玩的,把自己恶心坏了。主打一个自动化",
},
];
// ========== 游戏详情数据 ==========
const gameDetailData = {
0: {
id: '游戏ID: 42956400140163',
rank: '<strong>历史最高段位:</strong>无相龙王',
detailDesc: '我希望能玩一辈子永劫无间!',
images: [
'./static/img/game/yjwj/yjwj_chuanyun.png',
'./static/img/game/yjwj/yjwj_xiafeng.png',
'./static/img/game/yjwj/yjwj_liebian.png',
]
},
6: {
id: '',
rank: '<strong>历史最高段位:</strong>传奇车神',
detailDesc: '巅峰竞速!可惜我的天行者被割韭菜了。。。',
images: [
'./static/img/game/qqspead/qqspead1.jpg',
'./static/img/game/qqspead/qqspead2.jpg',
]
},
0: {
id: "游戏ID: 42956400140163",
rank: "<strong>历史最高段位:</strong>无相龙王",
detailDesc: "我希望能玩一辈子永劫无间!",
images: [
"./static/img/game/yjwj/yjwj_chuanyun.png",
"./static/img/game/yjwj/yjwj_xiafeng.png",
"./static/img/game/yjwj/yjwj_liebian.png",
],
},
1: {
id: "levin9992@qq.com",
rank: "",
detailDesc: "我自己精神的自留地!我幻想中的乌托邦",
images: [
"./static/img/game/wodeshijie/1.jpg",
"./static/img/game/wodeshijie/2.jpg",
"./static/img/game/wodeshijie/3.jpg",
],
},
2: {
id: "",
rank: "<strong>历史最高段位:</strong>登仙",
detailDesc: "好玩!爱玩!立绘非常好看!",
images: [
"./static/img/game/guigubahuang/1.jpg",
"./static/img/game/guigubahuang/2.jpg",
"./static/img/game/guigubahuang/3.jpg",
],
},
6: {
id: "",
rank: "<strong>历史最高段位:</strong>传奇车神",
detailDesc: "巅峰竞速!可惜我的天行者被割韭菜了。。。",
images: [
"./static/img/game/qqspead/qqspead1.jpg",
"./static/img/game/qqspead/qqspead2.jpg",
],
},
};
let currentlyOpenTooltip = null; // 用于跟踪当前打开的tooltip
// ========== 显示/隐藏游戏详情的函数 (Tooltip 版本) ==========
function toggleGameDetailTooltip(gameElement, gameIndex) {
// 如果点击的是同一个游戏且tooltip是打开的则关闭它
if (currentlyOpenTooltip && currentlyOpenTooltip.index === gameIndex && currentlyOpenTooltip.element && currentlyOpenTooltip.element.style.display === 'block') {
hideTooltip(currentlyOpenTooltip.element);
currentlyOpenTooltip = null;
return;
}
// 如果点击的是同一个游戏且tooltip是打开的则关闭它
if (
currentlyOpenTooltip &&
currentlyOpenTooltip.index === gameIndex &&
currentlyOpenTooltip.element &&
currentlyOpenTooltip.element.style.display === "block"
) {
hideTooltip(currentlyOpenTooltip.element);
currentlyOpenTooltip = null;
return;
}
// 如果点击的是另一个游戏先关闭之前打开的tooltip
if (currentlyOpenTooltip) {
hideTooltip(currentlyOpenTooltip.element);
}
// 如果点击的是另一个游戏先关闭之前打开的tooltip
if (currentlyOpenTooltip) {
hideTooltip(currentlyOpenTooltip.element);
}
const detailId = `game-tooltip-${gameIndex}`;
let tooltipDiv = document.getElementById(detailId);
const detailId = `game-tooltip-${gameIndex}`;
let tooltipDiv = document.getElementById(detailId);
// 如果tooltip不存在则创建它
if (!tooltipDiv) {
const detail = gameDetailData[gameIndex];
const currentLang = localStorage.getItem('preferred_language') || 'zh';
// 如果tooltip不存在则创建它
if (!tooltipDiv) {
const detail = gameDetailData[gameIndex];
const currentLang = localStorage.getItem("preferred_language") || "zh";
const nameKey = `game_name_${gameIndex}`;
const descKey = `game_desc_${gameIndex}`;
const gameName = typeof translations !== 'undefined' && translations[currentLang] ? translations[currentLang][nameKey] || gamesData[gameIndex].name : gamesData[gameIndex].name;
// const gameDesc = typeof translations !== 'undefined' && translations[currentLang] ? translations[currentLang][descKey] || gamesData[gameIndex].desc : gamesData[gameIndex].desc;
// console.log("游戏名称:", gameDesc);
let tooltipContentHtml = '';
if (detail) {
tooltipContentHtml = `
const nameKey = `game_name_${gameIndex}`;
const descKey = `game_desc_${gameIndex}`;
const gameName =
typeof translations !== "undefined" && translations[currentLang]
? translations[currentLang][nameKey] || gamesData[gameIndex].name
: gamesData[gameIndex].name;
let tooltipContentHtml = "";
if (detail) {
tooltipContentHtml = `
<div class="tooltip-content">
<div class="tooltip-header">
<h4>${gameName}</h4>
@@ -78,16 +147,18 @@ function toggleGameDetailTooltip(gameElement, gameIndex) {
<p><strong>${detail.id}</strong></p>
<p> ${detail.rank}</p>
<p><em>${detail.detailDesc}</em></p>
${detail.images && detail.images.length > 0 ?
`<div class="tooltip-images">
${detail.images.map(imgSrc => `<img src="${imgSrc}" alt="游戏详情图片" class="tooltip-image-item">`).join('')}
${
detail.images && detail.images.length > 0
? `<div class="tooltip-images">
${detail.images.map((imgSrc) => `<img src="${imgSrc}" alt="游戏详情图片" class="tooltip-image-item">`).join("")}
</div>`
: ''}
: ""
}
</div>
</div>
`;
} else {
tooltipContentHtml = `
} else {
tooltipContentHtml = `
<div class="tooltip-content">
<div class="tooltip-header">
<h4>${gameName}</h4>
@@ -98,72 +169,75 @@ function toggleGameDetailTooltip(gameElement, gameIndex) {
</div>
</div>
`;
}
tooltipDiv = document.createElement('div');
tooltipDiv.id = detailId;
tooltipDiv.className = 'game-detail-tooltip';
tooltipDiv.innerHTML = tooltipContentHtml;
// 添加关闭按钮事件
const closeBtn = tooltipDiv.querySelector('.tooltip-close');
closeBtn.addEventListener('click', (e) => {
e.stopPropagation(); // 防止触发外层的点击关闭
hideTooltip(tooltipDiv);
currentlyOpenTooltip = null;
});
// 添加点击tooltip外部区域关闭的功能
tooltipDiv.addEventListener('click', (e) => {
// 只有点击tooltip自身而非内部内容才关闭
if (e.target === tooltipDiv) {
hideTooltip(tooltipDiv);
currentlyOpenTooltip = null;
}
});
document.body.appendChild(tooltipDiv); // 将tooltip添加到body实现悬浮效果
}
// 定位tooltip,让它出现在游戏项附近
const rect = gameElement.getBoundingClientRect();
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
tooltipDiv = document.createElement("div");
tooltipDiv.id = detailId;
tooltipDiv.className = "game-detail-tooltip";
tooltipDiv.innerHTML = tooltipContentHtml;
// 计算tooltip的位置 (例如,出现在游戏项下方)
const top = rect.bottom + scrollTop + 10; // 10px 间隙
const left = rect.left + scrollLeft; // 与游戏项左侧对齐
// 添加关闭按钮事件
const closeBtn = tooltipDiv.querySelector(".tooltip-close");
closeBtn.addEventListener("click", (e) => {
e.stopPropagation(); // 防止触发外层的点击关闭
hideTooltip(tooltipDiv);
currentlyOpenTooltip = null;
});
tooltipDiv.style.top = `${top}px`;
tooltipDiv.style.left = `${left}px`;
tooltipDiv.style.display = 'block';
// 添加点击tooltip外部区域关闭的功能
tooltipDiv.addEventListener("click", (e) => {
// 只有点击tooltip自身而非内部内容才关闭
if (e.target === tooltipDiv) {
hideTooltip(tooltipDiv);
currentlyOpenTooltip = null;
}
});
// 记录当前打开的tooltip
currentlyOpenTooltip = { element: tooltipDiv, index: gameIndex };
document.body.appendChild(tooltipDiv); // 将tooltip添加到body实现悬浮效果
}
// 阻止事件冒泡到document避免立即被关闭
tooltipDiv.onclick = function(e) {
e.stopPropagation();
};
// 定位tooltip让它出现在游戏项附近
const rect = gameElement.getBoundingClientRect();
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
// 计算tooltip的位置 (例如,出现在游戏项下方)
const top = rect.bottom + scrollTop + 10; // 10px 间隙
const left = rect.left + scrollLeft; // 与游戏项左侧对齐
tooltipDiv.style.top = `${top}px`;
tooltipDiv.style.left = `${left}px`;
tooltipDiv.style.display = "block";
// 记录当前打开的tooltip
currentlyOpenTooltip = { element: tooltipDiv, index: gameIndex };
// 阻止事件冒泡到document避免立即被关闭
tooltipDiv.onclick = function (e) {
e.stopPropagation();
};
}
// ========== 隐藏Tooltip的辅助函数 ==========
function hideTooltip(tooltipElement) {
if (tooltipElement) {
tooltipElement.style.display = 'none';
// 如果想完全移除DOM可以取消下面两行注释但通常隐藏即可
// if (tooltipElement.parentNode) {
// tooltipElement.parentNode.removeChild(tooltipElement);
// }
}
if (tooltipElement) {
tooltipElement.style.display = "none";
// 如果想完全移除DOM可以取消下面两行注释但通常隐藏即可
// if (tooltipElement.parentNode) {
// tooltipElement.parentNode.removeChild(tooltipElement);
// }
}
}
// ========== 点击文档其他地方关闭Tooltip ==========
document.addEventListener('click', function(event) {
if (currentlyOpenTooltip && !currentlyOpenTooltip.element.contains(event.target)) {
hideTooltip(currentlyOpenTooltip.element);
currentlyOpenTooltip = null;
}
document.addEventListener("click", function (event) {
if (
currentlyOpenTooltip &&
!currentlyOpenTooltip.element.contains(event.target)
) {
hideTooltip(currentlyOpenTooltip.element);
currentlyOpenTooltip = null;
}
});
// ========== 渲染游戏列表的函数 ==========
@@ -180,14 +254,20 @@ function renderGames(gamesArray) {
return;
}
const currentLang = localStorage.getItem('preferred_language') || 'zh';
const currentLang = localStorage.getItem("preferred_language") || "zh";
let html = "";
gamesArray.forEach((game, index) => {
const nameKey = `game_name_${index}`;
const descKey = `game_desc_${index}`;
const nameTranslation = typeof translations !== 'undefined' && translations[currentLang] ? translations[currentLang][nameKey] || game.name : game.name;
const descTranslation = typeof translations !== 'undefined' && translations[currentLang] ? translations[currentLang][descKey] || game.desc : game.desc;
const nameTranslation =
typeof translations !== "undefined" && translations[currentLang]
? translations[currentLang][nameKey] || game.name
: game.name;
const descTranslation =
typeof translations !== "undefined" && translations[currentLang]
? translations[currentLang][descKey] || game.desc
: game.desc;
// 为每个游戏项添加点击事件,并传递其索引
html += `
@@ -201,17 +281,17 @@ function renderGames(gamesArray) {
container.innerHTML = html;
// 为每个生成的游戏项添加点击事件监听器
const gameItems = container.querySelectorAll('.game-item');
gameItems.forEach(item => {
item.addEventListener('click', function(event) {
event.stopPropagation(); // 阻止点击事件冒泡到document避免立即关闭
const gameIndex = parseInt(this.getAttribute('data-game-index'));
toggleGameDetailTooltip(this, gameIndex);
});
const gameItems = container.querySelectorAll(".game-item");
gameItems.forEach((item) => {
item.addEventListener("click", function (event) {
event.stopPropagation(); // 阻止点击事件冒泡到document避免立即关闭
const gameIndex = parseInt(this.getAttribute("data-game-index"));
toggleGameDetailTooltip(this, gameIndex);
});
});
}
// ========== 初始化 ==========
document.addEventListener('DOMContentLoaded', function() {
renderGames(gamesData);
});
document.addEventListener("DOMContentLoaded", function () {
renderGames(gamesData);
});

View File

@@ -1,9 +1,11 @@
const translationsEN = {
'footprint_map_h2': '足迹',// 添加这个
'page_title': 'BaiTu - BAITU',
'nav_about': 'About Me',
'nav_website': 'My Websites',
'nav_tools': 'Tools',
'nav_games': 'Games',
'nav_footprint':'Footprints',
'nav_memos': 'Memos',
'nav_contact': 'Contact Me',
'hello': 'Hello',

View File

@@ -4,6 +4,7 @@ const translationsZH = {
'nav_website': '我的网站',
'nav_tools': '常用工具',
'nav_games': '常玩游戏',
'nav_footprint':'历史足迹',
'nav_memos': '闲言碎语',
'nav_contact': '联系我',
'hello': '你好',
@@ -54,21 +55,21 @@ const translationsZH = {
'game_name_0': '《永劫无间》',
'game_desc_0': '我身无拘,武道无穷',
'game_name_1': '《我的世界》',
'game_desc_1': '这个小盒才是我的永远的家',
'game_desc_1': '这个小盒才是我的永远的家',
'game_name_2': '《鬼谷八荒》',
'game_desc_2': '当互动版的修仙小说看了,很好玩.',
'game_desc_2': '立绘无敌,剧情无敌,非常不错的修仙游戏!',
'game_name_3': '《江城创业记》',
'game_desc_3': '缝合怪,但是全缝了。很喜欢的一款游戏',
'game_desc_3': '自动化、闯关、结婚总有一款方式适合你。',
'game_name_4': '《中国式家长》',
'game_desc_4': '我承认我做不好一个孩子,也做不好一个家长',
'game_desc_4': '我承认我做不好一个孩子,也做不好一个家长',
'game_name_5': '《王者荣耀》',
'game_desc_5': '买了好多皮肤,和朋友玩才是真快乐(已退坑)',
'game_desc_5': '和朋友玩才是真快乐,一个人的王者,一群人的荣耀(已退坑)',
'game_name_6': '《QQ飞车手游》',
'game_desc_6': '氪了好多,有些后悔了(已退坑)',
'game_desc_6': '一辆天行者陪我从大学跑到工作(已退坑)',
'game_name_7': '《龙族幻想》',
'game_desc_7': '因为龙族入坑的,江南老贼!(已退坑)',
'game_desc_7': '因为龙族入坑的,只能说剧情还不错!(已退坑)',
'game_name_8': '《洛克王国》',
'game_desc_8': '还记得小时候拿压岁钱偷偷买点卡(已退坑)',
'game_desc_8': '还记得小时候拿压岁钱偷偷买点卡,可惜号被盗了(已退坑)',
'game_name_9': '《造梦西游》',
'game_desc_9': '造梦3从小学玩到大学现在还时不时的回味一下已退坑',

229
static/js/map-footprint.js Normal file
View File

@@ -0,0 +1,229 @@
// ./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 = '<p>加载地图数据失败,请检查网络连接或稍后重试。</p>';
}
}
};
/**
* 初始化 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 + '<br/>经度: ' + params.value[0].toFixed(4) + '<br/>纬度: ' + 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}<br/>坐标: [ ${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 // 导出销毁方法,如果需要的话
};
})();

View File

@@ -12,7 +12,6 @@
// 获取 DOM 元素
const memosTab = document.querySelector('.nav-tab[data-tab="memos"]');
const memosContainer = document.getElementById("memos-container");
const memosContent = document.getElementById("memos-content");
// 日期格式化函数 (简单实现)
function formatDate(dateStr) {
@@ -201,4 +200,4 @@
loadMemos();
}
});
})();
})();

View File

@@ -1,60 +1,105 @@
// ==================== 标签切换功能 ====================
document.addEventListener('DOMContentLoaded', function () {
const tabs = document.querySelectorAll('.nav-tab');
const contents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => {
tab.addEventListener('click', function () {
const tabId = this.getAttribute('data-tab');
// 移除所有激活状态
tabs.forEach(t => t.classList.remove('active'));
contents.forEach(c => c.classList.remove('active'));
// 添加当前激活状态
this.classList.add('active');
document.getElementById(`${tabId}-content`).classList.add('active');
});
});
// ==================== 标签切换功能 ====================
document.addEventListener("DOMContentLoaded", function () {
const tabs = document.querySelectorAll(".nav-tab");
const contents = document.querySelectorAll(".tab-content");
tabs.forEach((tab) => {
tab.addEventListener("click", function () {
const tabId = this.getAttribute("data-tab");
// 在切换之前,如果当前是足迹页且地图已存在,销毁旧地图实例 (ECharts 版本)
const currentActiveTab = document.querySelector(".nav-tab.active");
if (
currentActiveTab &&
currentActiveTab.getAttribute("data-tab") === "footprint" &&
typeof MapFootprintModule !== "undefined"
) {
MapFootprintModule.destroyMap(); // 销毁之前的 ECharts 实例
console.log("切换标签前已销毁旧地图实例");
}
const websiteTab = document.querySelector('.nav-tab[data-tab="website"]');
const websiteContent = document.getElementById('website-content');
if (websiteTab && websiteContent) {
websiteTab.addEventListener('click', function () {
const hasRendered = websiteContent.querySelector('.category-links') !== null;
if (!hasRendered) {
const savedLang = localStorage.getItem(LANG_KEY) || 'zh';
renderWebsites(websitesData, translations, savedLang);
}
});
} else {
console.warn("未找到“我的网站”标签或内容区域。");
}
// 移除所有激活状态
tabs.forEach((t) => t.classList.remove("active"));
contents.forEach((c) => c.classList.remove("active"));
// 添加当前激活状态
this.classList.add("active");
document.getElementById(`${tabId}-content`).classList.add("active");
});
});
// 点击我的工具函数
const toolsTab = document.querySelector('.nav-tab[data-tab="tools"]');
const toolsContent = document.getElementById('tools-content');
if (toolsTab && toolsContent) {
toolsTab.addEventListener('click', function () {
const hasRendered = toolsContent.querySelector('.tool-item') !== null;
if (!hasRendered) {
renderTools(toolsData);
}
});
} else {
console.warn("未找到“我的工具”标签或内容区域,将在页面加载时尝试渲染。");
renderTools(toolsData);
}
// 点击常玩游戏函数
const gamesTab = document.querySelector('.nav-tab[data-tab="games"]');
const gamesContent = document.getElementById('games-content');
if (gamesTab && gamesContent) {
gamesTab.addEventListener('click', function () {
const hasRendered = gamesContent.querySelector('.game-item') !== null;
if (!hasRendered) {
renderGames(gamesData);
}
});
} else {
console.warn("未找到“常玩游戏”标签或内容区域。");
renderGames(gamesData);
}
const websiteTab = document.querySelector('.nav-tab[data-tab="website"]');
const websiteContent = document.getElementById("website-content");
if (websiteTab && websiteContent) {
websiteTab.addEventListener("click", function () {
const hasRendered =
websiteContent.querySelector(".category-links") !== null;
if (!hasRendered) {
const savedLang = localStorage.getItem(LANG_KEY) || "zh";
renderWebsites(websitesData, translations, savedLang);
}
});
} else {
console.warn("未找到“我的网站”标签或内容区域。");
}
});
// 点击我的工具函数
const toolsTab = document.querySelector('.nav-tab[data-tab="tools"]');
const toolsContent = document.getElementById("tools-content");
if (toolsTab && toolsContent) {
toolsTab.addEventListener("click", function () {
const hasRendered = toolsContent.querySelector(".tool-item") !== null;
if (!hasRendered) {
renderTools(toolsData);
}
});
} else {
console.warn("未找到“我的工具”标签或内容区域,将在页面加载时尝试渲染。");
renderTools(toolsData);
}
// 点击常玩游戏函数
const gamesTab = document.querySelector('.nav-tab[data-tab="games"]');
const gamesContent = document.getElementById("games-content");
if (gamesTab && gamesContent) {
gamesTab.addEventListener("click", function () {
const hasRendered = gamesContent.querySelector(".game-item") !== null;
if (!hasRendered) {
renderGames(gamesData);
}
});
} else {
console.warn("未找到“常玩游戏”标签或内容区域。");
renderGames(gamesData);
}
// 点击足迹函数 (新增)
const footprintTab = document.querySelector('.nav-tab[data-tab="footprint"]');
const footprintContent = document.getElementById("footprint-content");
if (footprintTab && footprintContent) {
footprintTab.addEventListener("click", function () {
// 如果 MapFootprintModule 已加载(即 map-footprint.js 已成功执行)
if (typeof MapFootprintModule !== "undefined") {
// 调用模块中的 renderMap 函数来渲染地图
MapFootprintModule.renderMap(footprintContent);
} else {
// 如果模块未定义,说明 map-footprint.js 可能未加载或加载失败
console.error(
"MapFootprintModule 未定义,请确保 map-footprint.js 已正确加载且在 tabchange.js 之前。",
);
// 可以选择显示错误信息给用户
footprintContent.innerHTML =
'<p data-i18n="error_loading_map">加载地图失败,请刷新页面重试。</p>';
// 如果需要更新国际化文本,可以在这里处理
if (typeof translations !== "undefined") {
const errorElement = footprintContent.querySelector(
'[data-i18n="error_loading_map"]',
);
if (errorElement) {
const savedLang = localStorage.getItem(LANG_KEY) || "zh";
const translation = translations[savedLang]["error_loading_map"];
if (translation) errorElement.textContent = translation;
}
}
}
});
} else {
console.warn("未找到“足迹”标签或内容区域。");
}
});

View File

@@ -0,0 +1,60 @@
// ==================== 标签切换功能 ====================
document.addEventListener("DOMContentLoaded", function () {
const tabs = document.querySelectorAll(".nav-tab");
const contents = document.querySelectorAll(".tab-content");
tabs.forEach((tab) => {
tab.addEventListener("click", function () {
const tabId = this.getAttribute("data-tab");
// 移除所有激活状态
tabs.forEach((t) => t.classList.remove("active"));
contents.forEach((c) => c.classList.remove("active"));
// 添加当前激活状态
this.classList.add("active");
document.getElementById(`${tabId}-content`).classList.add("active");
});
});
const websiteTab = document.querySelector('.nav-tab[data-tab="website"]');
const websiteContent = document.getElementById("website-content");
if (websiteTab && websiteContent) {
websiteTab.addEventListener("click", function () {
const hasRendered =
websiteContent.querySelector(".category-links") !== null;
if (!hasRendered) {
const savedLang = localStorage.getItem(LANG_KEY) || "zh";
renderWebsites(websitesData, translations, savedLang);
}
});
} else {
console.warn("未找到“我的网站”标签或内容区域。");
}
// 点击我的工具函数
const toolsTab = document.querySelector('.nav-tab[data-tab="tools"]');
const toolsContent = document.getElementById("tools-content");
if (toolsTab && toolsContent) {
toolsTab.addEventListener("click", function () {
const hasRendered = toolsContent.querySelector(".tool-item") !== null;
if (!hasRendered) {
renderTools(toolsData);
}
});
} else {
console.warn("未找到“我的工具”标签或内容区域,将在页面加载时尝试渲染。");
renderTools(toolsData);
}
// 点击常玩游戏函数
const gamesTab = document.querySelector('.nav-tab[data-tab="games"]');
const gamesContent = document.getElementById("games-content");
if (gamesTab && gamesContent) {
gamesTab.addEventListener("click", function () {
const hasRendered = gamesContent.querySelector(".game-item") !== null;
if (!hasRendered) {
renderGames(gamesData);
}
});
} else {
console.warn("未找到“常玩游戏”标签或内容区域。");
renderGames(gamesData);
}
});