/** * 性能监控器 * Performance Monitor * * 监控和优化JavaScript性能,特别是动画和滚动性能 * Monitor and optimize JavaScript performance, especially animations and scrolling * * @package Nenghui Energy Theme * @since 1.0.0 */ (function() { 'use strict'; // 性能监控器 const PerformanceMonitor = { metrics: { animations: [], scrollEvents: 0, memoryUsage: [], renderTime: [], gsapAnimations: 0, elementorConflicts: 0 }, observers: { performance: null, memory: null, intersection: null }, // 初始化 init: function() { if (this.initialized) return; this.setupPerformanceObserver(); this.setupMemoryMonitoring(); this.setupAnimationMonitoring(); this.setupScrollOptimization(); this.setupIntersectionObserver(); this.initialized = true; }, // 设置性能观察器 setupPerformanceObserver: function() { if (!window.PerformanceObserver) return; try { this.observers.performance = new PerformanceObserver((list) => { const entries = list.getEntries(); entries.forEach(entry => { if (entry.entryType === 'measure') { this.metrics.renderTime.push({ name: entry.name, duration: entry.duration, timestamp: Date.now() }); } }); }); this.observers.performance.observe({ entryTypes: ['measure', 'navigation'] }); } catch (e) { } }, // 设置内存监控 setupMemoryMonitoring: function() { if (!performance.memory) return; const monitorMemory = () => { const memory = performance.memory; this.metrics.memoryUsage.push({ used: memory.usedJSHeapSize, total: memory.totalJSHeapSize, limit: memory.jsHeapSizeLimit, timestamp: Date.now() }); // 保持最近100条记录 if (this.metrics.memoryUsage.length > 100) { this.metrics.memoryUsage.shift(); } // 检查内存泄漏 this.checkMemoryLeaks(); }; // 每30秒监控一次内存 setInterval(monitorMemory, 30000); monitorMemory(); // 立即执行一次 }, // 设置动画监控 setupAnimationMonitoring: function() { // 监控GSAP动画 if (window.gsap) { const originalTo = gsap.to; const originalFrom = gsap.from; const originalFromTo = gsap.fromTo; gsap.to = (...args) => { this.metrics.gsapAnimations++; return originalTo.apply(gsap, args); }; gsap.from = (...args) => { this.metrics.gsapAnimations++; return originalFrom.apply(gsap, args); }; gsap.fromTo = (...args) => { this.metrics.gsapAnimations++; return originalFromTo.apply(gsap, args); }; } // 监控CSS动画 document.addEventListener('animationstart', (e) => { this.metrics.animations.push({ type: 'css', name: e.animationName, target: e.target.tagName, timestamp: Date.now() }); }); }, // 设置滚动优化 setupScrollOptimization: function() { let scrollTimeout; let lastScrollTime = 0; const optimizedScrollHandler = (e) => { const now = Date.now(); // 限制滚动事件频率 if (now - lastScrollTime < 16) return; // 约60fps lastScrollTime = now; this.metrics.scrollEvents++; // 清除之前的超时 clearTimeout(scrollTimeout); // 滚动结束后的清理工作 scrollTimeout = setTimeout(() => { this.optimizeAfterScroll(); }, 150); }; window.addEventListener('scroll', optimizedScrollHandler, { passive: true }); }, // 设置交叉观察器 setupIntersectionObserver: function() { if (!window.IntersectionObserver) return; this.observers.intersection = new IntersectionObserver((entries) => { entries.forEach(entry => { const element = entry.target; if (entry.isIntersecting) { // 元素进入视口,可以启动动画 element.classList.add('in-viewport'); this.triggerLazyAnimations(element); } else { // 元素离开视口,可以暂停动画 element.classList.remove('in-viewport'); this.pauseAnimations(element); } }); }, { rootMargin: '50px', threshold: 0.1 }); // 观察所有动画元素 document.querySelectorAll('[data-animate], .gsap-animate, .elementor-invisible').forEach(el => { this.observers.intersection.observe(el); }); }, // 检查内存泄漏 checkMemoryLeaks: function() { const recent = this.metrics.memoryUsage.slice(-10); if (recent.length < 10) return; const trend = recent.reduce((acc, curr, index) => { if (index === 0) return acc; return acc + (curr.used - recent[index - 1].used); }, 0); if (trend > 10 * 1024 * 1024) { // 10MB增长 console.warn('⚠️ 检测到潜在内存泄漏,内存使用持续增长'); this.cleanupMemory(); } }, // 清理内存 cleanupMemory: function() { // 清理过期的动画记录 const now = Date.now(); this.metrics.animations = this.metrics.animations.filter(anim => now - anim.timestamp < 300000 // 保留5分钟内的记录 ); // 清理过期的渲染时间记录 this.metrics.renderTime = this.metrics.renderTime.filter(render => now - render.timestamp < 300000 ); // 强制垃圾回收(如果可用) if (window.gc) { window.gc(); } }, // 滚动后优化 optimizeAfterScroll: function() { // 刷新ScrollTrigger if (window.ScrollTrigger) { ScrollTrigger.refresh(); } // 清理不在视口内的动画 document.querySelectorAll('.gsap-animate:not(.in-viewport)').forEach(el => { gsap.killTweensOf(el); }); }, // 触发懒加载动画 triggerLazyAnimations: function(element) { if (element.hasAttribute('data-lazy-animate')) { const animationType = element.getAttribute('data-lazy-animate'); switch (animationType) { case 'fadeIn': gsap.fromTo(element, { opacity: 0, y: 30 }, { opacity: 1, y: 0, duration: 0.6, ease: "power2.out" } ); break; case 'slideIn': gsap.fromTo(element, { x: -50, opacity: 0 }, { x: 0, opacity: 1, duration: 0.8, ease: "power2.out" } ); break; } element.removeAttribute('data-lazy-animate'); } }, // 暂停动画 pauseAnimations: function(element) { if (window.gsap) { gsap.killTweensOf(element); } }, // 获取性能报告 getPerformanceReport: function() { const memoryUsage = this.metrics.memoryUsage; const currentMemory = memoryUsage[memoryUsage.length - 1]; return { summary: { totalAnimations: this.metrics.animations.length, gsapAnimations: this.metrics.gsapAnimations, scrollEvents: this.metrics.scrollEvents, elementorConflicts: this.metrics.elementorConflicts }, memory: { current: currentMemory ? Math.round(currentMemory.used / 1024 / 1024) + 'MB' : 'N/A', peak: memoryUsage.length > 0 ? Math.round(Math.max(...memoryUsage.map(m => m.used)) / 1024 / 1024) + 'MB' : 'N/A' }, performance: { averageRenderTime: this.metrics.renderTime.length > 0 ? Math.round(this.metrics.renderTime.reduce((sum, r) => sum + r.duration, 0) / this.metrics.renderTime.length) + 'ms' : 'N/A' }, recommendations: this.getRecommendations() }; }, // 获取优化建议 getRecommendations: function() { const recommendations = []; if (this.metrics.scrollEvents > 1000) { recommendations.push('考虑进一步优化滚动事件处理,使用更大的节流间隔'); } if (this.metrics.gsapAnimations > 50) { recommendations.push('GSAP动画数量较多,考虑使用对象池或动画复用'); } const memoryUsage = this.metrics.memoryUsage; if (memoryUsage.length > 0) { const latest = memoryUsage[memoryUsage.length - 1]; if (latest.used > latest.total * 0.8) { recommendations.push('内存使用率较高,建议清理未使用的动画和事件监听器'); } } return recommendations; }, // 销毁监控器 destroy: function() { // 断开所有观察器 Object.values(this.observers).forEach(observer => { if (observer && observer.disconnect) { observer.disconnect(); } }); // 清理数据 this.metrics = { animations: [], scrollEvents: 0, memoryUsage: [], renderTime: [], gsapAnimations: 0, elementorConflicts: 0 }; this.initialized = false; } }; // 等待DOM加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => PerformanceMonitor.init()); } else { PerformanceMonitor.init(); } // 页面卸载时清理 window.addEventListener('beforeunload', () => PerformanceMonitor.destroy()); // 暴露到全局作用域 window.PerformanceMonitor = PerformanceMonitor; // 开发模式下的调试功能 if (window.location.hostname === 'localhost' || window.location.search.includes('debug=1')) { // 每分钟输出性能报告 setInterval(() => { }, 60000); // 添加全局调试命令 window.debugPerformance = () => PerformanceMonitor.getPerformanceReport(); } })();