Files
all-personal-resume/个人简历_机械智能制造/gsap-animations.js

732 lines
24 KiB
JavaScript
Raw Normal View History

// GSAP动画配置文件
// 确保在DOM加载完成后执行动画
document.addEventListener('DOMContentLoaded', function() {
// 检查GSAP是否已加载
if (typeof gsap === 'undefined') {
console.warn('GSAP library is not loaded. Please include GSAP before this script.');
// 如果GSAP未加载确保所有元素可见
const allElements = document.querySelectorAll('.navbar, .contact-buttons .btn, .skill-category, .contact-item, .other-experience, .modern-project-showcase');
allElements.forEach(el => {
if (el) {
el.style.opacity = '1';
el.style.visibility = 'visible';
el.style.transform = '';
console.log(`Made ${el.className} visible (GSAP fallback)`);
}
});
return;
}
console.log('GSAP loaded successfully, initializing animations...');
// ===== 页面加载动画 =====
function initLoadingAnimations() {
// 隐藏加载器的动画
gsap.to("#loader", {
opacity: 0,
duration: 0.5,
delay: 1,
onComplete: function() {
document.getElementById('loader').style.display = 'none';
}
});
// 导航栏动画
// 首先确保导航栏存在
const navbarElement = document.querySelector(".navbar");
if (navbarElement) {
gsap.from(".navbar", {
y: -100,
opacity: 0,
duration: 0.8,
delay: 1.2,
ease: "back.out(1.7)"
});
} else {
console.warn('Navbar element not found for animation');
}
}
// ===== 首页英雄区域动画 =====
function initHeroAnimations() {
// 确保元素初始可见,然后应用动画
gsap.set([".hero-avatar", ".hero h1", ".hero .subtitle", ".hero .description", ".contact-buttons .btn"], {
clearProps: "all"
});
const tl = gsap.timeline({ delay: 1.5 });
tl.from(".hero-avatar", {
scale: 0,
rotation: 360,
duration: 1,
ease: "back.out(1.7)"
})
.from(".hero h1", {
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
}, "-=0.5")
.from(".hero .subtitle", {
y: 30,
opacity: 0,
duration: 0.6,
ease: "power2.out"
}, "-=0.3")
.from(".hero .description", {
y: 30,
opacity: 0,
duration: 0.6,
ease: "power2.out"
}, "-=0.2")
.from(".contact-buttons .btn", {
y: 30,
opacity: 0,
duration: 0.5,
stagger: 0.1,
ease: "power2.out"
}, "-=0.2");
}
// ===== 滚动触发动画 =====
function initScrollAnimations() {
// 注册ScrollTrigger插件
if (typeof ScrollTrigger !== 'undefined') {
gsap.registerPlugin(ScrollTrigger);
} else {
console.warn('ScrollTrigger plugin not found. Elements will be visible immediately.');
// 如果ScrollTrigger不可用确保所有元素可见
gsap.set([".skill-category", ".contact-item", ".other-experience", ".modern-project-showcase"], {
opacity: 1,
y: 0,
x: 0
});
return;
}
// 基本资料部分动画
gsap.from("#basic-info .section-title", {
scrollTrigger: {
trigger: "#basic-info",
start: "top 80%",
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
gsap.from("#basic-info .project-card", {
scrollTrigger: {
trigger: "#basic-info",
start: "top 70%",
toggleActions: "play none none reverse"
},
y: 80,
opacity: 0,
duration: 1,
delay: 0.2,
ease: "power2.out"
});
gsap.from("#basic-info .education-item", {
scrollTrigger: {
trigger: "#basic-info .education-item",
start: "top 80%",
toggleActions: "play none none reverse"
},
x: -80,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
// 技能卡片动画
gsap.from("#skills .section-title", {
scrollTrigger: {
trigger: "#skills",
start: "top 80%",
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
gsap.to(".skill-category", {
scrollTrigger: {
trigger: "#skills",
start: "top 70%",
toggleActions: "play none none reverse"
},
opacity: 1,
duration: 2,
scale: 1,
delay: 0.5,
ease: "cire.out"
});
// 项目展示动画
gsap.from("#experience .section-title", {
scrollTrigger: {
trigger: "#experience",
start: "top 80%",
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
// 只为可见的项目卡片设置动画
gsap.from("#industrial-design-content .modern-project-showcase", {
scrollTrigger: {
trigger: "#experience",
start: "top 70%",
toggleActions: "play none none reverse"
},
x: -100,
opacity: 0,
duration: 1.2,
ease: "power2.out"
});
// 为其他标签的项目卡片设置初始可见状态
gsap.set("#machining-content .modern-project-showcase, #automation-content .modern-project-showcase, #non-standard-content .modern-project-showcase", {
opacity: 1,
x: 0
});
// 实习经历标签动画
gsap.from(".experience-tab-btn", {
scrollTrigger: {
trigger: ".experience-tabs",
start: "top 80%",
toggleActions: "play none none reverse"
},
y: 30,
opacity: 0,
duration: 0.6,
stagger: 0.1,
ease: "power2.out"
});
gsap.from(".placeholder-card", {
scrollTrigger: {
trigger: ".experience-tab-content",
start: "top 70%",
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
// 个人总结动画 - 极宽松触发条件,适应所有标签页面高度
gsap.from("#summary .section-title", {
scrollTrigger: {
trigger: "#summary",
start: "top 50%", // 极宽松触发阈值,页面滚动即触发
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
gsap.from("#summary .summary-content", {
scrollTrigger: {
trigger: "#summary",
start: "top 50%", // 极宽松触发阈值,页面滚动即触发
toggleActions: "play none none reverse"
},
y: 30,
opacity: 0,
duration: 1,
delay: 0.2,
ease: "power2.out"
});
// 联系信息动画 - 极宽松触发条件,适应所有标签页面高度
gsap.from("#contact .section-title", {
scrollTrigger: {
trigger: "#contact",
start: "top 100%", // 极宽松触发阈值,页面滚动即触发
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
gsap.from(".contact-item", {
scrollTrigger: {
trigger: "#contact",
start: "top 100%", // 极宽松触发阈值,页面滚动即触发
toggleActions: "play none none reverse"
},
y: 50,
opacity: 0,
duration: 0.6,
stagger: 0.15,
ease: "power2.out"
});
}
// ===== 悬停交互动画 =====
function initHoverAnimations() {
// 项目卡片悬停动画
const projectCard = document.querySelector('.modern-project-showcase');
if (projectCard) {
projectCard.addEventListener('mouseenter', function() {
gsap.to(this, {
y: -15,
scale: 1.02,
duration: 0.3,
ease: "power2.out"
});
});
projectCard.addEventListener('mouseleave', function() {
gsap.to(this, {
y: 0,
scale: 1,
duration: 0.3,
ease: "power2.out"
});
});
}
// 技能卡片悬停动画
document.querySelectorAll('.skill-category').forEach(card => {
card.addEventListener('mouseenter', function() {
gsap.to(this, {
y: -8,
scale: 1.01,
duration: 0.3,
ease: "power2.out"
});
});
card.addEventListener('mouseleave', function() {
gsap.to(this, {
y: 0,
scale: 1,
duration: 0.3,
ease: "power2.out"
});
});
});
}
// ===== 弹窗动画增强 =====
function initModalAnimations() {
// 替换原有的职责弹窗动画
window.openResponsibilitiesModalGSAP = function() {
const modal = document.getElementById('responsibilitiesModal');
const content = modal.querySelector('.responsibilities-modal-content');
modal.style.display = 'block';
document.body.style.overflow = 'hidden';
// GSAP弹窗动画
gsap.fromTo(modal,
{ opacity: 0 },
{ opacity: 1, duration: 0.3 }
);
gsap.fromTo(content,
{ x: '-100%', opacity: 0 },
{ x: '0%', opacity: 1, duration: 0.4, ease: "power2.out" }
);
};
window.closeResponsibilitiesModalGSAP = function() {
const modal = document.getElementById('responsibilitiesModal');
const content = modal.querySelector('.responsibilities-modal-content');
// GSAP关闭动画
gsap.to(content, {
x: '100%',
opacity: 0,
duration: 0.4,
ease: "power2.in",
onComplete: function() {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
gsap.to(modal, {
opacity: 0,
duration: 0.3,
delay: 0.1
});
};
// 智能手表项目弹窗动画
window.openWatchProjectModalGSAP = function() {
const modal = document.getElementById('watchProjectModal');
const content = modal.querySelector('.responsibilities-modal-content');
modal.style.display = 'block';
document.body.style.overflow = 'hidden';
// GSAP弹窗动画
gsap.fromTo(modal,
{ opacity: 0 },
{ opacity: 1, duration: 0.3 }
);
gsap.fromTo(content,
{ x: '-100%', opacity: 0 },
{ x: '0%', opacity: 1, duration: 0.4, ease: "power2.out" }
);
};
window.closeWatchProjectModalGSAP = function() {
const modal = document.getElementById('watchProjectModal');
const content = modal.querySelector('.responsibilities-modal-content');
// GSAP关闭动画
gsap.to(content, {
x: '100%',
opacity: 0,
duration: 0.4,
ease: "power2.in",
onComplete: function() {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
gsap.to(modal, {
opacity: 0,
duration: 0.3,
delay: 0.1
});
};
}
// ===== 机械加工工艺项目弹窗动画 =====
function initMachiningProjectModalAnimations() {
window.openMachiningProjectModalGSAP = function() {
const modal = document.getElementById('machiningProjectModal');
if (!modal) return;
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
const modalContent = modal.querySelector('.responsibilities-modal-content');
// 重置初始状态
gsap.set(modal, { opacity: 0 });
gsap.set(modalContent, { x: '-100%', opacity: 0 });
// 弹窗背景淡入
gsap.to(modal, {
opacity: 1,
duration: 0.3,
ease: "power2.out"
});
// 内容区域从左侧滑入
gsap.to(modalContent, {
x: '0%',
opacity: 1,
duration: 0.5,
delay: 0.1,
ease: "power3.out"
});
};
window.closeMachiningProjectModalGSAP = function() {
const modal = document.getElementById('machiningProjectModal');
if (!modal) return;
const modalContent = modal.querySelector('.responsibilities-modal-content');
// 内容区域向右侧滑出
gsap.to(modalContent, {
x: '100%',
opacity: 0,
duration: 0.4,
ease: "power2.in",
onComplete: function() {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
gsap.to(modal, {
opacity: 0,
duration: 0.3,
delay: 0.1
});
};
}
// ===== 自动化控制项目弹窗动画 =====
function initAutomationProjectModalAnimations() {
window.openAutomationProjectModalGSAP = function() {
const modal = document.getElementById('automationProjectModal');
if (!modal) return;
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
const modalContent = modal.querySelector('.responsibilities-modal-content');
// 重置初始状态
gsap.set(modal, { opacity: 0 });
gsap.set(modalContent, { x: '-100%', opacity: 0 });
// 弹窗背景淡入
gsap.to(modal, {
opacity: 1,
duration: 0.3,
ease: "power2.out"
});
// 内容区域从左侧滑入
gsap.to(modalContent, {
x: '0%',
opacity: 1,
duration: 0.5,
delay: 0.1,
ease: "power3.out"
});
};
window.closeAutomationProjectModalGSAP = function() {
const modal = document.getElementById('automationProjectModal');
if (!modal) return;
const modalContent = modal.querySelector('.responsibilities-modal-content');
// 内容区域向右侧滑出
gsap.to(modalContent, {
x: '100%',
opacity: 0,
duration: 0.4,
ease: "power2.in",
onComplete: function() {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
gsap.to(modal, {
opacity: 0,
duration: 0.3,
delay: 0.1
});
};
}
// ===== 非标自动化项目弹窗动画 =====
function initNonStandardProjectModalAnimations() {
window.openNonStandardProjectModalGSAP = function() {
const modal = document.getElementById('nonStandardProjectModal');
if (!modal) return;
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
const modalContent = modal.querySelector('.responsibilities-modal-content');
// 重置初始状态
gsap.set(modal, { opacity: 0 });
gsap.set(modalContent, { x: '-100%', opacity: 0 });
// 弹窗背景淡入
gsap.to(modal, {
opacity: 1,
duration: 0.3,
ease: "power2.out"
});
// 内容区域从左侧滑入
gsap.to(modalContent, {
x: '0%',
opacity: 1,
duration: 0.5,
delay: 0.1,
ease: "power3.out"
});
};
window.closeNonStandardProjectModalGSAP = function() {
const modal = document.getElementById('nonStandardProjectModal');
if (!modal) return;
const modalContent = modal.querySelector('.responsibilities-modal-content');
// 内容区域向右侧滑出
gsap.to(modalContent, {
x: '100%',
opacity: 0,
duration: 0.4,
ease: "power2.in",
onComplete: function() {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
});
gsap.to(modal, {
opacity: 0,
duration: 0.3,
delay: 0.1
});
};
}
// ===== 粒子背景动画增强 =====
function initParticleAnimations() {
// 可以在这里添加与粒子背景的GSAP交互
// 例如:鼠标移动时的粒子响应动画
}
// ===== 返回顶部按钮动画管理 =====
function initScrollTopButtonAnimation() {
let scrollTopAnimation = null;
const scrollTopButton = document.getElementById('scrollTop');
if (!scrollTopButton) return;
// 全局函数供外部调用
window.startScrollTopAnimation = function() {
if (!scrollTopAnimation) {
scrollTopAnimation = gsap.to(scrollTopButton, {
y: -10,
duration: 1.5,
repeat: -1,
yoyo: true,
ease: "power2.inOut"
});
}
};
window.stopScrollTopAnimation = function() {
if (scrollTopAnimation) {
scrollTopAnimation.kill();
gsap.set(scrollTopButton, { y: 0 });
scrollTopAnimation = null;
}
};
}
// ===== 统一的元素可见性确保机制 =====
function ensureElementsVisible() {
// 确保关键元素始终可见,防止动画失败导致元素消失
const criticalElements = [
'.navbar', // 导航栏
'.contact-buttons .btn', // 首页按钮
'.skill-category', // 技能卡片
'.contact-item', // 联系方式
'.experience-tab-btn', // 实习经历标签
'.modern-project-showcase' // 项目展示
];
criticalElements.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(el => {
if (el) {
// 检查元素是否可能被隐藏
const computedStyle = window.getComputedStyle(el);
const isHidden = el.style.opacity === '0' ||
el.style.visibility === 'hidden' ||
computedStyle.opacity === '0' ||
computedStyle.visibility === 'hidden';
if (isHidden) {
console.log(`Making ${selector} visible as fallback`);
if (typeof gsap !== 'undefined') {
// 优先使用GSAP设置
gsap.set(el, { opacity: 1, visibility: 'visible', y: 0, x: 0 });
} else {
// 回退到原生CSS
el.style.opacity = '1';
el.style.visibility = 'visible';
el.style.transform = '';
}
}
}
});
});
}
// ===== 初始化所有动画 =====
function initAllAnimations() {
try {
initLoadingAnimations();
initHeroAnimations();
initScrollAnimations();
initHoverAnimations();
initModalAnimations();
initMachiningProjectModalAnimations();
initAutomationProjectModalAnimations();
initNonStandardProjectModalAnimations();
initParticleAnimations();
initScrollTopButtonAnimation();
// 延迟检查元素可见性
setTimeout(ensureElementsVisible, 2000);
} catch (error) {
console.error('GSAP animation initialization failed:', error);
// 如果动画初始化失败,确保所有元素可见
ensureElementsVisible();
}
}
// 启动动画系统
initAllAnimations();
// 暴露一些函数到全局作用域以便HTML中调用
window.gsapAnimations = {
openModal: window.openResponsibilitiesModalGSAP,
closeModal: window.closeResponsibilitiesModalGSAP,
openWatchModal: window.openWatchProjectModalGSAP,
closeWatchModal: window.closeWatchProjectModalGSAP
};
});
// ===== 工具函数 =====
function createTextAnimation(selector, options = {}) {
const defaults = {
y: 30,
opacity: 0,
duration: 0.6,
stagger: 0.1,
ease: "power2.out"
};
const settings = { ...defaults, ...options };
return gsap.from(selector, settings);
}
function createFadeInAnimation(selector, direction = 'up', distance = 50) {
const transforms = {
up: { y: distance },
down: { y: -distance },
left: { x: distance },
right: { x: -distance }
};
return gsap.from(selector, {
...transforms[direction],
opacity: 0,
duration: 0.8,
ease: "power2.out"
});
}