timoxiliu/word-cloud
0
1// 工具函数:防抖函数2function debounce(func, wait) {3 let timeout;4 return function executedFunction(...args) {5 const later = () => {6 clearTimeout(timeout);7 func(...args);8 };9 clearTimeout(timeout);10 timeout = setTimeout(later, wait);11 };12}13 14// AI技术关键词数据15const techTerms = {16 "生成式AI": { value: 20, category: "核心技术" },17 "大语言模型": { value: 18, category: "核心技术" },18 "Gemini": { value: 17, category: "模型产品" },19 "GPT-5": { value: 16, category: "模型产品" },20 "DeepSeek": { value: 15, category: "模型产品" },21 "多模态": { value: 15, category: "核心技术" },22 "Agent": { value: 14, category: "应用技术" },23 "混合推理": { value: 14, category: "算法技术" },24 "512K上下文": { value: 13, category: "技术指标" },25 "视频生成": { value: 13, category: "应用技术" },26 "3D建模": { value: 12, category: "应用技术" },27 "智能体": { value: 12, category: "应用技术" },28 "开源": { value: 11, category: "生态发展" },29 "端侧AI": { value: 11, category: "部署方式" },30 "实时翻译": { value: 10, category: "应用技术" },31 "无代码": { value: 10, category: "开发工具" },32 "私有化部署": { value: 9, category: "部署方式" },33 "算力优化": { value: 9, category: "技术优化" },34 "语音助手": { value: 9, category: "应用产品" },35 "决策智能": { value: 8, category: "算法技术" },36 "Transformer": { value: 8, category: "算法架构" },37 "神经网络": { value: 7, category: "算法架构" },38 "机器学习": { value: 7, category: "基础技术" },39 "深度学习": { value: 7, category: "基础技术" },40 "计算机视觉": { value: 6, category: "基础技术" },41 "知识图谱": { value: 6, category: "数据技术" },42 "模式识别": { value: 5, category: "基础技术" },43 "API": { value: 5, category: "开发工具" },44 "边缘计算": { value: 8, category: "部署方式" },45 "联邦学习": { value: 7, category: "算法技术" },46 "强化学习": { value: 6, category: "算法技术" },47 "自监督学习": { value: 6, category: "算法技术" },48 "量子计算": { value: 5, category: "前沿技术" },49 "脑机接口": { value: 4, category: "前沿技术" }50};51 52// 颜色配置53const colors = [54 '#3b82f6', '#8b5cf6', '#ec4899', '#06b6d4', '#10b981', 55 '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4', '#10b981',56 '#f59e0b', '#ef4444', '#6366f1', '#14b8a6', '#f97316'57];58 59// 应用场景数据60const applicationData = [61 { name: '教育科研', value: 25, color: '#3b82f6' },62 { name: '医疗健康', value: 22, color: '#10b981' },63 { name: '智能制造', value: 18, color: '#f59e0b' },64 { name: '金融服务', value: 15, color: '#eab308' },65 { name: '自动驾驶', value: 12, color: '#8b5cf6' },66 { name: '内容创作', value: 8, color: '#ec4899' }67];68 69// 技术成熟度数据70const maturityData = [71 { name: '机器学习', value: 95 },72 { name: '深度学习', value: 90 },73 { name: '计算机视觉', value: 88 },74 { name: '自然语言处理', value: 85 },75 { name: '语音识别', value: 82 },76 { name: '强化学习', value: 75 },77 { name: '生成式AI', value: 70 },78 { name: '多模态AI', value: 65 },79 { name: '量子AI', value: 35 },80 { name: '脑机接口', value: 25 }81];82 83// 趋势发展数据84const trendData = {85 categories: ['2020', '2021', '2022', '2023', '2024', '2025', '2026'],86 series: [87 {88 name: '大语言模型',89 data: [10, 25, 45, 70, 85, 95, 98],90 color: '#3b82f6'91 },92 {93 name: '多模态AI',94 data: [5, 15, 30, 50, 70, 85, 92],95 color: '#8b5cf6'96 },97 {98 name: 'Agent应用',99 data: [2, 8, 20, 40, 65, 80, 90],100 color: '#ec4899'101 },102 {103 name: '端侧AI',104 data: [8, 18, 35, 55, 75, 88, 95],105 color: '#10b981'106 },107 {108 name: '量子AI',109 data: [1, 3, 8, 15, 25, 40, 60],110 color: '#f59e0b'111 }112 ]113};114 115// 全局变量116let wordCloudChart = null;117let applicationChart = null;118let maturityChart = null;119let trendChart = null;120 121// 页面加载完成后初始化122document.addEventListener('DOMContentLoaded', function() {123 // 记录初始屏幕宽度124 window.lastWidth = window.innerWidth;125 126 initializeCharts();127 initializeInteractions();128 initializeAnimations();129});130 131// 初始化图表132function initializeCharts() {133 initWordCloud();134 initApplicationChart();135 initMaturityChart();136 initTrendChart();137}138 139// 初始化词云图140function initWordCloud() {141 try {142 // 检查必要的依赖是否已加载143 if (typeof echarts === 'undefined') {144 throw new Error('ECharts 库未加载');145 }146 147 // 检查词云插件是否已加载148 if (!echarts.registerMap && !echarts.getMap) {149 console.warn('词云插件可能未完全加载,尝试继续初始化...');150 }151 152 const chartDom = document.getElementById('wordCloudChart');153 if (!chartDom) {154 throw new Error('词云图容器元素未找到');155 }156 157 // 确保容器有足够的尺寸158 if (chartDom.offsetWidth === 0 || chartDom.offsetHeight === 0) {159 console.warn('词云图容器尺寸为0,等待DOM完全渲染...');160 setTimeout(() => initWordCloud(), 100);161 return;162 }163 164 wordCloudChart = echarts.init(chartDom);165 166 // 获取设备类型和屏幕尺寸(先定义,后使用)167 const screenWidth = window.innerWidth;168 const isMobile = screenWidth < 640;169 const isTablet = screenWidth >= 640 && screenWidth < 1024;170 const isDesktop = screenWidth >= 1024;171 172 // 转换数据格式,根据屏幕大小过滤数据173 let filteredTerms = Object.entries(techTerms);174 175 // 根据屏幕大小过滤数据量176 if (isMobile) {177 // 移动端只显示热度最高的20个词汇178 filteredTerms = filteredTerms179 .sort(([,a], [,b]) => b.value - a.value)180 .slice(0, 20);181 } else if (isTablet) {182 // 平板显示热度最高的25个词汇183 filteredTerms = filteredTerms184 .sort(([,a], [,b]) => b.value - a.value)185 .slice(0, 25);186 }187 188 const wordCloudData = filteredTerms.map(([name, data]) => ({189 name: name,190 value: data.value,191 textStyle: {192 color: colors[Math.floor(Math.random() * colors.length)]193 }194 }));195 196 // 根据设备类型调整参数197 let gridSize, sizeRange, rotationRange, rotationStep;198 199 if (isMobile) {200 gridSize = 3;201 sizeRange = [6, 28];202 rotationRange = [-30, 30];203 rotationStep = 30;204 } else if (isTablet) {205 gridSize = 5;206 sizeRange = [8, 40];207 rotationRange = [-45, 45];208 rotationStep = 15;209 } else {210 gridSize = 8;211 sizeRange = [12, 60];212 rotationRange = [-60, 60];213 rotationStep = 15;214 }215 216 // 尝试使用词云图,如果失败则使用备用方案217 let option;218 219 try {220 option = {221 backgroundColor: 'transparent',222 tooltip: {223 show: true,224 backgroundColor: 'rgba(15, 23, 42, 0.9)',225 borderColor: 'rgba(59, 130, 246, 0.3)',226 textStyle: {227 color: '#ffffff',228 fontSize: isMobile ? 12 : 14229 },230 padding: isMobile ? [6, 8] : [10, 12],231 formatter: function(params) {232 const category = techTerms[params.name]?.category || '未分类';233 const fontSize = isMobile ? '12px' : '14px';234 return `<div style="padding: ${isMobile ? '4px' : '8px'};">235 <div style="font-weight: bold; color: #3b82f6; font-size: ${fontSize};">${params.name}</div>236 <div style="margin-top: 4px; color: #94a3b8; font-size: ${isMobile ? '11px' : '13px'};">分类: ${category}</div>237 <div style="color: #94a3b8; font-size: ${isMobile ? '11px' : '13px'};">热度: ${params.value}</div>238 </div>`;239 }240 },241 series: [{242 type: 'wordCloud',243 gridSize: gridSize,244 sizeRange: sizeRange,245 rotationRange: rotationRange,246 rotationStep: rotationStep,247 shape: 'circle',248 width: '100%',249 height: '100%',250 drawOutOfBound: false,251 layoutAnimation: true,252 textStyle: {253 fontFamily: 'Inter, sans-serif',254 fontWeight: isMobile ? 'normal' : 'bold'255 },256 emphasis: {257 focus: 'self',258 textStyle: {259 shadowBlur: isMobile ? 5 : 10,260 shadowColor: '#3b82f6'261 }262 },263 data: wordCloudData264 }]265 };266 267 wordCloudChart.setOption(option);268 269 } catch (wordCloudError) {270 console.warn('词云图插件不可用,使用备用散点图方案:', wordCloudError);271 272 // 备用方案:使用散点图模拟词云效果273 option = {274 backgroundColor: 'transparent',275 tooltip: {276 show: true,277 backgroundColor: 'rgba(15, 23, 42, 0.9)',278 borderColor: 'rgba(59, 130, 246, 0.3)',279 textStyle: {280 color: '#ffffff',281 fontSize: isMobile ? 12 : 14282 },283 formatter: function(params) {284 const category = techTerms[params.data.name]?.category || '未分类';285 return `<div style="padding: 8px;">286 <div style="font-weight: bold; color: #3b82f6;">${params.data.name}</div>287 <div style="margin-top: 4px; color: #94a3b8;">分类: ${category}</div>288 <div style="color: #94a3b8;">热度: ${params.data.value}</div>289 </div>`;290 }291 },292 xAxis: { show: false, min: 0, max: 100 },293 yAxis: { show: false, min: 0, max: 100 },294 series: [{295 type: 'scatter',296 symbolSize: function(data) {297 return Math.max(isMobile ? 20 : 30, data.value * (isMobile ? 2 : 3));298 },299 label: {300 show: true,301 formatter: '{@name}',302 fontSize: function(params) {303 return Math.max(isMobile ? 10 : 12, params.data.value * 0.8);304 },305 color: function(params) {306 return colors[params.dataIndex % colors.length];307 },308 fontWeight: 'bold'309 },310 itemStyle: {311 opacity: 0.1312 },313 data: wordCloudData.map((item, index) => ({314 name: item.name,315 value: [316 Math.random() * 80 + 10,317 Math.random() * 80 + 10,318 item.value319 ]320 }))321 }]322 };323 324 wordCloudChart.setOption(option);325 }326 327 // 添加触摸设备优化328 if ('ontouchstart' in window) {329 // 触摸设备特殊处理330 wordCloudChart.on('click', function(params) {331 if (params.componentType === 'series') {332 // 触摸设备点击反馈333 const element = document.getElementById('wordCloudChart');334 element.style.transform = 'scale(0.98)';335 setTimeout(() => {336 element.style.transform = 'scale(1)';337 }, 150);338 }339 });340 }341 342 // 响应式处理将在全局处理函数中统一处理343 344 } catch (error) {345 console.error('词云图初始化失败:', error);346 // 显示错误信息并提供重试功能347 const chartDom = document.getElementById('wordCloudChart');348 if (chartDom) {349 chartDom.innerHTML = `350 <div class="flex items-center justify-center h-full text-gray-400">351 <div class="text-center">352 <i class="fas fa-sync-alt text-4xl mb-4 text-blue-400"></i>353 <div class="text-lg font-medium mb-2">词云图正在加载中...</div>354 <div class="text-sm mb-4">如果长时间未显示,请点击重试</div>355 <button onclick="retryWordCloud()" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors duration-200">356 <i class="fas fa-redo mr-2"></i>重新加载357 </button>358 </div>359 </div>360 `;361 }362 363 // 3秒后自动重试一次364 setTimeout(() => {365 if (chartDom && chartDom.innerHTML.includes('词云图正在加载中')) {366 retryWordCloud();367 }368 }, 3000);369 }370}371 372// 初始化应用分布图373function initApplicationChart() {374 try {375 const chartDom = document.getElementById('applicationChart');376 if (!chartDom) return;377 378 applicationChart = echarts.init(chartDom);379 380 const option = {381 backgroundColor: 'transparent',382 tooltip: {383 trigger: 'item',384 backgroundColor: 'rgba(15, 23, 42, 0.9)',385 borderColor: 'rgba(59, 130, 246, 0.3)',386 textStyle: {387 color: '#ffffff'388 },389 formatter: '{b}: {c}% ({d}%)'390 },391 legend: {392 orient: window.innerWidth < 768 ? 'horizontal' : 'vertical',393 left: window.innerWidth < 768 ? 'center' : 'left',394 top: window.innerWidth < 768 ? 'top' : 'center',395 bottom: window.innerWidth < 768 ? 'auto' : 'auto',396 textStyle: {397 color: '#94a3b8',398 fontSize: window.innerWidth < 768 ? 10 : 12399 }400 },401 series: [402 {403 type: 'pie',404 radius: window.innerWidth < 768 ? ['30%', '60%'] : ['40%', '70%'],405 center: window.innerWidth < 768 ? ['50%', '60%'] : ['60%', '50%'],406 avoidLabelOverlap: false,407 itemStyle: {408 borderRadius: 8,409 borderColor: 'rgba(15, 23, 42, 0.8)',410 borderWidth: 2411 },412 label: {413 show: false,414 position: 'center'415 },416 emphasis: {417 label: {418 show: true,419 fontSize: 16,420 fontWeight: 'bold',421 color: '#ffffff'422 },423 itemStyle: {424 shadowBlur: 10,425 shadowOffsetX: 0,426 shadowColor: 'rgba(59, 130, 246, 0.5)'427 }428 },429 labelLine: {430 show: false431 },432 data: applicationData433 }434 ]435 };436 437 applicationChart.setOption(option);438 439 // 添加触摸设备优化440 if ('ontouchstart' in window) {441 // 触摸设备特殊处理442 wordCloudChart.on('click', function(params) {443 if (params.componentType === 'series') {444 // 触摸设备点击反馈445 const element = document.getElementById('wordCloudChart');446 element.style.transform = 'scale(0.98)';447 setTimeout(() => {448 element.style.transform = 'scale(1)';449 }, 150);450 }451 });452 }453 454 // 响应式处理将在全局处理函数中统一处理455 456 } catch (error) {457 console.error('应用分布图初始化失败:', error);458 }459}460 461// 初始化成熟度图表462function initMaturityChart() {463 try {464 const chartDom = document.getElementById('maturityChart');465 if (!chartDom) return;466 467 maturityChart = echarts.init(chartDom);468 469 const option = {470 backgroundColor: 'transparent',471 tooltip: {472 trigger: 'axis',473 backgroundColor: 'rgba(15, 23, 42, 0.9)',474 borderColor: 'rgba(59, 130, 246, 0.3)',475 textStyle: {476 color: '#ffffff'477 },478 axisPointer: {479 type: 'shadow'480 }481 },482 grid: {483 left: '3%',484 right: '4%',485 bottom: '3%',486 containLabel: true487 },488 xAxis: {489 type: 'value',490 max: 100,491 axisLine: {492 lineStyle: {493 color: '#374151'494 }495 },496 axisLabel: {497 color: '#94a3b8',498 formatter: '{value}%'499 },500 splitLine: {501 lineStyle: {502 color: '#374151'503 }504 }505 },506 yAxis: {507 type: 'category',508 data: maturityData.map(item => item.name),509 axisLine: {510 lineStyle: {511 color: '#374151'512 }513 },514 axisLabel: {515 color: '#94a3b8'516 }517 },518 series: [519 {520 type: 'bar',521 data: maturityData.map((item, index) => ({522 value: item.value,523 itemStyle: {524 color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [525 { offset: 0, color: colors[index % colors.length] + '40' },526 { offset: 1, color: colors[index % colors.length] }527 ]),528 borderRadius: [0, 4, 4, 0]529 }530 })),531 barWidth: '60%',532 label: {533 show: true,534 position: 'right',535 color: '#ffffff',536 formatter: '{c}%'537 }538 }539 ]540 };541 542 maturityChart.setOption(option);543 544 window.addEventListener('resize', function() {545 if (maturityChart) {546 maturityChart.resize();547 }548 });549 550 } catch (error) {551 console.error('成熟度图表初始化失败:', error);552 }553}554 555// 初始化趋势图表556function initTrendChart() {557 try {558 const chartDom = document.getElementById('trendChart');559 if (!chartDom) return;560 561 trendChart = echarts.init(chartDom);562 563 const option = {564 backgroundColor: 'transparent',565 tooltip: {566 trigger: 'axis',567 backgroundColor: 'rgba(15, 23, 42, 0.9)',568 borderColor: 'rgba(59, 130, 246, 0.3)',569 textStyle: {570 color: '#ffffff'571 }572 },573 legend: {574 data: trendData.series.map(s => s.name),575 textStyle: {576 color: '#94a3b8'577 },578 top: 20579 },580 grid: {581 left: '3%',582 right: '4%',583 bottom: '3%',584 top: '15%',585 containLabel: true586 },587 xAxis: {588 type: 'category',589 boundaryGap: false,590 data: trendData.categories,591 axisLine: {592 lineStyle: {593 color: '#374151'594 }595 },596 axisLabel: {597 color: '#94a3b8'598 }599 },600 yAxis: {601 type: 'value',602 max: 100,603 axisLine: {604 lineStyle: {605 color: '#374151'606 }607 },608 axisLabel: {609 color: '#94a3b8',610 formatter: '{value}%'611 },612 splitLine: {613 lineStyle: {614 color: '#374151'615 }616 }617 },618 series: trendData.series.map(s => ({619 name: s.name,620 type: 'line',621 smooth: true,622 data: s.data,623 lineStyle: {624 color: s.color,625 width: 3626 },627 itemStyle: {628 color: s.color,629 borderWidth: 2,630 borderColor: '#ffffff'631 },632 areaStyle: {633 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [634 { offset: 0, color: s.color + '40' },635 { offset: 1, color: s.color + '10' }636 ])637 },638 emphasis: {639 focus: 'series'640 }641 }))642 };643 644 trendChart.setOption(option);645 646 window.addEventListener('resize', function() {647 if (trendChart) {648 trendChart.resize();649 }650 });651 652 } catch (error) {653 console.error('趋势图表初始化失败:', error);654 }655}656 657// 初始化交互功能658function initializeInteractions() {659 // 词云刷新功能660 const refreshBtn = document.getElementById('refreshWordCloud');661 if (refreshBtn) {662 refreshBtn.addEventListener('click', function() {663 if (wordCloudChart) {664 // 重新生成颜色665 const wordCloudData = Object.entries(techTerms).map(([name, data]) => ({666 name: name,667 value: data.value,668 textStyle: {669 color: colors[Math.floor(Math.random() * colors.length)]670 }671 }));672 673 wordCloudChart.setOption({674 series: [{675 data: wordCloudData676 }]677 });678 679 // 按钮动画680 refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>刷新中...';681 setTimeout(() => {682 refreshBtn.innerHTML = '<i class="fas fa-sync-alt mr-2"></i>刷新';683 }, 1000);684 }685 });686 }687 688 // 词云下载功能689 const downloadBtn = document.getElementById('downloadWordCloud');690 if (downloadBtn) {691 downloadBtn.addEventListener('click', function() {692 if (wordCloudChart) {693 const url = wordCloudChart.getDataURL({694 type: 'png',695 pixelRatio: 2,696 backgroundColor: '#0f172a'697 });698 699 const link = document.createElement('a');700 link.download = 'AI_2025_WordCloud.png';701 link.href = url;702 link.click();703 704 // 下载提示705 downloadBtn.innerHTML = '<i class="fas fa-check mr-2"></i>已下载';706 setTimeout(() => {707 downloadBtn.innerHTML = '<i class="fas fa-download mr-2"></i>下载';708 }, 2000);709 }710 });711 }712 713 // 导航平滑滚动714 const navLinks = document.querySelectorAll('.nav-link');715 navLinks.forEach(link => {716 link.addEventListener('click', function(e) {717 e.preventDefault();718 const targetId = this.getAttribute('href');719 const targetElement = document.querySelector(targetId);720 if (targetElement) {721 targetElement.scrollIntoView({722 behavior: 'smooth',723 block: 'start'724 });725 }726 });727 });728 729 // 返回顶部按钮730 const backToTopBtn = document.getElementById('backToTop');731 if (backToTopBtn) {732 backToTopBtn.addEventListener('click', function() {733 window.scrollTo({734 top: 0,735 behavior: 'smooth'736 });737 });738 }739}740 741// 初始化动画效果742function initializeAnimations() {743 // 滚动进度指示器744 const scrollProgress = document.getElementById('scrollProgress');745 const backToTopBtn = document.getElementById('backToTop');746 747 window.addEventListener('scroll', function() {748 const scrollTop = window.pageYOffset || document.documentElement.scrollTop;749 const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;750 const scrollPercent = (scrollTop / scrollHeight) * 100;751 752 if (scrollProgress) {753 scrollProgress.style.width = scrollPercent + '%';754 }755 756 // 返回顶部按钮显示/隐藏757 if (backToTopBtn) {758 if (scrollTop > 300) {759 backToTopBtn.classList.remove('opacity-0', 'invisible');760 backToTopBtn.classList.add('opacity-100', 'visible');761 } else {762 backToTopBtn.classList.add('opacity-0', 'invisible');763 backToTopBtn.classList.remove('opacity-100', 'visible');764 }765 }766 });767 768 // 卡片悬浮动画769 const techCards = document.querySelectorAll('.tech-card');770 techCards.forEach(card => {771 card.addEventListener('mouseenter', function() {772 this.style.transform = 'translateY(-5px) scale(1.02)';773 });774 775 card.addEventListener('mouseleave', function() {776 this.style.transform = 'translateY(0) scale(1)';777 });778 });779 780 // 应用展示卡片动画781 const applicationCards = document.querySelectorAll('.application-showcase');782 applicationCards.forEach(card => {783 card.addEventListener('mouseenter', function() {784 const img = this.querySelector('img');785 if (img) {786 img.style.transform = 'scale(1.05)';787 }788 });789 790 card.addEventListener('mouseleave', function() {791 const img = this.querySelector('img');792 if (img) {793 img.style.transform = 'scale(1)';794 }795 });796 });797 798 // 趋势卡片动画799 const trendCards = document.querySelectorAll('.trend-card');800 trendCards.forEach(card => {801 card.addEventListener('mouseenter', function() {802 this.style.transform = 'scale(1.02)';803 this.style.boxShadow = '0 10px 30px rgba(59, 130, 246, 0.2)';804 });805 806 card.addEventListener('mouseleave', function() {807 this.style.transform = 'scale(1)';808 this.style.boxShadow = 'none';809 });810 });811 812 // 创新指标动画813 const innovationMetrics = document.querySelectorAll('.innovation-metric');814 innovationMetrics.forEach(metric => {815 metric.addEventListener('mouseenter', function() {816 this.style.transform = 'translateY(-2px)';817 this.style.borderColor = 'rgba(59, 130, 246, 0.6)';818 });819 820 metric.addEventListener('mouseleave', function() {821 this.style.transform = 'translateY(0)';822 this.style.borderColor = 'rgba(59, 130, 246, 0.3)';823 });824 });825 826 // 页面加载动画827 const observer = new IntersectionObserver((entries) => {828 entries.forEach(entry => {829 if (entry.isIntersecting) {830 entry.target.style.opacity = '1';831 entry.target.style.transform = 'translateY(0)';832 }833 });834 }, {835 threshold: 0.1,836 rootMargin: '0px 0px -50px 0px'837 });838 839 // 观察所有需要动画的元素840 const animatedElements = document.querySelectorAll('.tech-card, .application-showcase, .trend-card, .innovation-metric');841 animatedElements.forEach(el => {842 el.style.opacity = '0';843 el.style.transform = 'translateY(20px)';844 el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';845 observer.observe(el);846 });847}848 849// 统一的响应式处理850function handleResize() {851 const currentWidth = window.innerWidth;852 853 // 重新初始化词云图表以适应新的屏幕尺寸854 if (wordCloudChart) {855 // 检查是否需要重新初始化(屏幕尺寸类别发生变化)856 const wasMobile = window.lastWidth < 640;857 const wasTablet = window.lastWidth >= 640 && window.lastWidth < 1024;858 const isMobile = currentWidth < 640;859 const isTablet = currentWidth >= 640 && currentWidth < 1024;860 861 // 如果设备类型发生变化,重新初始化862 if ((wasMobile !== isMobile) || (wasTablet !== isTablet)) {863 wordCloudChart.dispose();864 initWordCloud();865 } else {866 // 否则只调整大小867 wordCloudChart.resize();868 }869 }870 871 if (applicationChart) {872 applicationChart.dispose();873 initApplicationChart();874 }875 876 if (maturityChart) {877 maturityChart.resize();878 }879 880 if (trendChart) {881 trendChart.resize();882 }883 884 // 记录当前宽度885 window.lastWidth = currentWidth;886}887 888// 词云图重试函数889function retryWordCloud() {890 console.log('重试加载词云图...');891 const chartDom = document.getElementById('wordCloudChart');892 if (chartDom) {893 // 显示加载状态894 chartDom.innerHTML = `895 <div class="flex items-center justify-center h-full text-gray-400">896 <div class="text-center">897 <i class="fas fa-spinner fa-spin text-4xl mb-4 text-blue-400"></i>898 <div class="text-lg font-medium">正在重新加载词云图...</div>899 </div>900 </div>901 `;902 903 // 销毁现有图表实例904 if (wordCloudChart) {905 wordCloudChart.dispose();906 wordCloudChart = null;907 }908 909 // 延迟重新初始化,确保DOM更新完成910 setTimeout(() => {911 try {912 initWordCloud();913 } catch (error) {914 console.error('重试加载词云图失败:', error);915 chartDom.innerHTML = `916 <div class="flex items-center justify-center h-full text-gray-400">917 <div class="text-center">918 <i class="fas fa-exclamation-triangle text-4xl mb-4 text-red-400"></i>919 <div class="text-lg font-medium mb-2">词云图加载失败</div>920 <div class="text-sm mb-4">请检查网络连接或刷新页面</div>921 <button onclick="location.reload()" class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg transition-colors duration-200">922 <i class="fas fa-refresh mr-2"></i>刷新页面923 </button>924 </div>925 </div>926 `;927 }928 }, 500);929 }930}931 932// 添加响应式监听933window.addEventListener('resize', debounce(handleResize, 300));934 935// 工具函数:格式化数字936function formatNumber(num) {937 if (num >= 1000000) {938 return (num / 1000000).toFixed(1) + 'M';939 } else if (num >= 1000) {940 return (num / 1000).toFixed(1) + 'K';941 }942 return num.toString();943}944 945// 工具函数:生成随机颜色946function getRandomColor() {947 return colors[Math.floor(Math.random() * colors.length)];948}949 950// 这个handleResize已经在前面定义了,删除重复声明951 952// 错误处理953window.addEventListener('error', function(e) {954 console.error('页面错误:', e.error);955});956 957// 页面卸载时清理资源958window.addEventListener('beforeunload', function() {959 if (wordCloudChart) {960 wordCloudChart.dispose();961 wordCloudChart = null;962 }963 if (applicationChart) {964 applicationChart.dispose();965 applicationChart = null;966 }967 if (maturityChart) {968 maturityChart.dispose();969 maturityChart = null;970 }971 if (trendChart) {972 trendChart.dispose();973 trendChart = null;974 }975});976 977// 初始化导航功能978function initNavigation() {979 // 平滑滚动到指定区域980 function smoothScrollTo(targetId) {981 const target = document.getElementById(targetId);982 if (target) {983 const navHeight = 64; // 导航栏高度984 const targetPosition = target.offsetTop - navHeight;985 986 window.scrollTo({987 top: targetPosition,988 behavior: 'smooth'989 });990 }991 }992 993 // 绑定导航链接点击事件994 const navLinks = document.querySelectorAll('.nav-link');995 navLinks.forEach(link => {996 link.addEventListener('click', function(e) {997 e.preventDefault();998 const href = this.getAttribute('href');999 if (href && href.startsWith('#')) {1000 const targetId = href.substring(1);1001 smoothScrollTo(targetId);1002 }1003 });1004 });1005 1006 // 高亮当前区域的导航链接1007 function updateActiveNavLink() {1008 const sections = document.querySelectorAll('section[id]');1009 const navHeight = 64;1010 let currentSection = '';1011 1012 sections.forEach(section => {1013 const sectionTop = section.offsetTop - navHeight - 50;1014 const sectionBottom = sectionTop + section.offsetHeight;1015 1016 if (window.scrollY >= sectionTop && window.scrollY < sectionBottom) {1017 currentSection = section.id;1018 }1019 });1020 1021 navLinks.forEach(link => {1022 const href = link.getAttribute('href');1023 if (href && href.startsWith('#')) {1024 const targetId = href.substring(1);1025 if (targetId === currentSection) {1026 link.classList.add('text-blue-400');1027 link.classList.remove('text-gray-300');1028 } else {1029 link.classList.add('text-gray-300');1030 link.classList.remove('text-blue-400');1031 }1032 }1033 });1034 }1035 1036 // 监听滚动事件更新导航高亮1037 window.addEventListener('scroll', debounce(updateActiveNavLink, 100));1038 1039 // 初始化时更新一次1040 updateActiveNavLink();1041}1042 1043// 初始化移动端菜单1044function initMobileMenu() {1045 const mobileMenuBtn = document.getElementById('mobileMenuBtn');1046 const mobileMenu = document.getElementById('mobileMenu');1047 const mobileMenuLinks = mobileMenu.querySelectorAll('a');1048 1049 if (!mobileMenuBtn || !mobileMenu) {1050 console.warn('移动端菜单元素未找到');1051 return;1052 }1053 1054 // 切换菜单显示/隐藏1055 mobileMenuBtn.addEventListener('click', function() {1056 const isHidden = mobileMenu.classList.contains('hidden');1057 1058 if (isHidden) {1059 mobileMenu.classList.remove('hidden');1060 mobileMenuBtn.innerHTML = '<i class="fas fa-times text-xl"></i>';1061 } else {1062 mobileMenu.classList.add('hidden');1063 mobileMenuBtn.innerHTML = '<i class="fas fa-bars text-xl"></i>';1064 }1065 });1066 1067 // 点击菜单链接时关闭菜单1068 mobileMenuLinks.forEach(link => {1069 link.addEventListener('click', function() {1070 mobileMenu.classList.add('hidden');1071 mobileMenuBtn.innerHTML = '<i class="fas fa-bars text-xl"></i>';1072 });1073 });1074 1075 // 点击页面其他地方时关闭菜单1076 document.addEventListener('click', function(event) {1077 if (!mobileMenuBtn.contains(event.target) && !mobileMenu.contains(event.target)) {1078 mobileMenu.classList.add('hidden');1079 mobileMenuBtn.innerHTML = '<i class="fas fa-bars text-xl"></i>';1080 }1081 });1082 1083 // 窗口大小改变时关闭移动端菜单1084 window.addEventListener('resize', function() {1085 if (window.innerWidth >= 768) {1086 mobileMenu.classList.add('hidden');1087 mobileMenuBtn.innerHTML = '<i class="fas fa-bars text-xl"></i>';1088 }1089 });1090}1091 1092// 统一的响应式处理1093function handleResize() {1094 const currentWidth = window.innerWidth;1095 1096 // 重新初始化词云图表以适应新的屏幕尺寸1097 if (wordCloudChart) {1098 // 检查是否需要重新初始化(屏幕尺寸类别发生变化)1099 const wasMobile = window.lastWidth < 640;1100 const wasTablet = window.lastWidth >= 640 && window.lastWidth < 1024;1101 const isMobile = currentWidth < 640;1102 const isTablet = currentWidth >= 640 && currentWidth < 1024;1103 1104 // 如果设备类型发生变化,重新初始化1105 if ((wasMobile !== isMobile) || (wasTablet !== isTablet)) {1106 wordCloudChart.dispose();1107 initWordCloud();1108 } else {1109 // 否则只调整大小1110 wordCloudChart.resize();1111 }1112 }1113 1114 if (applicationChart) {1115 applicationChart.dispose();1116 initApplicationChart();1117 }1118 1119 if (maturityChart) {1120 maturityChart.resize();1121 }1122 1123 if (trendChart) {1124 trendChart.resize();1125 }1126 1127 // 记录当前宽度1128 window.lastWidth = currentWidth;1129}1130 1131// 词云图重试函数1132function retryWordCloud() {1133 console.log('重试加载词云图...');1134 const chartDom = document.getElementById('wordCloudChart');1135 if (chartDom) {1136 // 显示加载状态1137 chartDom.innerHTML = `1138 <div class="flex items-center justify-center h-full text-gray-400">1139 <div class="text-center">1140 <i class="fas fa-spinner fa-spin text-4xl mb-4 text-blue-400"></i>1141 <div class="text-lg font-medium">正在重新加载词云图...</div>1142 </div>1143 </div>1144 `;1145 1146 // 销毁现有图表实例1147 if (wordCloudChart) {1148 wordCloudChart.dispose();1149 wordCloudChart = null;1150 }1151 1152 // 延迟重新初始化,确保DOM更新完成1153 setTimeout(() => {1154 try {1155 initWordCloud();1156 } catch (error) {1157 console.error('重试加载词云图失败:', error);1158 chartDom.innerHTML = `1159 <div class="flex items-center justify-center h-full text-gray-400">1160 <div class="text-center">1161 <i class="fas fa-exclamation-triangle text-4xl mb-4 text-red-400"></i>1162 <div class="text-lg font-medium mb-2">词云图加载失败</div>1163 <div class="text-sm mb-4">请检查网络连接或刷新页面</div>1164 <button onclick="location.reload()" class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg transition-colors duration-200">1165 <i class="fas fa-refresh mr-2"></i>刷新页面1166 </button>1167 </div>1168 </div>1169 `;1170 }1171 }, 500);1172 }1173}1174 1175// 添加响应式监听1176window.addEventListener('resize', debounce(handleResize, 300));1177 1178// 页面加载完成后初始化所有功能1179document.addEventListener('DOMContentLoaded', function() {1180 console.log('页面加载完成,开始初始化...');1181 1182 try {1183 // 初始化所有图表1184 initWordCloud();1185 initApplicationChart();1186 initMaturityChart();1187 initTrendChart();1188 1189 // 初始化滚动进度1190 initScrollProgress();1191 1192 // 初始化导航功能1193 initNavigation();1194 1195 // 初始化交互功能1196 initializeInteractions();1197 1198 // 初始化移动端菜单1199 initMobileMenu();1200 