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/
本站文章除注明[转载|引用|原文]出处外,均为本站原生内容,转载前请注明出处