|
|
/**
|
|
|
* Features Block Animation
|
|
|
* 特性展示区块动画效果
|
|
|
*/
|
|
|
|
|
|
// 等待GSAP准备就绪事件
|
|
|
function waitForGSAPReady(callback) {
|
|
|
if (window.gsap && window.ScrollTrigger) {
|
|
|
callback();
|
|
|
} else {
|
|
|
document.addEventListener('gsapReady', callback);
|
|
|
// 备用方案:如果事件未触发,使用定时器
|
|
|
setTimeout(() => {
|
|
|
if (window.gsap && window.ScrollTrigger) {
|
|
|
callback();
|
|
|
}
|
|
|
}, 3000);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 初始化特性区块动画
|
|
|
function initFeaturesAnimation() {
|
|
|
// 等待GSAP兼容性就绪
|
|
|
if (!document.body.classList.contains('gsap-ready')) {
|
|
|
document.addEventListener('gsapCompatibilityReady', initFeaturesAnimation);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 标题动画
|
|
|
const header = document.querySelector('.features-header');
|
|
|
if (header) {
|
|
|
// 检查是否在Elementor元素内
|
|
|
if (!header.closest('.elementor-element') || header.hasAttribute('data-gsap-ready')) {
|
|
|
createHeaderAnimation(header);
|
|
|
} else {
|
|
|
header.addEventListener('gsapElementReady', () => {
|
|
|
createHeaderAnimation(header);
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 统计数据项目动画
|
|
|
const statItems = document.querySelectorAll('.features-stat-item');
|
|
|
if (statItems.length > 0) {
|
|
|
statItems.forEach((item, index) => {
|
|
|
// 检查元素是否被Elementor暂停
|
|
|
if (item.hasAttribute('data-gsap-paused')) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 监听元素准备就绪事件
|
|
|
item.addEventListener('gsapElementReady', () => {
|
|
|
createStatItemAnimation(item, index);
|
|
|
});
|
|
|
|
|
|
// 如果元素已经准备就绪,直接创建动画
|
|
|
if (item.hasAttribute('data-gsap-ready') || !item.closest('.elementor-element')) {
|
|
|
createStatItemAnimation(item, index);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 数字计数动画
|
|
|
const statNumbers = document.querySelectorAll('.stat-number');
|
|
|
if (statNumbers.length > 0) {
|
|
|
statNumbers.forEach((numberElement, index) => {
|
|
|
// 检查元素是否被Elementor暂停
|
|
|
if (numberElement.hasAttribute('data-gsap-paused')) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 监听元素准备就绪事件
|
|
|
numberElement.addEventListener('gsapElementReady', () => {
|
|
|
createNumberAnimation(numberElement, index);
|
|
|
});
|
|
|
|
|
|
// 如果元素已经准备就绪,直接创建动画
|
|
|
if (numberElement.hasAttribute('data-gsap-ready') || !numberElement.closest('.elementor-element')) {
|
|
|
createNumberAnimation(numberElement, index);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 创建标题动画
|
|
|
function createHeaderAnimation(header) {
|
|
|
gsap.fromTo(header,
|
|
|
{
|
|
|
opacity: 0,
|
|
|
y: 30
|
|
|
},
|
|
|
{
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
duration: 1,
|
|
|
ease: "power2.out",
|
|
|
scrollTrigger: {
|
|
|
trigger: header,
|
|
|
start: "top 85%",
|
|
|
end: "bottom 20%",
|
|
|
toggleActions: "play none none reverse"
|
|
|
}
|
|
|
}
|
|
|
);
|
|
|
}
|
|
|
|
|
|
// 创建统计项目动画
|
|
|
function createStatItemAnimation(item, index) {
|
|
|
gsap.fromTo(item,
|
|
|
{
|
|
|
opacity: 0,
|
|
|
y: 50
|
|
|
},
|
|
|
{
|
|
|
opacity: 1,
|
|
|
y: 0,
|
|
|
duration: 0.8,
|
|
|
ease: "power2.out",
|
|
|
delay: index * 0.15, // 逐个显示,每个延迟0.15秒
|
|
|
scrollTrigger: {
|
|
|
trigger: item,
|
|
|
start: "top 80%",
|
|
|
end: "bottom 20%",
|
|
|
toggleActions: "play none none reverse"
|
|
|
}
|
|
|
}
|
|
|
);
|
|
|
}
|
|
|
|
|
|
// 创建数字计数动画
|
|
|
function createNumberAnimation(numberElement, index) {
|
|
|
const text = numberElement.textContent;
|
|
|
const hasPlus = text.includes('+');
|
|
|
const number = parseInt(text.replace(/[^0-9]/g, ''));
|
|
|
|
|
|
if (!isNaN(number)) {
|
|
|
// 设置初始值为0
|
|
|
numberElement.textContent = hasPlus ? '0+项' : '0项';
|
|
|
|
|
|
// 创建计数动画
|
|
|
gsap.to({value: 0}, {
|
|
|
value: number,
|
|
|
duration: 2,
|
|
|
ease: "power2.out",
|
|
|
delay: index * 0.15 + 0.5, // 在元素显示后开始计数
|
|
|
onUpdate: function() {
|
|
|
const currentValue = Math.round(this.targets()[0].value);
|
|
|
if (hasPlus) {
|
|
|
numberElement.textContent = currentValue + '+项';
|
|
|
} else {
|
|
|
numberElement.textContent = currentValue + '项';
|
|
|
}
|
|
|
},
|
|
|
scrollTrigger: {
|
|
|
trigger: numberElement,
|
|
|
start: "top 80%",
|
|
|
toggleActions: "play none none none"
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 等待GSAP准备就绪后初始化
|
|
|
waitForGSAPReady(() => {
|
|
|
// 注册 ScrollTrigger 插件
|
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
|
|
// DOM 加载完成后初始化动画
|
|
|
if (document.readyState === 'loading') {
|
|
|
document.addEventListener('DOMContentLoaded', initFeaturesAnimation);
|
|
|
} else {
|
|
|
initFeaturesAnimation();
|
|
|
}
|
|
|
|
|
|
// 如果是动态加载的内容,提供重新初始化的函数
|
|
|
window.reinitFeaturesAnimation = function() {
|
|
|
// 刷新 ScrollTrigger
|
|
|
ScrollTrigger.refresh();
|
|
|
initFeaturesAnimation();
|
|
|
};
|
|
|
});
|
|
|
|
|
|
// 如果GSAP未加载,显示警告
|
|
|
if (typeof gsap === 'undefined') {
|
|
|
} |