3D标签云动画效果
交互式3D标签展示,鼠标悬停可查看标签详情,点击控制按钮调整动画效果。

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D标签云 - 美观设计</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif; background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c); color: #fff; min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 20px; overflow-x: hidden; } header { text-align: center; padding: 30px 0; width: 100%%; max-width: 800px; margin-bottom: 20px; } h1 { font-size: 3.2rem; margin-bottom: 15px; text-shadow: 0 0 15px rgba(255, 255, 255, 0.6); background: linear-gradient(to right, #ff7e5f, #feb47b); -webkit-background-clip: text; background-clip: text; color: transparent; } .subtitle { font-size: 1.2rem; opacity: 0.85; max-width: 600px; margin: 0 auto; line-height: 1.6; } .controls { display: flex; justify-content: center; gap: 15px; margin: 20px 0; flex-wrap: wrap; } .control-btn { background: rgba(255, 255, 255, 0.15); color: white; border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 30px; padding: 10px 20px; font-size: 1rem; cursor: pointer; transition: all 0.3s ease; backdrop-filter: blur(5px); } .control-btn:hover { background: rgba(255, 255, 255, 0.25); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); } .tagBall-container { position: relative; width: 100%%; max-width: 600px; height: 500px; margin: 0 auto 40px; perspective: 1000px; } .tagBall { width: 100%%; height: 100%%; position: relative; margin: 0 auto; transform-style: preserve-3d; transition: transform 0.5s ease; } .tag { display: block; position: absolute; left: 0; top: 0; color: white; text-decoration: none; font-weight: bold; will-change: transform; padding: 10px 18px; border-radius: 30px; text-align: center; min-width: 100px; transition: all 0.3s ease; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); font-size: 16px; backdrop-filter: blur(4px); background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.15); } .tag:hover { background: rgba(255, 255, 255, 0.25); transform: scale(1.15) !important; z-index: 1000 !important; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.5); } .stats { background: rgba(255, 255, 255, 0.08); border-radius: 15px; padding: 20px; max-width: 600px; width: 100%%; margin-top: 20px; border: 1px solid rgba(255, 255, 255, 0.1); backdrop-filter: blur(5px); } .stats h2 { text-align: center; margin-bottom: 15px; font-size: 1.6rem; color: #ffb74d; } .stats-content { display: flex; justify-content: space-around; flex-wrap: wrap; gap: 20px; } .stat-item { text-align: center; flex: 1; min-width: 120px; } .stat-value { font-size: 2rem; font-weight: bold; color: #4fc3f7; margin-bottom: 5px; } .stat-label { font-size: 0.9rem; opacity: 0.8; } footer { margin-top: 30px; text-align: center; padding: 20px; font-size: 0.9rem; opacity: 0.7; width: 100%%; } @media (max-width: 600px) { h1 { font-size: 2.5rem; } .tagBall-container { height: 400px; } } </style> </head> <body> <header> <h1>3D标签云</h1> <p>交互式3D标签展示,鼠标悬停可查看标签详情,点击控制按钮调整动画效果</p> </header> <div> <button id="speedUp">加速旋转</button> <button id="speedDown">减速旋转</button> <button id="pauseResume">暂停动画</button> <button id="changeSize">调整大小</button> </div> <div> <div id="tagBall"> <!-- 标签将通过JS动态添加 --> </div> </div> <div> <h2>标签云统计</h2> <div> <div> <div>32</div> <div>标签总数</div> </div> <div> <div>12</div> <div>热门标签</div> </div> <div> <div>6</div> <div>分类数量</div> </div> </div> </div> <footer> <p>3D标签云交互展示 | 使用HTML5, CSS3和JavaScript实现</p> </footer> <script> // 标签数据 const tagsData = [ { text: "前端开发", category: "tech" }, { text: "JavaScript", category: "tech" }, { text: "CSS3", category: "tech" }, { text: "HTML5", category: "tech" }, { text: "React", category: "tech" }, { text: "Vue.js", category: "tech" }, { text: "Node.js", category: "tech" }, { text: "Web设计", category: "design" }, { text: "UI/UX", category: "design" }, { text: "响应式布局", category: "design" }, { text: "用户体验", category: "design" }, { text: "动画设计", category: "design" }, { text: "数据可视化", category: "data" }, { text: "大数据", category: "data" }, { text: "人工智能", category: "ai" }, { text: "机器学习", category: "ai" }, { text: "深度学习", category: "ai" }, { text: "云计算", category: "cloud" }, { text: "DevOps", category: "cloud" }, { text: "容器化", category: "cloud" }, { text: "微服务", category: "cloud" }, { text: "移动开发", category: "mobile" }, { text: "iOS", category: "mobile" }, { text: "Android", category: "mobile" }, { text: "Flutter", category: "mobile" }, { text: "游戏开发", category: "game" }, { text: "Unity", category: "game" }, { text: "3D建模", category: "game" }, { text: "网络安全", category: "security" }, { text: "区块链", category: "blockchain" }, { text: "物联网", category: "iot" }, { text: "智能家居", category: "iot" } ]; // 不同类别的颜色 const categoryColors = { tech: "#4fc3f7", design: "#ffb74d", data: "#81c784", ai: "#f06292", cloud: "#ba68c8", mobile: "#ff8a65", game: "#a1887f", security: "#e57373", blockchain: "#4db6ac", iot: "#7986cb" }; const tagBall = document.getElementById('tagBall'); let RADIUS = 220; const fallLength = 500; let tags = []; let angleX = Math.PI / 500; let angleY = Math.PI / 500; let CX, CY; let animationId; let isPaused = false; let speedFactor = 1; // 初始化标签 function initTags() { tagBall.innerHTML = ''; tags = []; // 创建标签元素 tagsData.forEach((tagData, i) => { const tagEle = document.createElement('a'); tagEle.className = 'tag'; tagEle.textContent = tagData.text; tagEle.style.backgroundColor = categoryColors[tagData.category]; tagBall.appendChild(tagEle); const k = -1 + (2 * (i + 1) - 1) / tagsData.length; const a = Math.acos(k); const b = a * Math.sqrt(tagsData.length * Math.PI); const x = RADIUS * Math.sin(a) * Math.cos(b); const y = RADIUS * Math.sin(a) * Math.sin(b); const z = RADIUS * Math.cos(a); tags.push(new Tag(tagEle, x, y, z)); }); } // 更新容器中心点 function updateCenter() { CX = tagBall.offsetWidth / 2; CY = tagBall.offsetHeight / 2; } // Tag类 class Tag { constructor(ele, x, y, z) { this.ele = ele; this.x = x; this.y = y; this.z = z; } move() { const scale = fallLength / (fallLength - this.z); const alpha = (this.z + RADIUS) / (2 * RADIUS); // 计算位置 const left = this.x + CX - this.ele.offsetWidth / 2; const top = this.y + CY - this.ele.offsetHeight / 2; // 应用变换 this.ele.style.opacity = Math.max(alpha + 0.3, 0.6); this.ele.style.zIndex = parseInt(scale * 100); // 使用transform实现高性能动画 this.ele.style.transform = `translate3d(${left}px, ${top}px, 0) scale(${scale})`; } } // 旋转函数 function rotateX() { const cos = Math.cos(angleX * speedFactor); const sin = Math.sin(angleX * speedFactor); tags.forEach(tag => { const y1 = tag.y * cos - tag.z * sin; const z1 = tag.z * cos + tag.y * sin; tag.y = y1; tag.z = z1; }); } function rotateY() { const cos = Math.cos(angleY * speedFactor); const sin = Math.sin(angleY * speedFactor); tags.forEach(tag => { const x1 = tag.x * cos - tag.z * sin; const z1 = tag.z * cos + tag.x * sin; tag.x = x1; tag.z = z1; }); } // 动画循环 function animate() { if (isPaused) return; rotateX(); rotateY(); tags.forEach(tag => { tag.move(); }); animationId = requestAnimationFrame(animate); } // 初始化 function init() { initTags(); updateCenter(); // 初始化位置 tags.forEach(tag => tag.move()); // 开始动画 animate(); // 添加鼠标交互 tagBall.addEventListener('mousemove', (e) => { if (isPaused) return; const rect = tagBall.getBoundingClientRect(); const x = e.clientX - rect.left - CX; const y = e.clientY - rect.top - CY; angleY = x * 0.0001; angleX = y * 0.0001; }); // 窗口大小改变时更新中心点 window.addEventListener('resize', () => { updateCenter(); tags.forEach(tag => tag.move()); }); } // 控制按钮事件 document.getElementById('speedUp').addEventListener('click', () => { speedFactor = Math.min(speedFactor + 0.5, 3); }); document.getElementById('speedDown').addEventListener('click', () => { speedFactor = Math.max(speedFactor - 0.5, 0.5); }); document.getElementById('pauseResume').addEventListener('click', function() { isPaused = !isPaused; this.textContent = isPaused ? '继续动画' : '暂停动画'; if (!isPaused) { animate(); } }); document.getElementById('changeSize').addEventListener('click', () => { RADIUS = RADIUS === 220 ? 180 : RADIUS === 180 ? 250 : 220; initTags(); updateCenter(); tags.forEach(tag => tag.move()); }); // 启动 window.onload = init; </script> </body> </html>
本文最后更新时间 2025-06-16
文章链接地址:https://xzlo.blog/index.php/archives/50/
本站文章除注明[转载|引用|原文]出处外,均为本站原生内容,转载前请注明出处