css三维布局(未来沉浸式)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>沉浸式3D水库大坝模拟</title>
    <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 src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/GLTFLoader.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            overflow: hidden;
            background: linear-gradient(to bottom, #1a2980, #26d0ce);
            color: #fff;
        }
        
        #container {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
        
        #info-panel {
            position: absolute;
            top: 20px;
            left: 20px;
            background: rgba(0, 0, 30, 0.7);
            border-radius: 15px;
            padding: 20px;
            max-width: 320px;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(255, 255, 255, 0.1);
            z-index: 100;
        }
        
        h1 {
            font-size: 2.2rem;
            margin-bottom: 15px;
            color: #4facfe;
            text-shadow: 0 0 10px rgba(79, 172, 254, 0.5);
        }
        
        .controls {
            margin: 15px 0;
        }
        
        .control-item {
            display: flex;
            margin: 10px 0;
            align-items: center;
        }
        
        .key {
            display: inline-block;
            width: 40px;
            height: 40px;
            background: rgba(0, 30, 60, 0.8);
            border: 2px solid #4facfe;
            border-radius: 8px;
            text-align: center;
            line-height: 36px;
            margin-right: 15px;
            font-weight: bold;
            box-shadow: 0 0 10px rgba(79, 172, 254, 0.3);
        }
        
        .status-bar {
            position: absolute;
            bottom: 20px;
            left: 20px;
            background: rgba(0, 0, 30, 0.7);
            border-radius: 15px;
            padding: 15px;
            font-size: 1.1rem;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(255, 255, 255, 0.1);
            z-index: 100;
        }
        
        .water-controls {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(0, 0, 30, 0.7);
            border-radius: 15px;
            padding: 20px;
            backdrop-filter: blur(5px);
            border: 1px solid rgba(255, 255, 255, 0.1);
            z-index: 100;
        }
        
        button {
            background: linear-gradient(to right, #4facfe, #00f2fe);
            border: none;
            color: white;
            padding: 10px 20px;
            margin: 5px;
            border-radius: 30px;
            cursor: pointer;
            font-weight: bold;
            transition: all 0.3s;
        }
        
        button:hover {
            transform: translateY(-3px);
            box-shadow: 0 5px 15px rgba(0, 242, 254, 0.4);
        }
        
        #loading {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: #0b1a30;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            transition: opacity 1s;
        }
        
        .progress {
            width: 300px;
            height: 20px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 10px;
            margin-top: 20px;
            overflow: hidden;
        }
        
        .progress-bar {
            height: 100%;
            background: linear-gradient(to right, #4facfe, #00f2fe);
            width: 0%;
            transition: width 0.5s;
        }
        
        .logo {
            font-size: 3rem;
            margin-bottom: 20px;
            text-align: center;
            color: #4facfe;
            text-shadow: 0 0 20px rgba(79, 172, 254, 0.7);
        }
        
        .logo span {
            color: #00f2fe;
        }
    </style>
</head>
<body>
    <div id="loading">
        <div class="logo">3D<span>大坝</span>模拟系统</div>
        <p>正在加载场景资源...</p>
        <div class="progress">
            <div class="progress-bar" id="progress-bar"></div>
        </div>
    </div>
    
    <div id="container"></div>
    
    <div id="info-panel">
        <h1>水库大坝模拟系统</h1>
        <p>本模拟展示了水力发电站的核心结构,包含大坝主体、发电机组、泄洪道和水库水体。</p>
        
        <div class="controls">
            <h3>控制说明:</h3>
            <div class="control-item">
                <div class="key">W</div>
                <span>前进</span>
            </div>
            <div class="control-item">
                <div class="key">S</div>
                <span>后退</span>
            </div>
            <div class="control-item">
                <div class="key">A</div>
                <span>左移</span>
            </div>
            <div class="control-item">
                <div class="key">D</div>
                <span>右移</span>
            </div>
            <div class="control-item">
                <div class="key">Q</div>
                <span>上升</span>
            </div>
            <div class="control-item">
                <div class="key">E</div>
                <span>下降</span>
            </div>
            <div class="control-item">
                <div class="key">R</div>
                <span>重置视角</span>
            </div>
            <div class="control-item">
                <div class="key">F</div>
                <span>飞行模式</span>
            </div>
            <div class="control-item">
                <div class="key">鼠标</div>
                <span>视角控制</span>
            </div>
        </div>
    </div>
    
    <div class="status-bar">
        <div>坐标: <span id="position">0, 0, 0</span></div>
        <div>视角模式: <span id="mode">行走模式</span></div>
        <div>时间: <span id="time">白天</span></div>
    </div>
    
    <div class="water-controls">
        <h3>水体控制</h3>
        <button id="normal-waves">正常波浪</button>
        <button id="storm-waves">风暴模式</button>
        <button id="calm-water">平静水面</button>
        <button id="toggle-flow">切换水流</button>
        <button id="toggle-time">切换时间</button>
    </div>

    <script>
        // 主要变量
        let scene, camera, renderer, controls;
        let dam, water, terrain, river, waterfall;
        let directionalLight, ambientLight, hemisphereLight;
        let clock = new THREE.Clock();
        let moveForward = false, moveBackward = false;
        let moveLeft = false, moveRight = false;
        let moveUp = false, moveDown = false;
        let velocity = new THREE.Vector3();
        let flyMode = false;
        let isDay = true;
        let waterLevel = 50;
        let waterFlow = true;

        // 初始化场景
        function init() {
            // 创建场景
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x87CEEB);
            scene.fog = new THREE.Fog(0x87CEEB, 500, 2000);

            // 创建相机
            camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 5000);
            camera.position.set(0, 100, 200);
            camera.lookAt(0, 0, 0);

            // 创建渲染器
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            renderer.setPixelRatio(window.devicePixelRatio);
            document.getElementById('container').appendChild(renderer.domElement);

            // 添加轨道控制
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.05;
            controls.screenSpacePanning = false;
            controls.minDistance = 50;
            controls.maxDistance = 1000;
            controls.maxPolarAngle = Math.PI / 2 - 0.1;

            // 添加光源
            setupLights();

            // 创建地形
            createTerrain();

            // 创建大坝
            createDam();

            // 创建水体
            createWater();

            // 创建环境
            createEnvironment();

            // 添加事件监听器
            setupEventListeners();

            // 开始动画
            animate();
            
            // 隐藏加载界面
            setTimeout(() => {
                document.getElementById('loading').style.opacity = '0';
                setTimeout(() => {
                    document.getElementById('loading').style.display = 'none';
                }, 1000);
            }, 2000);
            
            // 模拟加载进度
            let progress = 0;
            const interval = setInterval(() => {
                progress += Math.random() * 10;
                if (progress >= 100) {
                    progress = 100;
                    clearInterval(interval);
                }
                document.getElementById('progress-bar').style.width = progress + '%';
            }, 100);
        }

        // 设置光源
        function setupLights() {
            // 环境光
            ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
            scene.add(ambientLight);
            
            // 半球光
            hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.6);
            scene.add(hemisphereLight);
            
            // 方向光(太阳)
            directionalLight = new THREE.DirectionalLight(0xffffff, isDay ? 0.8 : 0.3);
            directionalLight.position.set(-100, 200, 100);
            directionalLight.castShadow = true;
            directionalLight.shadow.mapSize.width = 2048;
            directionalLight.shadow.mapSize.height = 2048;
            scene.add(directionalLight);
            
            // 大坝灯光
            const damLight = new THREE.PointLight(0xffaa00, 1, 200);
            damLight.position.set(0, 60, 0);
            scene.add(damLight);
        }

        // 创建地形
        function createTerrain() {
            // 地面
            const groundGeometry = new THREE.PlaneGeometry(2000, 2000, 50, 50);
            const groundMaterial = new THREE.MeshStandardMaterial({ 
                color: 0x3d8c40,
                roughness: 0.9,
                metalness: 0.1
            });
            
            // 创建高度变化
            const vertices = groundGeometry.attributes.position.array;
            for (let i = 0; i < vertices.length; i += 3) {
                const x = vertices[i];
                const z = vertices[i + 2];
                // 在河流区域创建凹陷
                if (Math.abs(z) < 200) {
                    vertices[i + 1] = -5;
                } else {
                    // 地形高度变化
                    const height = Math.sin(x * 0.01) * 20 + Math.cos(z * 0.01) * 20;
                    vertices[i + 1] = height;
                }
            }
            
            groundGeometry.computeVertexNormals();
            const ground = new THREE.Mesh(groundGeometry, groundMaterial);
            ground.rotation.x = -Math.PI / 2;
            ground.position.y = -5;
            ground.receiveShadow = true;
            scene.add(ground);
            
            // 添加岩石纹理
            const rockGeometry = new THREE.BoxGeometry(800, 100, 2000);
            const rockMaterial = new THREE.MeshStandardMaterial({ 
                color: 0x7a7a7a,
                roughness: 0.8
            });
            const rocks = new THREE.Mesh(rockGeometry, rockMaterial);
            rocks.position.set(0, -60, 0);
            rocks.receiveShadow = true;
            scene.add(rocks);
        }

        // 创建大坝结构
        function createDam() {
            const damGroup = new THREE.Group();
            
            // 坝体
            const damGeometry = new THREE.BoxGeometry(300, 100, 40);
            const damMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xaaaaaa,
                roughness: 0.7,
                metalness: 0.3
            });
            dam = new THREE.Mesh(damGeometry, damMaterial);
            dam.position.set(0, 50, 0);
            dam.castShadow = true;
            dam.receiveShadow = true;
            damGroup.add(dam);
            
            // 坝顶
            const topGeometry = new THREE.BoxGeometry(320, 5, 50);
            const topMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xcccccc,
                roughness: 0.5,
                metalness: 0.5
            });
            const top = new THREE.Mesh(topGeometry, topMaterial);
            top.position.set(0, 102, 0);
            top.castShadow = true;
            top.receiveShadow = true;
            damGroup.add(top);
            
            // 闸门
            const gateMaterial = new THREE.MeshStandardMaterial({ 
                color: 0x3366cc,
                roughness: 0.4,
                metalness: 0.6
            });
            
            for (let i = -120; i <= 120; i += 60) {
                const gateGeometry = new THREE.BoxGeometry(10, 40, 5);
                const gate = new THREE.Mesh(gateGeometry, gateMaterial);
                gate.position.set(i, 70, 20);
                gate.castShadow = true;
                damGroup.add(gate);
                
                // 闸门支撑结构
                const supportGeometry = new THREE.BoxGeometry(5, 50, 5);
                const support = new THREE.Mesh(supportGeometry, damMaterial);
                support.position.set(i, 60, 15);
                support.castShadow = true;
                damGroup.add(support);
            }
            
            // 发电站
            const powerStationGeometry = new THREE.BoxGeometry(100, 60, 80);
            const powerStation = new THREE.Mesh(powerStationGeometry, new THREE.MeshStandardMaterial({ 
                color: 0xdddddd,
                roughness: 0.6
            }));
            powerStation.position.set(0, 30, -60);
            powerStation.castShadow = true;
            powerStation.receiveShadow = true;
            damGroup.add(powerStation);
            
            // 发电站屋顶
            const roofGeometry = new THREE.ConeGeometry(60, 20, 4);
            const roof = new THREE.Mesh(roofGeometry, new THREE.MeshStandardMaterial({ 
                color: 0xaa2222,
                roughness: 0.8
            }));
            roof.position.set(0, 65, -60);
            roof.rotation.y = Math.PI / 4;
            roof.castShadow = true;
            damGroup.add(roof);
            
            scene.add(damGroup);
            
            // 创建瀑布
            createWaterfall();
        }

        // 创建水体
        function createWater() {
            const waterGeometry = new THREE.PlaneGeometry(1000, 500, 50, 50);
            
            // 自定义水材质
            const waterMaterial = new THREE.MeshStandardMaterial({
                color: 0x0077be,
                transparent: true,
                opacity: 0.9,
                roughness: 0.1,
                metalness: 0.9
            });
            
            water = new THREE.Mesh(waterGeometry, waterMaterial);
            water.rotation.x = -Math.PI / 2;
            water.position.set(0, waterLevel, -250);
            water.receiveShadow = true;
            scene.add(water);
            
            // 河流
            const riverGeometry = new THREE.PlaneGeometry(150, 1000, 20, 100);
            const riverMaterial = new THREE.MeshStandardMaterial({
                color: 0x0066aa,
                transparent: true,
                opacity: 0.9,
                roughness: 0.1,
                metalness: 0.8
            });
            
            river = new THREE.Mesh(riverGeometry, riverMaterial);
            river.rotation.x = -Math.PI / 2;
            river.position.set(0, 0, 250);
            river.receiveShadow = true;
            scene.add(river);
        }

        // 创建瀑布
        function createWaterfall() {
            // 瀑布粒子系统
            const particleCount = 2000;
            const particles = new THREE.BufferGeometry();
            const positions = new Float32Array(particleCount * 3);
            
            for (let i = 0; i < particleCount * 3; i += 3) {
                positions[i] = (Math.random() - 0.5) * 60; // x
                positions[i + 1] = Math.random() * 40 + 60; // y
                positions[i + 2] = Math.random() * 5 + 20; // z
            }
            
            particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            
            const particleMaterial = new THREE.PointsMaterial({
                color: 0x88ccff,
                size: 2,
                transparent: true,
                opacity: 0.7
            });
            
            waterfall = new THREE.Points(particles, particleMaterial);
            scene.add(waterfall);
        }

        // 创建环境
        function createEnvironment() {
            // 添加山脉
            for (let i = -1; i < 2; i += 2) {
                const mountainGeometry = new THREE.ConeGeometry(300, 200, 4);
                const mountainMaterial = new THREE.MeshStandardMaterial({ 
                    color: 0x556b2f,
                    roughness: 0.9
                });
                const mountain = new THREE.Mesh(mountainGeometry, mountainMaterial);
                mountain.position.set(i * 600, 0, -300);
                mountain.rotation.y = i * Math.PI / 4;
                mountain.castShadow = true;
                mountain.receiveShadow = true;
                scene.add(mountain);
            }
            
            // 添加树木
            const treeMaterial = new THREE.MeshStandardMaterial({ color: 0x2e8b57 });
            const trunkMaterial = new THREE.MeshStandardMaterial({ color: 0x8b4513 });
            
            for (let i = 0; i < 50; i++) {
                const x = (Math.random() - 0.5) * 1800;
                const z = (Math.random() - 0.5) * 1800 + 400;
                const y = -5;
                
                if (Math.abs(x) < 400 && Math.abs(z) < 400) continue;
                
                // 树干
                const trunkGeometry = new THREE.CylinderGeometry(2, 3, 10, 8);
                const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
                trunk.position.set(x, y, z);
                trunk.castShadow = true;
                trunk.receiveShadow = true;
                scene.add(trunk);
                
                // 树冠
                const treeGeometry = new THREE.ConeGeometry(8, 20, 6);
                const tree = new THREE.Mesh(treeGeometry, treeMaterial);
                tree.position.set(x, y + 15, z);
                tree.castShadow = true;
                scene.add(tree);
            }
            
            // 添加道路
            const roadGeometry = new THREE.PlaneGeometry(100, 1000);
            const roadMaterial = new THREE.MeshStandardMaterial({ 
                color: 0x444444,
                roughness: 0.9
            });
            const road = new THREE.Mesh(roadGeometry, roadMaterial);
            road.rotation.x = -Math.PI / 2;
            road.position.set(-200, 0.1, 0);
            road.receiveShadow = true;
            scene.add(road);
        }

        // 设置事件监听器
        function setupEventListeners() {
            // 键盘控制
            document.addEventListener('keydown', onKeyDown);
            document.addEventListener('keyup', onKeyUp);
            
            // 窗口大小调整
            window.addEventListener('resize', onWindowResize);
            
            // 控制按钮
            document.getElementById('normal-waves').addEventListener('click', () => setWaterMode('normal'));
            document.getElementById('storm-waves').addEventListener('click', () => setWaterMode('storm'));
            document.getElementById('calm-water').addEventListener('click', () => setWaterMode('calm'));
            document.getElementById('toggle-flow').addEventListener('click', toggleWaterFlow);
            document.getElementById('toggle-time').addEventListener('click', toggleTime);
        }

        // 键盘按下事件
        function onKeyDown(event) {
            switch (event.key.toLowerCase()) {
                case 'w': moveForward = true; break;
                case 's': moveBackward = true; break;
                case 'a': moveLeft = true; break;
                case 'd': moveRight = true; break;
                case 'q': moveUp = true; break;
                case 'e': moveDown = true; break;
                case 'r': resetView(); break;
                case 'f': toggleFlyMode(); break;
            }
        }

        // 键盘释放事件
        function onKeyUp(event) {
            switch (event.key.toLowerCase()) {
                case 'w': moveForward = false; break;
                case 's': moveBackward = false; break;
                case 'a': moveLeft = false; break;
                case 'd': moveRight = false; break;
                case 'q': moveUp = false; break;
                case 'e': moveDown = false; break;
            }
        }

        // 重置视角
        function resetView() {
            camera.position.set(0, 100, 200);
            camera.lookAt(0, 0, 0);
            flyMode = false;
            document.getElementById('mode').textContent = '行走模式';
        }

        // 切换飞行模式
        function toggleFlyMode() {
            flyMode = !flyMode;
            document.getElementById('mode').textContent = flyMode ? '飞行模式' : '行走模式';
            controls.enableRotate = flyMode;
        }

        // 设置水体模式
        function setWaterMode(mode) {
            water.material.roughness = 
                mode === 'calm' ? 0.1 : 
                mode === 'storm' ? 0.5 : 0.3;
        }

        // 切换水流
        function toggleWaterFlow() {
            waterFlow = !waterFlow;
        }

        // 切换时间
        function toggleTime() {
            isDay = !isDay;
            document.getElementById('time').textContent = isDay ? '白天' : '夜晚';
            
            // 更新光照
            directionalLight.intensity = isDay ? 0.8 : 0.3;
            scene.background = new THREE.Color(isDay ? 0x87CEEB : 0x0a1122);
            ambientLight.intensity = isDay ? 0.4 : 0.1;
            hemisphereLight.intensity = isDay ? 0.6 : 0.2;
        }

        // 窗口大小调整
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        // 动画循环
        function animate() {
            requestAnimationFrame(animate);
            
            const delta = clock.getDelta();
            
            // 更新控制
            controls.update();
            
            // 处理键盘移动
            velocity.x = 0;
            velocity.z = 0;
            velocity.y = 0;
            
            const speed = flyMode ? 100 : 50;
            
            if (moveForward) velocity.z -= speed * delta;
            if (moveBackward) velocity.z += speed * delta;
            if (moveLeft) velocity.x -= speed * delta;
            if (moveRight) velocity.x += speed * delta;
            if (moveUp) velocity.y += speed * delta;
            if (moveDown) velocity.y -= speed * delta;
            
            camera.translateX(velocity.x);
            camera.translateZ(velocity.z);
            camera.position.y += velocity.y;
            
            // 限制高度(非飞行模式)
            if (!flyMode && camera.position.y < 10) {
                camera.position.y = 10;
            }
            
            // 更新水体效果
            updateWaterEffect(delta);
            
            // 更新瀑布
            updateWaterfall(delta);
            
            // 更新状态显示
            updateStatus();
            
            // 渲染场景
            renderer.render(scene, camera);
        }

        // 更新水体效果
        function updateWaterEffect(delta) {
            if (!waterFlow) return;
            
            // 获取顶点位置
            const positions = water.geometry.attributes.position.array;
            const count = positions.length / 3;
            
            // 更新时间
            const time = Date.now() * 0.001;
            
            // 创建波浪效果
            for (let i = 0; i < count; i++) {
                const idx = i * 3;
                const x = positions[idx];
                const z = positions[idx + 2];
                
                // 创建波浪运动
                const waveHeight = Math.sin(x * 0.05 + time * 2) * 0.5 + 
                                   Math.cos(z * 0.03 + time * 1.5) * 0.7;
                
                positions[idx + 1] = waveHeight;
            }
            
            water.geometry.attributes.position.needsUpdate = true;
            water.geometry.computeVertexNormals();
        }

        // 更新瀑布
        function updateWaterfall(delta) {
            if (!waterFlow) return;
            
            const positions = waterfall.geometry.attributes.position.array;
            const count = positions.length / 3;
            const time = Date.now() * 0.001;
            
            for (let i = 0; i < count; i++) {
                const idx = i * 3;
                
                // 粒子下落
                positions[idx + 1] -= 40 * delta;
                
                // 如果粒子落到底部,重置位置
                if (positions[idx + 1] < 0) {
                    positions[idx] = (Math.random() - 0.5) * 60;
                    positions[idx + 1] = Math.random() * 10 + 80;
                    positions[idx + 2] = Math.random() * 5 + 20;
                }
                
                // 添加一些随机运动
                positions[idx] += (Math.random() - 0.5) * 0.5;
                positions[idx + 2] += (Math.random() - 0.5) * 0.3;
            }
            
            waterfall.geometry.attributes.position.needsUpdate = true;
        }

        // 更新状态显示
        function updateStatus() {
            const pos = camera.position;
            document.getElementById('position').textContent = 
                `${Math.round(pos.x)}, ${Math.round(pos.y)}, ${Math.round(pos.z)}`;
        }

        // 初始化应用
        init();
    </script>
</body>
</html>

  

posted @ 2025-06-24 14:49  华腾智算  阅读(18)  评论(0)    收藏  举报
https://damo.alibaba.com/ https://tianchi.aliyun.com/course?spm=5176.21206777.J_3941670930.5.87dc17c9BZNvLL