feat(about): 优化关于页面样式与功能
- 添加毛玻璃效果和背景模糊滤镜 - 改进导航栏布局和激活状态样式 - 优化操作按钮样式和交互反馈 - 完善语言切换功能,支持中英文字样显示 - 增强主题切换逻辑,同步按钮激活状态 - 改进博客文章渲染,支持多分类标签展示 - 优化日期格式化函数,适配中英文显示 - 调整标签云布局算法,改善视觉效果 - 增加标签网格定位和缩放限制 - 优化球形标签云旋转逻辑和自动旋转速度
This commit is contained in:
@@ -571,6 +571,8 @@ body {
|
|||||||
height: auto;
|
height: auto;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
background: var(--dock-bg);
|
background: var(--dock-bg);
|
||||||
|
backdrop-filter: blur(12px) saturate(120%);
|
||||||
|
-webkit-backdrop-filter: blur(12px) saturate(120%);
|
||||||
border-top: 1px solid rgba(128,128,128,0.1);
|
border-top: 1px solid rgba(128,128,128,0.1);
|
||||||
padding-bottom: env(safe-area-inset-bottom);
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
@@ -582,26 +584,38 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
.nav-item {
|
.nav-item {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
.nav-item i {
|
.nav-item i {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
}
|
}
|
||||||
.nav-label {
|
.nav-label {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
.nav-item.active {
|
||||||
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
.action-btn .btn-text {
|
.action-btn .btn-text {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.action-btn {
|
.action-btn {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
padding: 5px;
|
padding: 8px;
|
||||||
background: transparent;
|
background: rgba(128,128,128,0.08);
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
.action-btn.is-active {
|
||||||
|
background: rgba(108, 92, 231, 0.25);
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stacking Bento */
|
/* Stacking Bento */
|
||||||
|
|||||||
57
js/about.js
57
js/about.js
@@ -65,6 +65,9 @@ class I18nManager {
|
|||||||
this.lang = this.lang === 'zh' ? 'en' : 'zh';
|
this.lang = this.lang === 'zh' ? 'en' : 'zh';
|
||||||
localStorage.setItem('lang', this.lang);
|
localStorage.setItem('lang', this.lang);
|
||||||
this.apply();
|
this.apply();
|
||||||
|
const label = this.lang === 'zh' ? 'CN' : 'EN';
|
||||||
|
$('#lang-btn .btn-text').text(label);
|
||||||
|
$('#lang-btn').attr('title', label);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +77,9 @@ class I18nManager {
|
|||||||
const k = $(this).data('i18n');
|
const k = $(this).data('i18n');
|
||||||
if(t[k]) $(this).text(t[k]);
|
if(t[k]) $(this).text(t[k]);
|
||||||
});
|
});
|
||||||
|
const label = this.lang === 'zh' ? 'CN' : 'EN';
|
||||||
|
$('#lang-btn .btn-text').text(label);
|
||||||
|
$('#lang-btn').attr('title', label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +94,7 @@ class ThemeManager {
|
|||||||
init() {
|
init() {
|
||||||
const saved = localStorage.getItem('theme') || 'day';
|
const saved = localStorage.getItem('theme') || 'day';
|
||||||
if(saved === 'night') this.root.setAttribute('data-theme', 'night');
|
if(saved === 'night') this.root.setAttribute('data-theme', 'night');
|
||||||
|
$('#theme-btn').toggleClass('is-active', saved === 'night');
|
||||||
|
|
||||||
$('#theme-btn').on('click', () => {
|
$('#theme-btn').on('click', () => {
|
||||||
const curr = this.root.getAttribute('data-theme');
|
const curr = this.root.getAttribute('data-theme');
|
||||||
@@ -95,6 +102,7 @@ class ThemeManager {
|
|||||||
if(next === 'night') this.root.setAttribute('data-theme', 'night');
|
if(next === 'night') this.root.setAttribute('data-theme', 'night');
|
||||||
else this.root.removeAttribute('data-theme');
|
else this.root.removeAttribute('data-theme');
|
||||||
localStorage.setItem('theme', next);
|
localStorage.setItem('theme', next);
|
||||||
|
$('#theme-btn').toggleClass('is-active', next === 'night');
|
||||||
|
|
||||||
// 更新Artalk主题
|
// 更新Artalk主题
|
||||||
if (typeof Artalk !== 'undefined') {
|
if (typeof Artalk !== 'undefined') {
|
||||||
@@ -244,13 +252,14 @@ class DataManager {
|
|||||||
const title = item.querySelector("title")?.textContent || "无标题";
|
const title = item.querySelector("title")?.textContent || "无标题";
|
||||||
const link = item.querySelector("link")?.textContent || "#";
|
const link = item.querySelector("link")?.textContent || "#";
|
||||||
const pubDate = item.querySelector("pubDate")?.textContent || "";
|
const pubDate = item.querySelector("pubDate")?.textContent || "";
|
||||||
const category = item.querySelector("category")?.textContent || "Tech";
|
const categoryNodes = item.querySelectorAll("category");
|
||||||
|
const categories = Array.from(categoryNodes).map(n => (n.textContent || '').trim()).filter(Boolean);
|
||||||
|
|
||||||
posts.push({
|
posts.push({
|
||||||
title,
|
title,
|
||||||
link,
|
link,
|
||||||
date: pubDate,
|
date: pubDate,
|
||||||
cat: category
|
cats: categories.length ? categories : ["Tech"]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,9 +286,29 @@ class DataManager {
|
|||||||
|
|
||||||
renderBlog(list) {
|
renderBlog(list) {
|
||||||
let html = '';
|
let html = '';
|
||||||
|
const lang = localStorage.getItem('lang') || (navigator.language && navigator.language.startsWith('zh') ? 'zh' : 'en');
|
||||||
|
const fmtDate = (dStr) => {
|
||||||
|
if(!dStr) return '';
|
||||||
|
const d = new Date(dStr);
|
||||||
|
if(isNaN(d.getTime())) {
|
||||||
|
try {
|
||||||
|
const parsed = new Date(Date.parse(dStr));
|
||||||
|
if(!isNaN(parsed.getTime())) return lang === 'zh'
|
||||||
|
? `${parsed.getFullYear()}年${String(parsed.getMonth()+1).padStart(2,'0')}月${String(parsed.getDate()).padStart(2,'0')}日`
|
||||||
|
: `${parsed.getFullYear()}-${String(parsed.getMonth()+1).padStart(2,'0')}-${String(parsed.getDate()).padStart(2,'0')}`;
|
||||||
|
} catch(_) {}
|
||||||
|
return dStr;
|
||||||
|
}
|
||||||
|
return lang === 'zh'
|
||||||
|
? `${d.getFullYear()}年${String(d.getMonth()+1).padStart(2,'0')}月${String(d.getDate()).padStart(2,'0')}日`
|
||||||
|
: `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
|
||||||
|
};
|
||||||
|
|
||||||
list.slice(0, 5).forEach(post => {
|
list.slice(0, 5).forEach(post => {
|
||||||
const date = (post.pubDate || post.date || '').split('T')[0];
|
const dateRaw = post.pubDate || post.date || '';
|
||||||
const cat = post.category || post.cat || 'Tech';
|
const date = fmtDate(dateRaw);
|
||||||
|
const catsArr = post.categories || post.cats || (post.category ? [post.category] : (post.cat ? [post.cat] : ['Tech']));
|
||||||
|
const cat = Array.isArray(catsArr) ? (lang === 'zh' ? catsArr.join('、') : catsArr.join(', ')) : (catsArr || 'Tech');
|
||||||
const link = post.link || post.url || '#';
|
const link = post.link || post.url || '#';
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
@@ -357,6 +386,7 @@ class UIManager {
|
|||||||
const colorClass = `tag-color-${(index % 5) + 1}`;
|
const colorClass = `tag-color-${(index % 5) + 1}`;
|
||||||
el.classList.add(colorClass);
|
el.classList.add(colorClass);
|
||||||
el.innerText = item.name;
|
el.innerText = item.name;
|
||||||
|
el.style.gridRow = `${(index % 3) + 1}`;
|
||||||
container.appendChild(el);
|
container.appendChild(el);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -378,10 +408,9 @@ class UIManager {
|
|||||||
tags.push({ el, x:0, y:0, z:0 });
|
tags.push({ el, x:0, y:0, z:0 });
|
||||||
});
|
});
|
||||||
|
|
||||||
// 增大球体半径以避免标签重叠
|
let radius = Math.max(180, Math.min(container.offsetWidth, container.offsetHeight) / 2 - 24);
|
||||||
let radius = 220;
|
|
||||||
const dtr = Math.PI/180;
|
const dtr = Math.PI/180;
|
||||||
let lasta=1, lastb=1;
|
const autoAx = 0.6, autoBx = 0.5;
|
||||||
let active=false, mouseX=0, mouseY=0;
|
let active=false, mouseX=0, mouseY=0;
|
||||||
|
|
||||||
// Init positions
|
// Init positions
|
||||||
@@ -404,15 +433,12 @@ class UIManager {
|
|||||||
const update = () => {
|
const update = () => {
|
||||||
let a, b;
|
let a, b;
|
||||||
if(active) {
|
if(active) {
|
||||||
a = (-Math.min(Math.max(-mouseY, -200), 200)/radius) * 2;
|
a = (-Math.min(Math.max(-mouseY, -200), 200)/radius) * 2 + autoAx;
|
||||||
b = (Math.min(Math.max(-mouseX, -200), 200)/radius) * 2;
|
b = (Math.min(Math.max(-mouseX, -200), 200)/radius) * 2 + autoBx;
|
||||||
} else {
|
} else {
|
||||||
a = lasta * 0.98; // Auto rotate
|
a = autoAx;
|
||||||
b = lastb * 0.98;
|
b = autoBx;
|
||||||
}
|
}
|
||||||
lasta=a; lastb=b;
|
|
||||||
|
|
||||||
if(Math.abs(a)<=0.01 && Math.abs(b)<=0.01 && !active) a=0.5; // Keep spinning slowly
|
|
||||||
|
|
||||||
let sa=Math.sin(a*dtr), ca=Math.cos(a*dtr);
|
let sa=Math.sin(a*dtr), ca=Math.cos(a*dtr);
|
||||||
let sb=Math.sin(b*dtr), cb=Math.cos(b*dtr);
|
let sb=Math.sin(b*dtr), cb=Math.cos(b*dtr);
|
||||||
@@ -422,7 +448,8 @@ class UIManager {
|
|||||||
let rx2=rx1*cb + rz1*sb, ry2=ry1, rz2=rx1*-sb + rz1*cb;
|
let rx2=rx1*cb + rz1*sb, ry2=ry1, rz2=rx1*-sb + rz1*cb;
|
||||||
tag.x=rx2; tag.y=ry2; tag.z=rz2;
|
tag.x=rx2; tag.y=ry2; tag.z=rz2;
|
||||||
|
|
||||||
let scale = (tag.z + radius)/(2*radius) + 0.5;
|
let scale = (tag.z + radius)/(2*radius) + 0.45;
|
||||||
|
scale = Math.min(Math.max(scale, 0.7), 1.2);
|
||||||
let opacity = (tag.z + radius)/(2*radius) + 0.2;
|
let opacity = (tag.z + radius)/(2*radius) + 0.2;
|
||||||
|
|
||||||
tag.el.style.opacity = Math.min(Math.max(opacity, 0.1), 1);
|
tag.el.style.opacity = Math.min(Math.max(opacity, 0.1), 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user