<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D建筑塌陷循环特效</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
}
canvas {
display: block;
}
.info {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: white;
font-family: Arial, sans-serif;
pointer-events: none;
}
a {
color: #4fc3f7;
text-decoration: none;
}
</style>
</head>
<body>
<div class="info">
</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
<script>
// 初始化场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x111111);
document.body.appendChild(renderer.domElement);
// 添加轨道控制器
const controls = new THREE.OrbitControls(camera, renderer.domElement);
camera.position.set(0, 30, 50);
controls.update();
// 添加环境光和定向光
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// 创建城市建筑
const buildings = [];
const buildingCount = 50;
const citySize = 40;
// 创建地面
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshStandardMaterial({
color: 0x333333,
roughness: 0.8,
metalness: 0.2
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 创建建筑函数
function createBuilding(x, z) {
const width = 2 + Math.random() * 3;
const depth = 2 + Math.random() * 3;
const height = 5 + Math.random() * 15;
const geometry = new THREE.BoxGeometry(width, height, depth);
const material = new THREE.MeshStandardMaterial({
color: Math.random() * 0xffffff,
roughness: 0.7,
metalness: 0.3
});
const building = new THREE.Mesh(geometry, material);
building.position.set(x, height/2, z);
building.userData = {
originalHeight: height,
originalPosition: { x: x, y: height/2, z: z },
collapseProgress: 0,
rebuildProgress: 0,
isCollapsing: false,
isRebuilding: false
};
scene.add(building);
buildings.push(building);
}
// 初始化城市
for (let i = 0; i < buildingCount; i++) {
const x = (Math.random() - 0.5) * citySize;
const z = (Math.random() - 0.5) * citySize;
createBuilding(x, z);
}
// 动画状态
let collapseStartTime = 0;
const collapseDuration = 3000; // 3秒塌陷
const rebuildDuration = 3000; // 3秒重建
let currentBuildingIndex = 0;
// 动画循环
function animate() {
requestAnimationFrame(animate);
const time = Date.now();
// 控制建筑塌陷和重建
if (buildings.length > 0) {
const building = buildings[currentBuildingIndex];
const data = building.userData;
if (!data.isCollapsing && !data.isRebuilding) {
// 开始塌陷
data.isCollapsing = true;
collapseStartTime = time;
} else if (data.isCollapsing) {
// 更新塌陷进度
const elapsed = time - collapseStartTime;
data.collapseProgress = elapsed / collapseDuration;
if (data.collapseProgress >= 1) {
data.collapseProgress = 1;
data.isCollapsing = false;
data.isRebuilding = true;
collapseStartTime = time;
}
// 应用塌陷效果
const collapseFactor = easeOutQuad(data.collapseProgress);
building.scale.y = 1 - collapseFactor;
building.position.y = data.originalPosition.y * (1 - collapseFactor);
// 添加一些随机偏移模拟倒塌效果
building.rotation.x = Math.sin(data.collapseProgress * Math.PI) * 0.2;
building.rotation.z = Math.sin(data.collapseProgress * Math.PI) * 0.2;
} else if (data.isRebuilding) {
// 更新重建进度
const elapsed = time - collapseStartTime;
data.rebuildProgress = elapsed / rebuildDuration;
if (data.rebuildProgress >= 1) {
data.rebuildProgress = 1;
data.isRebuilding = false;
data.collapseProgress = 0;
// 重置到下一个建筑
currentBuildingIndex = (currentBuildingIndex + 1) % buildings.length;
}
// 应用重建效果
const rebuildFactor = easeInQuad(data.rebuildProgress);
building.scale.y = rebuildFactor;
building.position.y = data.originalPosition.y * rebuildFactor;
// 重置旋转
building.rotation.x = 0;
building.rotation.z = 0;
}
}
// 添加一些相机动画
camera.position.y = 30 + Math.sin(time * 0.001) * 5;
controls.update();
renderer.render(scene, camera);
}
// 缓动函数
function easeOutQuad(t) {
return t * (2 - t);
}
function easeInQuad(t) {
return t * t;
}
// 窗口大小调整
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate();
</script>
</body>
</html>
202

被折叠的 条评论
为什么被折叠?



