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.

323 lines
11 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.

/**
* Smooth Scroll Initialization
* 平滑滚动初始化脚本
* 优化版本增强与Elementor和其他滚动库的兼容性
*
* @package Nenghui Energy Theme
* @since 1.0.0
*/
// Elementor兼容性检查
function isElementorEditMode() {
return window.elementorFrontend && window.elementorFrontend.isEditMode();
}
// 检查是否有冲突的滚动库
function hasScrollConflicts() {
const conflicts = [];
// 检查常见的滚动库
if (window.AOS) conflicts.push('AOS');
if (window.ScrollMagic) conflicts.push('ScrollMagic');
if (window.gsap && window.ScrollTrigger) conflicts.push('GSAP ScrollTrigger');
if (conflicts.length > 0) {
}
return conflicts.length > 0;
}
// 动态配置选项
function getSmoothScrollConfig() {
const baseConfig = {
// 滚动速度 (毫秒)
animationTime: 800,
// 步长大小
stepSize: 100,
// 加速度倍数
accelerationDelta: 50,
// 最大加速度
accelerationMax: 3,
// 键盘支持
keyboardSupport: true,
// 箭头滚动步长
arrowScroll: 50,
// 脉冲算法设置
pulseAlgorithm: true,
// 脉冲比例
pulseScale: 4,
// 脉冲标准化
pulseNormalize: 1,
// 固定背景支持
fixedBackground: true,
// 排除的元素选择器
excluded: 'textarea, input[type="text"], input[type="password"], input[type="email"], input[type="number"], input[type="search"], input[type="tel"], input[type="url"], select'
};
// Elementor编辑模式下的特殊配置
if (isElementorEditMode()) {
return {
...baseConfig,
animationTime: 600, // 增加动画时间,使滚动更平滑
keyboardSupport: false, // 在编辑模式下禁用键盘支持
excluded: baseConfig.excluded + ', .elementor-editor-active, .elementor-widget-container'
};
}
// 检测到滚动冲突时的配置
if (hasScrollConflicts()) {
return {
...baseConfig,
animationTime: 600, // 减少动画时间
accelerationMax: 2, // 降低加速度
excluded: baseConfig.excluded + ', .gsap-scroll-trigger, .aos-animate, .scroll-magic-element'
};
}
return baseConfig;
}
// 在库加载前设置全局配置选项
if (typeof window.SmoothScrollOptions === 'undefined') {
window.SmoothScrollOptions = getSmoothScrollConfig();
}
(function() {
'use strict';
// 防抖函数
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// 节流函数
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// 平滑滚动管理器
const SmoothScrollManager = {
initialized: false,
backToTopBtn: null,
scrollThreshold: 300,
// 初始化
init: function() {
if (this.initialized) return;
// 在Elementor编辑模式下延迟初始化
if (isElementorEditMode()) {
setTimeout(() => this.initScrollFeatures(), 1000);
} else {
this.initScrollFeatures();
}
this.initialized = true;
},
// 初始化滚动功能
initScrollFeatures: function() {
console.log('✅ Smooth Scroll options configured successfully');
this.setupAnchorLinks();
this.setupBackToTop();
this.bindEvents();
},
// 设置锚点链接
setupAnchorLinks: function() {
const anchorLinks = document.querySelectorAll('a[href^="#"]');
anchorLinks.forEach(link => {
// 避免重复绑定事件
if (link.hasAttribute('data-smooth-scroll-bound')) return;
link.addEventListener('click', this.handleAnchorClick.bind(this));
link.setAttribute('data-smooth-scroll-bound', 'true');
});
},
// 处理锚点点击
handleAnchorClick: function(e) {
const targetId = e.currentTarget.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
e.preventDefault();
// 检查是否在Elementor编辑模式下
if (isElementorEditMode()) {
// 在编辑模式下使用简单的滚动
targetElement.scrollIntoView({ behavior: 'auto' });
return;
}
// 检查GSAP ScrollTrigger是否存在并刷新
if (window.ScrollTrigger) {
window.ScrollTrigger.refresh();
}
// 平滑滚动到目标元素
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'nearest'
});
}
},
// 设置回到顶部按钮
setupBackToTop: function() {
this.backToTopBtn = document.querySelector('.back-to-top');
if (this.backToTopBtn) {
// 避免重复绑定事件
if (!this.backToTopBtn.hasAttribute('data-smooth-scroll-bound')) {
this.backToTopBtn.addEventListener('click', this.handleBackToTop.bind(this));
this.backToTopBtn.setAttribute('data-smooth-scroll-bound', 'true');
}
}
},
// 处理回到顶部
handleBackToTop: function(e) {
e.preventDefault();
// 在Elementor编辑模式下使用简单滚动
if (isElementorEditMode()) {
window.scrollTo({ top: 0, behavior: 'auto' });
return;
}
this.smoothScrollToTop();
},
// 自定义平滑滚动到顶部函数
smoothScrollToTop: function() {
const startPosition = window.pageYOffset;
const startTime = performance.now();
const duration = 800;
const animation = (currentTime) => {
const timeElapsed = currentTime - startTime;
const run = this.easeInOutQuad(timeElapsed, startPosition, -startPosition, duration);
window.scrollTo(0, run);
if (timeElapsed < duration) {
requestAnimationFrame(animation);
} else {
// 动画完成后刷新ScrollTrigger
if (window.ScrollTrigger) {
window.ScrollTrigger.refresh();
}
}
};
requestAnimationFrame(animation);
},
// 缓动函数easeInOutQuad
easeInOutQuad: function(t, b, c, d) {
t /= d / 2;
if (t < 1) return c / 2 * t * t + b;
t--;
return -c / 2 * (t * (t - 2) - 1) + b;
},
// 绑定事件
bindEvents: function() {
// 使用节流的滚动事件处理器
const throttledScrollHandler = throttle(this.handleScroll.bind(this), 16); // 约60fps
window.addEventListener('scroll', throttledScrollHandler, { passive: true });
// 监听窗口大小变化
const debouncedResizeHandler = debounce(this.handleResize.bind(this), 250);
window.addEventListener('resize', debouncedResizeHandler);
// 监听Elementor前端加载完成
if (window.elementorFrontend && window.elementorFrontend.hooks && typeof window.elementorFrontend.hooks.addAction === 'function') {
try {
window.elementorFrontend.hooks.addAction('frontend/element_ready/global', () => {
this.setupAnchorLinks(); // 重新设置锚点链接
});
} catch (error) {
console.warn('SmoothScroll: 无法绑定Elementor钩子:', error);
}
}
},
// 处理滚动事件
handleScroll: function() {
if (this.backToTopBtn) {
const shouldShow = window.pageYOffset > this.scrollThreshold;
this.backToTopBtn.classList.toggle('visible', shouldShow);
}
},
// 处理窗口大小变化
handleResize: function() {
// 刷新ScrollTrigger实例
if (window.ScrollTrigger) {
window.ScrollTrigger.refresh();
}
},
// 销毁方法
destroy: function() {
// 移除所有事件监听器
const anchorLinks = document.querySelectorAll('a[href^="#"][data-smooth-scroll-bound]');
anchorLinks.forEach(link => {
link.removeEventListener('click', this.handleAnchorClick);
link.removeAttribute('data-smooth-scroll-bound');
});
if (this.backToTopBtn && this.backToTopBtn.hasAttribute('data-smooth-scroll-bound')) {
this.backToTopBtn.removeEventListener('click', this.handleBackToTop);
this.backToTopBtn.removeAttribute('data-smooth-scroll-bound');
}
this.initialized = false;
}
};
// 等待DOM加载完成
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => SmoothScrollManager.init());
} else {
SmoothScrollManager.init();
}
// 页面卸载时清理
window.addEventListener('beforeunload', () => SmoothScrollManager.destroy());
// 暴露到全局作用域以便调试
window.SmoothScrollManager = SmoothScrollManager;
})();