feat(about): 实现主题系统与技术标签球体动画
- 添加日夜主题CSS变量定义与样式覆盖 - 实现根据时间自动切换主题功能 - 技术标签云改造成3D球体布局并添加动画 - 优化移动端与减少动画模式下的标签展示 - 调整部分元素尺寸与颜色以适配新主题 - 更新MBTI图标展示方式并移除旧装饰图 - 修复SVG路径定义与GitHub统计展示问题
This commit is contained in:
@@ -29,10 +29,7 @@
|
|||||||
<main class="about-main">
|
<main class="about-main">
|
||||||
<!-- 英雄区域 -->
|
<!-- 英雄区域 -->
|
||||||
<section class="hero-section">
|
<section class="hero-section">
|
||||||
<!-- INFJ装饰图片 -->
|
|
||||||
<div class="infj-decoration">
|
|
||||||
<img src="https://blog-file.hehouhui.cn/INFJ.png" alt="INFJ" class="infj-image">
|
|
||||||
</div>
|
|
||||||
<div class="hero-container">
|
<div class="hero-container">
|
||||||
<div class="hero-left">
|
<div class="hero-left">
|
||||||
<div class="profile-card">
|
<div class="profile-card">
|
||||||
@@ -71,6 +68,7 @@
|
|||||||
<div class="personality-section">
|
<div class="personality-section">
|
||||||
<div class="mbti-card">
|
<div class="mbti-card">
|
||||||
<div class="mbti-header">
|
<div class="mbti-header">
|
||||||
|
<img src="https://blog-file.hehouhui.cn/INFJ.png" alt="INFJ" style="width:32px;height:32px;border-radius:50%;border:2px solid rgba(255,255,255,0.4)">
|
||||||
<span class="mbti-tag">INFJ</span>
|
<span class="mbti-tag">INFJ</span>
|
||||||
<span class="mbti-name">提倡者人格</span>
|
<span class="mbti-name">提倡者人格</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
114
css/about.css
114
css/about.css
@@ -23,6 +23,58 @@
|
|||||||
--accent-lavender: #7B7AE6;
|
--accent-lavender: #7B7AE6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root.theme-day {
|
||||||
|
--grad-a: #F6F7F9;
|
||||||
|
--grad-b: #EDEFF3;
|
||||||
|
--text-strong: #121417;
|
||||||
|
--text-soft: #2a2d34;
|
||||||
|
--glass-alpha: 0.10;
|
||||||
|
--glass-border: rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.theme-night {
|
||||||
|
--grad-a: #101216;
|
||||||
|
--grad-b: #171a1f;
|
||||||
|
--text-strong: #F2F3F5;
|
||||||
|
--text-soft: rgba(255, 255, 255, 0.9);
|
||||||
|
--glass-alpha: 0.14;
|
||||||
|
--glass-border: rgba(255, 255, 255, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-day .nav-logo {
|
||||||
|
background: linear-gradient(45deg, #121417, #2a2d34);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-day .nav-links a { color: var(--text-soft); }
|
||||||
|
|
||||||
|
.theme-day .hero-title,
|
||||||
|
.theme-day .section-title,
|
||||||
|
.theme-day .project-title,
|
||||||
|
.theme-day .article-title {
|
||||||
|
background: linear-gradient(45deg, #121417, #2a2d34);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-day .hero-subtitle,
|
||||||
|
.theme-day .intro-text p,
|
||||||
|
.theme-day .project-description,
|
||||||
|
.theme-day .article-excerpt,
|
||||||
|
.theme-day .timeline-content p,
|
||||||
|
.theme-day .section-subtitle,
|
||||||
|
.theme-day .location-info,
|
||||||
|
.theme-day .stat-label { color: var(--text-soft); }
|
||||||
|
|
||||||
|
.theme-day .cloud-tag {
|
||||||
|
color: var(--text-soft);
|
||||||
|
border-color: rgba(0, 0, 0, 0.1);
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Inter', 'SF Pro Text', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: 'Inter', 'SF Pro Text', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
@@ -795,6 +847,19 @@ a:not(.nav-logo):not(.nav-links a):not(.social-link):not(.btn):not(.footer-info
|
|||||||
perspective: 1000px;
|
perspective: 1000px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cloud-wrapper.sphere {
|
||||||
|
height: 420px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
perspective: 800px;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cloud-wrapper.sphere .cloud-tag {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
/* 连接线动画 */
|
/* 连接线动画 */
|
||||||
.cloud-wrapper::before {
|
.cloud-wrapper::before {
|
||||||
content: '';
|
content: '';
|
||||||
@@ -1379,11 +1444,12 @@ a:not(.nav-logo):not(.nav-links a):not(.social-link):not(.btn):not(.footer-info
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 120px;
|
width: 110px;
|
||||||
height: 120px;
|
height: 110px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes orbit {
|
@keyframes orbit {
|
||||||
@@ -1401,6 +1467,7 @@ a:not(.nav-logo):not(.nav-links a):not(.social-link):not(.btn):not(.footer-info
|
|||||||
background: var(--social-color, #667eea);
|
background: var(--social-color, #667eea);
|
||||||
transform: scaleX(0);
|
transform: scaleX(0);
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.social-card:hover {
|
.social-card:hover {
|
||||||
@@ -1820,7 +1887,7 @@ a:not(.nav-logo):not(.nav-links a):not(.social-link):not(.btn):not(.footer-info
|
|||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.hero-title {
|
.hero-title {
|
||||||
font-size: 2rem;
|
font-size: 1.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-stats {
|
.hero-stats {
|
||||||
@@ -1926,9 +1993,9 @@ a:not(.nav-logo):not(.nav-links a):not(.social-link):not(.btn):not(.footer-info
|
|||||||
.blog-waterfall-section,
|
.blog-waterfall-section,
|
||||||
.contact-floating-section,
|
.contact-floating-section,
|
||||||
.comments-section {
|
.comments-section {
|
||||||
padding: 4rem 1rem;
|
padding: 3rem 0.8rem;
|
||||||
margin: 1rem;
|
margin: 0.8rem;
|
||||||
border-radius: 25px;
|
border-radius: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cloud-tag {
|
.cloud-tag {
|
||||||
@@ -2061,4 +2128,39 @@ a:not(.nav-logo):not(.nav-links a):not(.social-link):not(.btn):not(.footer-info
|
|||||||
.avatar-ring {
|
.avatar-ring {
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.theme-day .profile-info h1,
|
||||||
|
.theme-day .github-info h3,
|
||||||
|
.theme-day .social-info h3 { color: var(--text-strong); }
|
||||||
|
|
||||||
|
.theme-day .intro-quote p,
|
||||||
|
.theme-day .intro-text p,
|
||||||
|
.theme-day .timeline-content p,
|
||||||
|
.theme-day .project-description,
|
||||||
|
.theme-day .article-excerpt,
|
||||||
|
.theme-day .article-meta,
|
||||||
|
.theme-day .social-info p,
|
||||||
|
.theme-day .github-bio { color: var(--text-soft); }
|
||||||
|
|
||||||
|
.theme-day .stat-number {
|
||||||
|
background: linear-gradient(45deg, #121417, #2a2d34);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
.theme-day .hero-description p { color: var(--text-soft); }
|
||||||
|
.theme-day .project-stat,
|
||||||
|
.theme-day .project-stats span { color: var(--text-soft); }
|
||||||
|
.theme-day .article-meta { color: var(--text-soft); }
|
||||||
|
.theme-day .view-all-link {
|
||||||
|
background: linear-gradient(45deg, #121417, #2a2d34);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
.theme-day .timeline-content h3 {
|
||||||
|
background: linear-gradient(45deg, #121417, #2a2d34);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
}
|
}
|
||||||
90
js/about.js
90
js/about.js
@@ -1,6 +1,7 @@
|
|||||||
// 关于页面JavaScript功能 - 现代动态版本
|
// 关于页面JavaScript功能 - 现代动态版本
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
initThemeByTime();
|
||||||
initMotionController();
|
initMotionController();
|
||||||
initGitHubStats();
|
initGitHubStats();
|
||||||
initProjects();
|
initProjects();
|
||||||
@@ -238,8 +239,8 @@ function displayProjects(repos) {
|
|||||||
(updateDate.getMonth() + 1) + '/' +
|
(updateDate.getMonth() + 1) + '/' +
|
||||||
updateDate.getDate();
|
updateDate.getDate();
|
||||||
|
|
||||||
var starSvg = '<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-label="Star" role="img"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.46 4.73L5.82 21z"></path></svg>';
|
var starSvg = '<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-label="Star" role="img"><path d="M12 17.27l6.18 3.73-1.64-7.03L22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.46 4.73L5.82 21z"></path></svg>';
|
||||||
var forkSvg = '<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-label="Fork" role="img"><path d="M7 4a3 3 0 106 0 3 3 0 00-6 0zm7 0a3 3 0 106 0 3 3 0 00-6 0zM7 20a3 3 0 106 0 3 3 0 00-6 0zm2-3.17V10a3 3 0 013-3h3"></path></svg>';
|
var forkSvg = '<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-label="Fork" role="img"><path d="M7 4a3 3 0 106 0 3 3 0 00-6 0zm10 0a3 3 0 106 0 3 3 0 00-6 0v6a3 3 0 01-3 3H7"></path></svg>';
|
||||||
projectsHtml += '<div class="project-card" onclick="window.open(\'' + repo.html_url + '\', \'_blank\')">' +
|
projectsHtml += '<div class="project-card" onclick="window.open(\'' + repo.html_url + '\', \'_blank\')">' +
|
||||||
'<div class="project-header">' +
|
'<div class="project-header">' +
|
||||||
'<div>' +
|
'<div>' +
|
||||||
@@ -412,14 +413,81 @@ function initTechCloud() {
|
|||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// 动态生成技术项目
|
var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||||
techItems.forEach((tech, index) => {
|
var isMobile = window.matchMedia('(pointer: coarse)').matches || window.innerWidth <= 768;
|
||||||
var orbit = $('.orbit-' + tech.orbit);
|
if (!reduced && !isMobile) {
|
||||||
var techElement = $('<div class="tech-item ' + tech.level + '">' + tech.name + '</div>');
|
initTechSphere(techItems);
|
||||||
orbit.append(techElement);
|
return;
|
||||||
|
}
|
||||||
|
var container = $('.cloud-wrapper');
|
||||||
|
techItems.forEach(function(tech) {
|
||||||
|
var el = $('<span class="cloud-tag" data-category="' + (categoryOf(tech.level)) + '" data-weight="' + weightOf(tech.level) + '">' + tech.name + '</span>');
|
||||||
|
container.append(el);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function categoryOf(level) {
|
||||||
|
if (level === 'primary') return 'core';
|
||||||
|
if (level === 'secondary') return 'backend';
|
||||||
|
return 'ops';
|
||||||
|
}
|
||||||
|
|
||||||
|
function weightOf(level) {
|
||||||
|
if (level === 'primary') return 5;
|
||||||
|
if (level === 'secondary') return 3;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initTechSphere(items) {
|
||||||
|
var container = document.querySelector('.cloud-wrapper');
|
||||||
|
if (!container) return;
|
||||||
|
container.classList.add('sphere');
|
||||||
|
var N = items.length;
|
||||||
|
var tags = [];
|
||||||
|
for (var i = 0; i < N; i++) {
|
||||||
|
var item = items[i];
|
||||||
|
var el = document.createElement('span');
|
||||||
|
el.className = 'cloud-tag';
|
||||||
|
el.textContent = item.name;
|
||||||
|
el.setAttribute('data-category', categoryOf(item.level));
|
||||||
|
el.setAttribute('data-weight', weightOf(item.level));
|
||||||
|
el.style.left = '50%';
|
||||||
|
el.style.top = '50%';
|
||||||
|
container.appendChild(el);
|
||||||
|
tags.push(el);
|
||||||
|
}
|
||||||
|
var radius = 220;
|
||||||
|
var phiStep = Math.PI * (3 - Math.sqrt(5)); // golden angle
|
||||||
|
tags.forEach(function(el, idx) {
|
||||||
|
var y = 1 - (idx / (N - 1)) * 2;
|
||||||
|
var r = Math.sqrt(1 - y * y);
|
||||||
|
var theta = idx * phiStep;
|
||||||
|
var x = Math.cos(theta) * r;
|
||||||
|
var z = Math.sin(theta) * r;
|
||||||
|
var tx = x * radius;
|
||||||
|
var ty = y * radius;
|
||||||
|
var tz = z * radius;
|
||||||
|
el.style.position = 'absolute';
|
||||||
|
el.style.transform = 'translate3d(' + tx + 'px,' + ty + 'px,' + tz + 'px) translate(-50%, -50%)';
|
||||||
|
el.style.willChange = 'transform';
|
||||||
|
var depth = (z + 1) / 2; // 0..1
|
||||||
|
var scale = 0.85 + depth * 0.3;
|
||||||
|
var opacity = 0.7 + depth * 0.3;
|
||||||
|
el.style.opacity = String(opacity);
|
||||||
|
el.style.transform += ' scale(' + scale + ')';
|
||||||
|
el.style.zIndex = String(Math.floor(100 + depth * 100));
|
||||||
|
});
|
||||||
|
var rotY = 0;
|
||||||
|
var rotX = 8;
|
||||||
|
function animate() {
|
||||||
|
rotY += 0.3;
|
||||||
|
container.style.transform = 'perspective(800px) rotateX(' + rotX + 'deg) rotateY(' + rotY + 'deg)';
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
container.style.transformStyle = 'preserve-3d';
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
// 滚动效果
|
// 滚动效果
|
||||||
function initScrollEffects() {
|
function initScrollEffects() {
|
||||||
// 导航栏滚动效果
|
// 导航栏滚动效果
|
||||||
@@ -703,4 +771,12 @@ function hideWechatQR() {
|
|||||||
if (modal) {
|
if (modal) {
|
||||||
modal.style.display = "none";
|
modal.style.display = "none";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
function initThemeByTime() {
|
||||||
|
var hour = new Date().getHours();
|
||||||
|
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
var night = hour >= 18 || prefersDark;
|
||||||
|
var root = document.documentElement;
|
||||||
|
root.classList.toggle('theme-night', night);
|
||||||
|
root.classList.toggle('theme-day', !night);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user