You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

603 lines
23 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* GSAP与Elementor兼容性管理器
* GSAP and Elementor Compatibility Manager
*
* 此文件确保GSAP动画与Elementor内置动画系统的兼容性
* This file ensures compatibility between GSAP animations and Elementor's built-in animation system
*
* @package Nenghui Energy Theme
* @since 1.0.0
*/
(function() {
'use strict';
// GSAP与Elementor兼容性管理器
const GSAPElementorCompatibility = {
initialized: false,
elementorAnimations: new Set(),
gsapAnimations: new Set(),
// 初始化
init: function() {
if (this.initialized) return;
// 添加页面就绪状态标记
document.body.classList.add('gsap-ready');
// 设置GSAP默认值
this.setupGSAPDefaults();
// 设置Elementor钩子
this.setupElementorHooks();
// 设置备用兼容性检查
this.setupFallbackCompatibility();
this.initialized = true;
// 触发初始化完成事件
const event = new CustomEvent('gsapCompatibilityReady');
document.dispatchEvent(event);
},
// 等待依赖加载
waitForDependencies: function(callback) {
let attempts = 0;
const maxAttempts = 100; // 增加等待时间到10秒
const checkDependencies = () => {
attempts++;
const gsapReady = window.gsap && window.ScrollTrigger;
const elementorReady = window.elementorFrontend && window.elementorFrontend.hooks;
if (gsapReady) {
// GSAP准备好了检查Elementor状态
if (elementorReady || attempts > 30) {
// Elementor也准备好了或者已经等待足够长时间
callback();
} else {
// 继续等待Elementor
setTimeout(checkDependencies, 100);
}
} else if (attempts < maxAttempts) {
// 继续等待GSAP
setTimeout(checkDependencies, 100);
} else {
// 超时,但仍然尝试继续
callback();
}
};
checkDependencies();
},
// 设置兼容性
setupCompatibility: function() {
// 设置GSAP默认值和基础配置
this.setupGSAPDefaults();
// 检查Elementor是否可用且hooks已准备好
if (window.elementorFrontend && window.elementorFrontend.hooks && typeof window.elementorFrontend.hooks.addAction === 'function') {
this.setupElementorHooks();
} else {
// 延迟再次检查Elementor
setTimeout(() => {
if (window.elementorFrontend && window.elementorFrontend.hooks) {
this.setupElementorHooks();
}
}, 1000);
}
this.setupScrollTriggerCompatibility();
this.setupAnimationConflictResolution();
this.setupGlobalAnimationManager();
},
// 设置Elementor兼容性钩子 - 改进版本
setupElementorHooks: function() {
// 检查Elementor是否可用
if (typeof elementorFrontend !== 'undefined' && elementorFrontend.hooks) {
this.initElementorHooks();
} else {
// 监听Elementor前端加载事件
document.addEventListener('DOMContentLoaded', () => {
// 使用更长的延迟确保Elementor完全加载
setTimeout(() => {
if (typeof elementorFrontend !== 'undefined' && elementorFrontend.hooks) {
this.initElementorHooks();
} else {
this.setupFallbackCompatibility();
}
}, 2000); // 增加延迟到2秒
});
}
},
// 初始化Elementor钩子
initElementorHooks: function() {
try {
// 检查elementorFrontend和hooks是否存在
if (!elementorFrontend || !elementorFrontend.hooks || typeof elementorFrontend.hooks.addAction !== 'function') {
return;
}
// 监听Elementor元素准备就绪事件
elementorFrontend.hooks.addAction('frontend/element_ready/global', (scope) => {
this.handleElementorElementReady(scope);
});
// 监听Elementor动画开始事件
elementorFrontend.hooks.addAction('frontend/element_ready/widget', (scope) => {
this.handleElementorWidgetReady(scope);
});
// 监听页面加载完成
if (elementorFrontend.hooks && typeof elementorFrontend.hooks.addAction === 'function') {
elementorFrontend.hooks.addAction('frontend/init', () => {
this.onElementorFrontendInit();
});
}
} catch (error) {
this.setupFallbackCompatibility();
}
},
// 备用兼容性方案
setupFallbackCompatibility: function() {
// 使用MutationObserver监听DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
// 验证节点是否为有效的DOM元素
if (node && node.nodeType === Node.ELEMENT_NODE) {
// 检查是否是Elementor元素
if (node.classList && (
node.classList.contains('elementor-element') ||
node.classList.contains('elementor-widget') ||
node.querySelector('.elementor-element')
)) {
// 添加延迟以确保元素完全加载
setTimeout(() => {
this.handleElementorElement(node);
}, 100);
}
}
});
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// 处理已存在的Elementor元素
setTimeout(() => {
const existingElements = document.querySelectorAll('.elementor-element, .elementor-widget');
existingElements.forEach(element => {
// 验证元素有效性
if (element && element.nodeType === Node.ELEMENT_NODE) {
this.handleElementorElement(element);
}
});
}, 1000);
},
// 处理Elementor元素
handleElementorElement: function(element) {
// 延迟处理确保Elementor动画已初始化
setTimeout(() => {
// 检查元素是否有动画设置
const hasAnimation = element.classList.contains('elementor-invisible') ||
element.hasAttribute('data-settings') ||
element.querySelector('[data-settings*="animation"]');
if (hasAnimation) {
// 暂停该元素的GSAP动画
this.pauseGSAPForElement(element);
// 监听Elementor动画完成
this.waitForElementorAnimation(element, () => {
this.enableGSAPForElement(element);
});
} else {
// 没有Elementor动画可以安全使用GSAP
this.enableGSAPForElement(element);
}
}, 500);
},
// 暂停元素的GSAP动画
pauseGSAPForElement: function(element) {
if (window.gsap) {
gsap.killTweensOf(element);
gsap.killTweensOf(element.querySelectorAll('*'));
element.setAttribute('data-gsap-paused', 'true');
}
},
// 启用元素的GSAP动画
enableGSAPForElement: function(element) {
element.removeAttribute('data-gsap-paused');
element.setAttribute('data-gsap-ready', 'true');
// 触发自定义事件通知GSAP动画可以开始
const event = new CustomEvent('gsapElementReady', {
detail: { element: element }
});
element.dispatchEvent(event);
},
// 等待Elementor动画完成
waitForElementorAnimation: function(element, callback) {
let attempts = 0;
const maxAttempts = 50; // 5秒超时
const checkAnimation = () => {
// 检查元素是否还有elementor-invisible类
if (!element.classList.contains('elementor-invisible')) {
callback();
return;
}
attempts++;
if (attempts < maxAttempts) {
setTimeout(checkAnimation, 100);
} else {
callback(); // 超时也执行回调
}
};
checkAnimation();
},
// 处理Elementor元素
handleElementorElement: function(scope) {
// 验证scope参数
if (!scope) {
return;
}
// 确保scope是DOM元素或jQuery对象
let element;
if (scope.jquery) {
// 如果是jQuery对象获取第一个DOM元素
element = scope[0];
} else if (scope.nodeType === Node.ELEMENT_NODE) {
// 如果是DOM元素
element = scope;
} else {
return;
}
// 验证最终的DOM元素
if (!element || !element.nodeType || element.nodeType !== Node.ELEMENT_NODE) {
return;
}
const $scope = jQuery(element);
// 检查是否有Elementor动画
const hasElementorAnimation = $scope.find('[data-settings*="animation"]').length > 0 ||
$scope.hasClass('elementor-invisible') ||
$scope.find('.elementor-invisible').length > 0;
if (hasElementorAnimation) {
this.elementorAnimations.add(element);
// 为有Elementor动画的元素添加标记
$scope.attr('data-has-elementor-animation', 'true');
// 延迟初始化GSAP动画避免冲突
setTimeout(() => {
this.initGSAPForElement(element);
}, 300);
} else {
// 没有Elementor动画的元素可以立即初始化GSAP
this.initGSAPForElement(element);
}
},
// 为元素初始化GSAP动画
initGSAPForElement: function(element) {
// 验证元素是否存在且为有效的DOM元素
if (!element || !element.nodeType || element.nodeType !== Node.ELEMENT_NODE) {
return;
}
// 检查元素是否已经有GSAP动画
if (element.hasAttribute('data-gsap-initialized')) return;
// 标记为已初始化
element.setAttribute('data-gsap-initialized', 'true');
// 这里可以添加特定的GSAP动画逻辑
// 例如hover效果、滚动触发动画等
},
// 暂停冲突的GSAP动画
pauseConflictingGSAPAnimations: function(scope) {
const gsapElements = scope.querySelectorAll('[data-gsap-initialized]');
gsapElements.forEach(element => {
// 暂停该元素上的所有GSAP动画
gsap.killTweensOf(element);
});
},
// 设置GSAP默认值
setupGSAPDefaults: function() {
if (!window.gsap) {
return;
}
// 设置GSAP默认缓动函数与Elementor保持一致
gsap.defaults({
ease: "power2.out",
duration: 0.6,
overwrite: "auto" // 自动覆盖冲突的动画
});
// 设置ScrollTrigger默认值
if (window.ScrollTrigger) {
ScrollTrigger.defaults({
toggleActions: "play none none reverse",
markers: false,
scroller: window, // 确保使用正确的滚动容器
refreshPriority: 1 // 提高刷新优先级
});
// 注册ScrollTrigger插件
gsap.registerPlugin(ScrollTrigger);
}
// 禁用GSAP的自动CSS前缀避免与Elementor冲突
gsap.config({
autoSleep: 60,
force3D: false, // 避免强制3D变换
nullTargetWarn: false // 减少警告信息
});
},
// 设置ScrollTrigger兼容性
setupScrollTriggerCompatibility: function() {
if (!window.ScrollTrigger) return;
// 监听Elementor的滚动事件
window.addEventListener('scroll', this.debounce(() => {
// 在滚动时刷新ScrollTrigger确保与Elementor动画同步
ScrollTrigger.refresh();
}, 100), { passive: true });
// 监听窗口大小变化
window.addEventListener('resize', this.debounce(() => {
ScrollTrigger.refresh();
}, 250));
// 在Elementor编辑模式下禁用ScrollTrigger
if (this.isElementorEditMode()) {
ScrollTrigger.disable();
}
},
// 设置动画冲突解决方案
setupAnimationConflictResolution: function() {
// 创建观察器来监听DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
this.resolveAnimationConflicts(node);
}
});
}
});
});
// 开始观察
observer.observe(document.body, {
childList: true,
subtree: true
});
},
// 解决动画冲突
resolveAnimationConflicts: function(element) {
// 检查元素是否同时有Elementor和GSAP动画
const hasElementorAnim = element.hasAttribute('data-has-elementor-animation') ||
element.classList.contains('elementor-invisible');
const hasGSAPAnim = element.hasAttribute('data-gsap-initialized');
if (hasElementorAnim && hasGSAPAnim) {
// 优先使用Elementor动画暂停GSAP动画
gsap.killTweensOf(element);
// 等待Elementor动画完成后再启用GSAP
setTimeout(() => {
this.initGSAPForElement(element);
}, 1000);
}
},
// 检查是否在Elementor编辑模式
isElementorEditMode: function() {
return window.elementorFrontend && window.elementorFrontend.isEditMode();
},
// 防抖函数
debounce: function(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
}
},
// 全局动画管理器
setupGlobalAnimationManager: function() {
// 创建全局动画管理器
window.GSAPAnimationManager = {
activeAnimations: new Map(),
// 注册动画
register: function(id, animation) {
this.activeAnimations.set(id, animation);
},
// 暂停所有动画
pauseAll: function() {
this.activeAnimations.forEach(animation => {
if (animation && animation.pause) {
animation.pause();
}
});
},
// 恢复所有动画
resumeAll: function() {
this.activeAnimations.forEach(animation => {
if (animation && animation.resume) {
animation.resume();
}
});
},
// 清理动画
cleanup: function(id) {
const animation = this.activeAnimations.get(id);
if (animation && animation.kill) {
animation.kill();
}
this.activeAnimations.delete(id);
}
};
// 监听页面可见性变化
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
window.GSAPAnimationManager.pauseAll();
} else {
window.GSAPAnimationManager.resumeAll();
}
});
},
// 公共API方法
api: {
// 安全地创建GSAP动画
createAnimation: function(target, vars, options = {}) {
if (!window.gsap) {
console.warn('GSAP未加载无法创建动画');
return null;
}
const element = typeof target === 'string' ? document.querySelector(target) : target;
if (!element) {
console.warn('目标元素未找到:', target);
return null;
}
// 检查是否有Elementor动画冲突
if (element.hasAttribute('data-has-elementor-animation') ||
element.classList.contains('elementor-invisible')) {
console.warn('元素有Elementor动画延迟GSAP动画');
return new Promise((resolve) => {
setTimeout(() => {
const animation = gsap.to(element, vars);
if (window.GSAPAnimationManager && options.id) {
window.GSAPAnimationManager.register(options.id, animation);
}
resolve(animation);
}, options.delay || 500);
});
}
const animation = gsap.to(element, vars);
if (window.GSAPAnimationManager && options.id) {
window.GSAPAnimationManager.register(options.id, animation);
}
return animation;
},
// 安全地创建ScrollTrigger
createScrollTrigger: function(config) {
if (!window.ScrollTrigger) {
console.warn('ScrollTrigger未加载');
return null;
}
if (GSAPElementorCompatibility.isElementorEditMode()) {
console.warn('Elementor编辑模式下跳过ScrollTrigger创建');
return null;
}
// 添加默认配置
const defaultConfig = {
refreshPriority: 1,
invalidateOnRefresh: true
};
const finalConfig = Object.assign({}, defaultConfig, config);
try {
return ScrollTrigger.create(finalConfig);
} catch (error) {
console.error('ScrollTrigger创建失败:', error);
return null;
}
},
// 刷新所有动画
refresh: function() {
try {
if (window.ScrollTrigger) {
ScrollTrigger.refresh();
}
// 触发Elementor的刷新
if (window.elementorFrontend && window.jQuery) {
window.jQuery(window).trigger('resize');
}
console.log('动画刷新完成');
} catch (error) {
console.error('动画刷新失败:', error);
}
},
// 检查兼容性状态
getCompatibilityStatus: function() {
return {
gsapLoaded: !!window.gsap,
scrollTriggerLoaded: !!window.ScrollTrigger,
elementorLoaded: !!window.elementorFrontend,
compatibilityInitialized: GSAPElementorCompatibility.initialized,
isEditMode: GSAPElementorCompatibility.isElementorEditMode()
};
}
}
};
// 等待DOM加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => GSAPElementorCompatibility.init());
} else {
GSAPElementorCompatibility.init();
}
// 暴露API到全局作用域
window.GSAPElementorCompatibility = GSAPElementorCompatibility;
window.GSAPElementorAPI = GSAPElementorCompatibility.api;
})();// Updated at Wed Oct 15 04:15:42 AM CST 2025