Files
mainPage/script.js
T

572 lines
19 KiB
JavaScript

// 获取所有导航链接
const navLinks = document.querySelectorAll('.nav-link');
const sections = document.querySelectorAll('section');
// 点击导航链接时更新active类
navLinks.forEach(link => {
link.addEventListener('click', function() {
// 移除所有链接的active类
navLinks.forEach(l => l.classList.remove('active'));
// 为当前点击的链接添加active类
this.classList.add('active');
});
});
// 滚动时更新active类
function updateActiveNavLink() {
let currentSectionId = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (window.scrollY >= (sectionTop - 200) && window.scrollY < (sectionTop + sectionHeight - 200)) {
currentSectionId = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === '#' + currentSectionId) {
link.classList.add('active');
}
});
}
// 监听滚动事件,使用节流优化
let isScrolling;
window.addEventListener('scroll', function() {
// 清除之前的计时器
clearTimeout(isScrolling);
// 设置一个新的计时器,在滚动停止后50毫秒执行
isScrolling = setTimeout(updateActiveNavLink, 50);
}, false);
// 页面加载时也执行一次
updateActiveNavLink();
window.addEventListener('load', function() {
// 获取当前页面的域名或IP
const currentHost = window.location.hostname;
// 构建跳转URL (保持相同的协议和域名/IP,只修改端口)
const portainerUrl = `${window.location.protocol}//${currentHost}:9000`;
const giteaUrl = `${window.location.protocol}//${currentHost}:3000`;
const grafanaUrl = `${window.location.protocol}//${currentHost}:3001`;
const jenkinsUrl = `${window.location.protocol}//${currentHost}:9095`;
// 设置链接的href属性和target属性,确保在新标签中打开
const portainerLink = document.getElementById('portainerLink');
const giteaLink = document.getElementById('giteaLink');
const grafanaLink = document.getElementById('grafanaLink');
const jenkinsLink = document.getElementById('jenkinsLink');
if (portainerLink) {
portainerLink.href = portainerUrl;
portainerLink.target = '_blank';
}
if (giteaLink) {
giteaLink.href = giteaUrl;
giteaLink.target = '_blank';
}
if (grafanaLink) {
grafanaLink.href = grafanaUrl;
grafanaLink.target = '_blank';
}
if (jenkinsLink) {
jenkinsLink.href = jenkinsUrl;
jenkinsLink.target = '_blank';
}
});
// 粒子背景效果
const canvas = document.getElementById('particleCanvas');
const ctx = canvas.getContext('2d');
// 设置画布大小
function setCanvasSize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
setCanvasSize();
window.addEventListener('resize', setCanvasSize);
// 粒子类
class Particle {
constructor() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.size = Math.random() * 2 + 0.5;
this.speedX = Math.random() * 0.5 - 0.25;
this.speedY = Math.random() * 0.5 - 0.25;
this.color = Math.random() > 0.5 ? '#00ffeb' : '#ff6b35';
this.alpha = Math.random() * 0.7 + 0.3;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
// 边界检测
if (this.x < 0 || this.x > canvas.width) this.speedX *= -1;
if (this.y < 0 || this.y > canvas.height) this.speedY *= -1;
}
draw() {
ctx.fillStyle = `${this.color}${Math.floor(this.alpha * 255).toString(16)}`;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
// 创建粒子数组
const particles = [];
const particleCount = 150;
for (let i = 0; i < particleCount; i++) {
particles.push(new Particle());
}
// 连接粒子效果
function connectParticles() {
for (let a = 0; a < particles.length; a++) {
for (let b = a; b < particles.length; b++) {
const dx = particles[a].x - particles[b].x;
const dy = particles[a].y - particles[b].y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// 根据粒子颜色决定连接线颜色
const color = particles[a].color === '#00ffeb' && particles[b].color === '#00ffeb' ? '#00ffeb' :
particles[a].color === '#ff6b35' && particles[b].color === '#ff6b35' ? '#ff6b35' : '#e0e0e0';
ctx.beginPath();
ctx.strokeStyle = `rgba(${hexToRgb(color).r}, ${hexToRgb(color).g}, ${hexToRgb(color).b}, ${0.1 - distance/1000})`;
ctx.lineWidth = 0.5;
ctx.moveTo(particles[a].x, particles[a].y);
ctx.lineTo(particles[b].x, particles[b].y);
ctx.stroke();
}
}
}
}
// 十六进制颜色转RGB
function hexToRgb(hex) {
// 移除#如果存在
hex = hex.replace('#', '');
// 解析RGB值
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}
// 系统状态图表
const ctxChart = document.getElementById('systemChart').getContext('2d');
// 生成随机数据
function generateData() {
return Array.from({length: 20}, () => Math.floor(Math.random() * 80) + 20);
}
const cpuData = generateData();
const memoryData = generateData();
const networkData = generateData();
const labels = Array.from({length: 20}, (_, i) => i);
// 根据主题获取图表颜色配置
function getChartColors(theme) {
switch(theme) {
case 'cyber':
return {
cpuBorder: '#ff6b35',
cpuBackground: 'rgba(255, 107, 53, 0.1)',
memoryBorder: '#00ffeb',
memoryBackground: 'rgba(0, 255, 235, 0.1)',
networkBorder: '#e0e0e0',
networkBackground: 'rgba(224, 224, 224, 0.1)',
gridColor: 'rgba(255, 255, 255, 0.05)',
tickColor: 'rgba(224, 224, 224, 0.7)',
legendColor: 'rgba(224, 224, 224, 0.9)',
tooltipBackground: 'rgba(10, 14, 23, 0.8)',
tooltipText: '#e0e0e0',
tooltipBorder: 'rgba(255, 255, 255, 0.1)'
};
case 'minimal':
return {
cpuBorder: '#333333', // 深灰色
cpuBackground: 'rgba(51, 51, 51, 0.1)',
memoryBorder: '#666666', // 中灰色
memoryBackground: 'rgba(102, 102, 102, 0.1)',
networkBorder: '#999999', // 浅灰色
networkBackground: 'rgba(153, 153, 153, 0.1)',
gridColor: 'rgba(0, 0, 0, 0.05)',
tickColor: 'rgba(224, 224, 224, 0.7)',
legendColor: 'rgba(224, 224, 224, 0.9)',
tooltipBackground: 'rgba(10, 14, 23, 0.8)',
tooltipText: '#e0e0e0',
tooltipBorder: 'rgba(0, 0, 0, 0.1)'
};
case 'gallery':
return {
cpuBorder: '#ff758f', // 粉色
cpuBackground: 'rgba(255, 117, 143, 0.1)',
memoryBorder: '#4dabf7', // 蓝色
memoryBackground: 'rgba(77, 171, 247, 0.1)',
networkBorder: '#333333',
networkBackground: 'rgba(51, 51, 51, 0.1)',
gridColor: 'rgba(0, 0, 0, 0.05)',
tickColor: 'rgba(224, 224, 224, 0.7)',
legendColor: 'rgba(224, 224, 224, 0.9)',
tooltipBackground: 'rgba(10, 14, 23, 0.8)',
tooltipText: '#e0e0e0',
tooltipBorder: 'rgba(77, 171, 247, 0.2)'
};
default:
return getChartColors('cyber');
}
}
// 创建图表
function createSystemChart(theme) {
const colors = getChartColors(theme);
return new Chart(ctxChart, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'CPU 使用率 (%)',
data: cpuData,
borderColor: colors.cpuBorder,
backgroundColor: colors.cpuBackground,
tension: 0.4,
fill: true,
borderWidth: 2,
pointRadius: 0, // 设置为0移除圆点
pointHoverRadius: 0 // 设置为0移除悬停圆点
},
{
label: '内存使用率 (%)',
data: memoryData,
borderColor: colors.memoryBorder,
backgroundColor: colors.memoryBackground,
tension: 0.4,
fill: true,
borderWidth: 2,
pointRadius: 0, // 设置为0移除圆点
pointHoverRadius: 0 // 设置为0移除悬停圆点
},
{
label: '网络流量 (MB/s)',
data: networkData,
borderColor: colors.networkBorder,
backgroundColor: colors.networkBackground,
tension: 0.4,
fill: true,
borderWidth: 2,
pointRadius: 0, // 设置为0移除圆点
pointHoverRadius: 0 // 设置为0移除悬停圆点
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
grid: {
color: colors.gridColor
},
ticks: {
color: colors.tickColor
}
},
y: {
grid: {
color: colors.gridColor
},
ticks: {
color: colors.tickColor
},
beginAtZero: true,
max: 100
}
},
plugins: {
legend: {
labels: {
color: colors.legendColor
}
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: colors.tooltipBackground,
titleColor: colors.tooltipText,
bodyColor: colors.tooltipText,
borderColor: colors.tooltipBorder,
borderWidth: 1,
boxPadding: 10,
bodyPadding: 10
}
},
interaction: {
mode: 'nearest',
axis: 'x',
intersect: false
},
animations: {
tension: {
duration: 1000,
easing: 'linear'
}
}
}
});
}
// 初始化图表
let systemChart = createSystemChart(document.body.getAttribute('data-theme') || 'cyber');
// 更新图表数据
function updateChart() {
cpuData.shift();
cpuData.push(Math.floor(Math.random() * 80) + 20);
memoryData.shift();
memoryData.push(Math.floor(Math.random() * 80) + 20);
networkData.shift();
networkData.push(Math.floor(Math.random() * 50) + 5);
systemChart.update();
}
// 每3秒更新一次图表
setInterval(updateChart, 3000);
// 导航栏滚动效果
window.addEventListener('scroll', () => {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 50) {
navbar.style.padding = '15px 0';
navbar.style.boxShadow = '0 5px 15px rgba(0, 0, 0, 0.3)';
} else {
navbar.style.padding = '20px 0';
navbar.style.boxShadow = 'none';
}
});
// 服务卡片悬停效果增强
const serviceCards = document.querySelectorAll('.service-card');
serviceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
card.style.transform = 'translateY(-10px) scale(1.02)';
card.style.boxShadow = '0 15px 30px rgba(0, 0, 0, 0.5), 0 0 15px rgba(0, 255, 235, 0.3)';
});
card.addEventListener('mouseleave', () => {
card.style.transform = 'translateY(0) scale(1)';
card.style.boxShadow = '0 8px 32px 0 rgba(0, 0, 0, 0.37)';
});
});
// 平滑滚动和链接处理
document.querySelectorAll('a').forEach(anchor => {
anchor.addEventListener('click', function (e) {
const href = this.getAttribute('href');
const target = this.getAttribute('target');
// 如果已经设置了target="_blank",让浏览器正常处理跳转
if (target === '_blank') {
return;
}
// 检查是否是有效的页面内ID选择器(以#开头且不是URL)
if (href && href.startsWith('#') && href.length > 1 && !href.includes('://')) {
const targetElement = document.querySelector(href);
if (targetElement) {
// 只在找到目标元素时阻止默认行为
e.preventDefault();
targetElement.scrollIntoView({
behavior: 'smooth'
});
}
// 如果找不到目标元素,不阻止默认行为
} else if (href === '#') {
// 处理 href="#" 的情况,滚动到页面顶部
e.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
// 对于URL链接等其他情况,如果没有设置target="_blank",添加它
else if (href && !href.startsWith('#') && (href.includes('://') || href.startsWith('//'))) {
// 不阻止默认行为,让浏览器处理带target="_blank"的跳转
this.target = '_blank';
}
});
});
// 视觉风格切换器功能
const themeToggle = document.getElementById('themeToggle');
const themeMenu = document.getElementById('themeMenu');
const themeOptions = document.querySelectorAll('.theme-option');
const particleCanvas = document.getElementById('particleCanvas');
// 在animate()函数前添加animationId变量声明
let animationId;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].draw();
}
// 连接相近的粒子
connectParticles();
animationId = requestAnimationFrame(animate);
}
// 页面加载完成后执行
window.addEventListener('load', () => {
// 添加页面加载动画
document.body.classList.add('loaded');
// 初始化粒子颜色
const initialTheme = document.body.getAttribute('data-theme') || 'cyber';
updateParticleColors(initialTheme);
// 初始化动态效果
toggleDynamicEffects(initialTheme);
// 启动动画(确保在DOM加载完成后)
animate();
});
// 切换菜单显示/隐藏
themeToggle.addEventListener('click', () => {
themeMenu.classList.toggle('active');
});
// 点击页面其他区域关闭菜单
document.addEventListener('click', (e) => {
if (!themeToggle.contains(e.target) && !themeMenu.contains(e.target)) {
themeMenu.classList.remove('active');
}
});
// 主题切换功能
themeOptions.forEach(option => {
option.addEventListener('click', () => {
// 移除所有选项的active类
themeOptions.forEach(opt => opt.classList.remove('active'));
// 为当前选项添加active类
option.classList.add('active');
// 获取主题值
const theme = option.getAttribute('data-theme');
// 设置body的data-theme属性
document.body.setAttribute('data-theme', theme);
// 更新图标
updateThemeIcon(theme);
// 更新粒子背景颜色
updateParticleColors(theme);
// 切换动态效果
toggleDynamicEffects(theme);
// 关闭菜单
themeMenu.classList.remove('active');
});
});
// 更新主题图标
function updateThemeIcon(theme) {
const icon = themeToggle.querySelector('i');
switch(theme) {
case 'cyber':
icon.className = 'fas fa-bolt';
break;
case 'minimal':
icon.className = 'fas fa-moon';
break;
case 'gallery':
icon.className = 'fas fa-palette';
break;
}
}
// 更新粒子背景颜色
function updateParticleColors(theme) {
let primaryColor, secondaryColor;
let particleVisibility = 'visible';
switch(theme) {
case 'cyber':
primaryColor = '#00ffeb';
secondaryColor = '#ff6b35';
particleVisibility = 'visible';
break;
case 'minimal':
primaryColor = '#6c757d';
secondaryColor = '#6c757d';
particleVisibility = 'hidden';
break;
case 'gallery':
primaryColor = '#ff758f'; // 粉色
secondaryColor = '#4dabf7'; // 蓝色
particleVisibility = 'visible';
break;
}
// 设置粒子可见性
if (particleCanvas) {
particleCanvas.style.visibility = particleVisibility;
}
particles.forEach(particle => {
particle.color = Math.random() > 0.5 ? primaryColor : secondaryColor;
});
}
// 切换动态效果
function toggleDynamicEffects(theme) {
// 暂停/恢复粒子动画
if (theme === 'minimal') {
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null;
}
// 移除视差滚动效果
document.querySelectorAll('[data-parallax]').forEach(el => {
el.style.transform = 'translateY(0)';
el.removeAttribute('data-parallax');
el.setAttribute('data-parallax-disabled', 'true');
});
// 移除悬停效果
document.querySelectorAll('.service-card, .thought-card, .friend-card, .lab-card').forEach(card => {
card.style.transform = 'none';
card.style.boxShadow = 'none';
});
} else {
// 恢复粒子动画
if (!animationId) {
animate();
}
// 恢复视差滚动效果
document.querySelectorAll('[data-parallax-disabled]').forEach(el => {
el.setAttribute('data-parallax', '0.3');
el.removeAttribute('data-parallax-disabled');
});
}
// 添加以下代码来更新图表颜色
// 销毁旧图表
if (systemChart) {
systemChart.destroy();
}
// 使用新主题创建新图表
systemChart = createSystemChart(theme);
}