mirror of
http://junepve.top:3000/chicrobot/mainPage.git
synced 2026-10-30 03:11:29 +08:00
首页
This commit is contained in:
1 parent
911704faf9
commit
5b79e9e733
2120 files changed
+362230
No files matched your search
@@ -0,0 +1,544 @@
|
||||
// 获取所有导航链接
|
||||
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属性
|
||||
document.getElementById('portainerLink').href = portainerUrl;
|
||||
document.getElementById('giteaLink').href = giteaUrl;
|
||||
document.getElementById('grafanaLink').href = grafanaUrl;
|
||||
document.getElementById('jenkinsLink').href = jenkinsUrl;
|
||||
});
|
||||
|
||||
// 粒子背景效果
|
||||
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[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
const targetId = this.getAttribute('href');
|
||||
// 检查是否是有效的ID选择器(以#开头且不是URL)
|
||||
if (targetId && targetId.startsWith('#') && targetId.length > 1 && !targetId.includes('://')) {
|
||||
const targetElement = document.querySelector(targetId);
|
||||
if (targetElement) {
|
||||
// 只在找到目标元素时阻止默认行为
|
||||
e.preventDefault();
|
||||
targetElement.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
// 如果找不到目标元素,不阻止默认行为
|
||||
} else if (targetId === '#') {
|
||||
// 处理 href="#" 的情况,滚动到页面顶部
|
||||
e.preventDefault();
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
// 对于URL链接等其他情况,不调用e.preventDefault(),允许浏览器正常跳转
|
||||
});
|
||||
});
|
||||
|
||||
// 视觉风格切换器功能
|
||||
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);
|
||||
}
|
||||
Reference in new issue
Block a user