返回博主主页

抽象圣诞树

<!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.140.1/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.140.1/examples/js/controls/OrbitControls.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background-color: #0a1128;
        }
        #canvas-container {
            position: relative;
            width: 100%;
            height: 100vh;
        }
        #info {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            font-family: Arial, sans-serif;
            z-index: 10;
            background-color: rgba(0, 0, 0, 0.5);
            padding: 10px;
            border-radius: 5px;
        }
        #merry-christmas {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: white;
            font-family: 'Arial Black', sans-serif;
            font-size: 48px;
            text-shadow: 0 0 10px #ff0000, 0 0 20px #ff0000, 0 0 30px #ff0000;
            opacity: 0;
            transition: opacity 1s ease-in-out;
            z-index: 5;
            pointer-events: none;
        }
        #santa-btn {
            position: absolute;
            bottom: 20px;
            right: 20px;
            padding: 10px 20px;
            background-color: #ff0000;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-family: Arial, sans-serif;
            font-weight: bold;
            z-index: 10;
            transition: all 0.3s ease;
        }
        #santa-btn:hover {
            background-color: #cc0000;
            transform: scale(1.05);
        }
    </style>
</head>
<body>
    <div id="canvas-container">
        <canvas id="scene-canvas"></canvas>
        <div id="info">
            <p>精美3D圣诞树</p>
            <p>鼠标拖拽: 旋转视角</p>
            <p>滚轮: 缩放</p>
            <p>点击装饰球: 点亮特效</p>
        </div>
        <div id="merry-christmas">MERRY CHRISTMAS!</div>
        <button id="santa-btn">召唤圣诞老人</button>
    </div>

    <script>
        // 全局变量
        let scene, camera, renderer, controls;
        let snowflakes = [];
        let ornaments = [];
        let lights = [];
        let santa = null;
        let treeGroup;
        let snowTexture;
        let isSantaVisible = false;
        let mouse = new THREE.Vector2();
        let raycaster = new THREE.Raycaster();

        // 初始化函数
        function init() {
            console.log('开始初始化精美3D圣诞树...');
            
            // 创建场景
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x0a1128);
            
            // 创建相机
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 5, 15);
            
            // 创建渲染器
            const canvas = document.getElementById('scene-canvas');
            renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            
            // 添加轨道控制器
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.05;
            controls.screenSpacePanning = false;
            controls.maxPolarAngle = Math.PI / 2;
            
            // 创建星空背景
            createStarfield();
            
            // 添加高级灯光
            addAdvancedLights();
            
            // 创建雪地
            createSnowyGround();
            
            // 创建圣诞树组
            treeGroup = new THREE.Group();
            scene.add(treeGroup);
            
            // 创建精美圣诞树
            createEnhancedTree();
            
            // 创建高级雪花系统
            createAdvancedSnowflakes();
            
            // 添加事件监听器
            window.addEventListener('resize', onWindowResize);
            window.addEventListener('click', onClick);
            document.getElementById('santa-btn').addEventListener('click', toggleSanta);
            
            // 开始动画循环
            animate();
            
            console.log('初始化完成,开始渲染...');
        }
        
        // 创建星空背景
        function createStarfield() {
            const starsGeometry = new THREE.BufferGeometry();
            const starsMaterial = new THREE.PointsMaterial({
                color: 0xffffff,
                size: 0.05,
                transparent: true,
                opacity: 0.8
            });
            
            const starsVertices = [];
            for (let i = 0; i < 5000; i++) {
                const x = (Math.random() - 0.5) * 200;
                const y = (Math.random() - 0.5) * 200;
                const z = (Math.random() - 0.5) * 200;
                starsVertices.push(x, y, z);
            }
            
            starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3));
            const stars = new THREE.Points(starsGeometry, starsMaterial);
            scene.add(stars);
        }
        
        // 添加高级灯光
        function addAdvancedLights() {
            // 环境光
            const ambientLight = new THREE.AmbientLight(0x404040, 0.4);
            scene.add(ambientLight);
            
            // 主方向光(模拟月光)
            const moonLight = new THREE.DirectionalLight(0xd0e0ff, 0.6);
            moonLight.position.set(5, 15, 7);
            moonLight.castShadow = true;
            moonLight.shadow.mapSize.width = 2048;
            moonLight.shadow.mapSize.height = 2048;
            moonLight.shadow.camera.near = 0.5;
            moonLight.shadow.camera.far = 50;
            scene.add(moonLight);
            
            // 添加一些彩色点光源(模拟远处的灯光)
            const colors = [0xff5555, 0x55ff55, 0x5555ff, 0xffff55];
            for (let i = 0; i < 8; i++) {
                const light = new THREE.PointLight(
                    colors[Math.floor(Math.random() * colors.length)],
                    0.3,
                    20
                );
                
                light.position.set(
                    Math.random() * 40 - 20,
                    Math.random() * 5 + 2,
                    Math.random() * 40 - 20
                );
                
                scene.add(light);
            }
        }
        
        // 创建雪地
        function createSnowyGround() {
            // 雪地平面
            const groundGeometry = new THREE.PlaneGeometry(100, 100);
            const groundMaterial = new THREE.MeshStandardMaterial({
                color: 0xffffff,
                roughness: 0.9,
                metalness: 0.1,
                bumpScale: 0.05
            });
            
            const ground = new THREE.Mesh(groundGeometry, groundMaterial);
            ground.rotation.x = -Math.PI / 2;
            ground.position.y = -0.5;
            ground.receiveShadow = true;
            scene.add(ground);
            
            // 添加雪堆
            for (let i = 0; i < 50; i++) {
                const moundGeometry = new THREE.SphereGeometry(
                    Math.random() * 0.8 + 0.3,
                    16,
                    16
                );
                
                const moundMaterial = new THREE.MeshStandardMaterial({
                    color: 0xffffff,
                    roughness: 0.9,
                    metalness: 0.05
                });
                
                const mound = new THREE.Mesh(moundGeometry, moundMaterial);
                
                mound.position.set(
                    Math.random() * 80 - 40,
                    -0.4,
                    Math.random() * 80 - 40
                );
                
                mound.scale.set(
                    Math.random() * 2 + 1,
                    Math.random() * 0.5 + 0.3,
                    Math.random() * 2 + 1
                );
                
                mound.castShadow = true;
                mound.receiveShadow = true;
                scene.add(mound);
            }
        }
        
        // 创建精美圣诞树
        function createEnhancedTree() {
            // 树干
            const trunkGeometry = new THREE.CylinderGeometry(0.3, 0.5, 1.5, 16);
            const trunkMaterial = new THREE.MeshStandardMaterial({
                color: 0x8B4513,
                roughness: 0.9,
                metalness: 0.1
            });
            
            const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
            trunk.position.y = 0.75;
            trunk.castShadow = true;
            trunk.receiveShadow = true;
            treeGroup.add(trunk);
            
            // 树冠(多层圆锥体)
            const treeParts = [];
            for (let i = 0; i < 6; i++) {
                const height = 1 - i * 0.05;
                const radius = 3 - i * 0.4;
                const coneHeight = 1.8;
                
                const geometry = new THREE.ConeGeometry(radius, coneHeight, 32);
                const material = new THREE.MeshStandardMaterial({
                    color: new THREE.Color(0x006400).offsetHSL(0, 0, i * 0.03),
                    roughness: 0.8,
                    metalness: 0.2
                });
                
                const part = new THREE.Mesh(geometry, material);
                part.position.y = 1.5 + i * (coneHeight * 0.8);
                part.castShadow = true;
                part.receiveShadow = true;
                treeGroup.add(part);
                treeParts.push(part);
            }
            
            // 树顶星星
            const starGeometry = new THREE.IcosahedronGeometry(0.5, 0);
            const starMaterial = new THREE.MeshBasicMaterial({
                color: 0xffff00,
                emissive: 0xffff00,
                emissiveIntensity: 0.8
            });
            
            const star = new THREE.Mesh(starGeometry, starMaterial);
            star.position.y = 10.5;
            treeGroup.add(star);
            
            // 添加灯带
            addChristmasLights();
            
            // 添加装饰球
            addOrnaments();
            
            // 添加礼物盒
            addGiftBoxes();
        }
        
        // 添加圣诞灯带
        function addChristmasLights() {
            const lightColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff];
            
            for (let i = 0; i < 30; i++) {
                const lightGeometry = new THREE.SphereGeometry(0.1, 8, 8);
                const lightMaterial = new THREE.MeshBasicMaterial({
                    color: lightColors[Math.floor(Math.random() * lightColors.length)],
                    emissive: lightColors[Math.floor(Math.random() * lightColors.length)],
                    emissiveIntensity: 0.8
                });
                
                const light = new THREE.Mesh(lightGeometry, lightMaterial);
                
                // 随机位置,在树的范围内
                const angle = Math.random() * Math.PI * 2;
                const height = Math.random() * 6 + 2;
                const radius = (1 - height / 8) * 2.5;
                
                light.position.set(
                    Math.cos(angle) * radius,
                    height,
                    Math.sin(angle) * radius
                );
                
                // 存储灯光数据
                const lightData = {
                    mesh: light,
                    originalColor: lightMaterial.color.clone(),
                    pulseSpeed: Math.random() * 0.03 + 0.01,
                    pulseIntensity: Math.random()
                };
                
                treeGroup.add(light);
                lights.push(lightData);
            }
        }
        
        // 添加装饰球
        function addOrnaments() {
            const colors = [
                0xff0000,  // 红色
                0x0000ff,  // 蓝色
                0xffff00,  // 黄色
                0xff00ff,  // 粉色
                0x00ffff,  // 青色
                0xffa500,  // 橙色
                0x9932cc,  // 紫色
                0xffc0cb   // 浅粉色
            ];
            
            for (let i = 0; i < 40; i++) {
                const radius = Math.random() * 0.25 + 0.15;
                const geometry = new THREE.SphereGeometry(radius, 16, 16);
                
                const color = colors[Math.floor(Math.random() * colors.length)];
                const material = new THREE.MeshStandardMaterial({
                    color: color,
                    roughness: 0.2,
                    metalness: 0.8,
                    reflectivity: 1.0
                });
                
                const ornament = new THREE.Mesh(geometry, material);
                
                // 在树上随机位置
                const angle = Math.random() * Math.PI * 2;
                const height = Math.random() * 6 + 2;
                const radiusFactor = (1 - (height - 2) / 6) * 2.5;
                
                ornament.position.set(
                    Math.cos(angle) * radiusFactor,
                    height,
                    Math.sin(angle) * radiusFactor
                );
                
                // 随机旋转
                ornament.rotation.x = Math.random() * Math.PI;
                ornament.rotation.y = Math.random() * Math.PI;
                
                ornament.castShadow = true;
                ornament.receiveShadow = true;
                
                treeGroup.add(ornament);
                
                ornaments.push({
                    mesh: ornament,
                    originalColor: material.color.clone(),
                    pulseIntensity: 0,
                    pulseSpeed: 0
                });
            }
        }
        
        // 添加礼物盒
        function addGiftBoxes() {
            const boxColors = [
                { body: 0xff0000, ribbon: 0xffff00 },  // 红色盒子,黄色丝带
                { body: 0x0000ff, ribbon: 0xffffff },  // 蓝色盒子,白色丝带
                { body: 0x00ff00, ribbon: 0xff00ff },  // 绿色盒子,粉色丝带
                { body: 0x9932cc, ribbon: 0x00ffff }   // 紫色盒子,青色丝带
            ];
            
            for (let i = 0; i < 8; i++) {
                const boxGroup = new THREE.Group();
                
                // 盒子主体
                const size = Math.random() * 0.5 + 0.4;
                const boxGeometry = new THREE.BoxGeometry(size, size, size);
                const boxColor = boxColors[Math.floor(Math.random() * boxColors.length)];
                
                const boxMaterial = new THREE.MeshStandardMaterial({
                    color: boxColor.body,
                    roughness: 0.7,
                    metalness: 0.2
                });
                
                const box = new THREE.Mesh(boxGeometry, boxMaterial);
                box.castShadow = true;
                box.receiveShadow = true;
                boxGroup.add(box);
                
                // 丝带
                const ribbonMaterial = new THREE.MeshStandardMaterial({
                    color: boxColor.ribbon,
                    roughness: 0.2,
                    metalness: 0.8
                });
                
                // 横向丝带
                const ribbonHGeometry = new THREE.BoxGeometry(size * 1.1, size * 0.1, size * 0.1);
                const ribbonH = new THREE.Mesh(ribbonHGeometry, ribbonMaterial);
                ribbonH.position.y = size * 0.05;
                boxGroup.add(ribbonH);
                
                // 纵向丝带
                const ribbonVGeometry = new THREE.BoxGeometry(size * 0.1, size * 1.1, size * 0.1);
                const ribbonV = new THREE.Mesh(ribbonVGeometry, ribbonMaterial);
                ribbonV.position.x = 0;
                ribbonV.position.y = 0;
                boxGroup.add(ribbonV);
                
                // 丝带结
                const bowGeometry = new THREE.SphereGeometry(size * 0.2, 8, 8);
                const bow = new THREE.Mesh(bowGeometry, ribbonMaterial);
                bow.position.y = size * 0.55;
                boxGroup.add(bow);
                
                // 随机位置(在树的底部周围)
                const angle = Math.random() * Math.PI * 2;
                const distance = Math.random() * 1.5 + 1.5;
                
                boxGroup.position.set(
                    Math.cos(angle) * distance,
                    size * 0.5 - 0.5,
                    Math.sin(angle) * distance
                );
                
                // 随机旋转
                boxGroup.rotation.y = Math.random() * Math.PI;
                
                treeGroup.add(boxGroup);
            }
        }
        
        // 创建高级雪花系统
        function createAdvancedSnowflakes() {
            // 创建雪花纹理
            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');
            canvas.width = 64;
            canvas.height = 64;
            
            // 绘制雪花
            context.fillStyle = 'white';
            context.beginPath();
            context.arc(32, 32, 30, 0, Math.PI * 2);
            context.fill();
            
            // 创建雪花形状
            const createSnowflake = () => {
                context.clearRect(0, 0, 64, 64);
                context.fillStyle = 'white';
                context.strokeStyle = 'white';
                context.lineWidth = 2;
                
                // 绘制雪花的基本形状
                const centerX = 32;
                const centerY = 32;
                const size = 20;
                
                // 绘制六条主分支
                for (let i = 0; i < 6; i++) {
                    const angle = (i * Math.PI) / 3;
                    
                    // 主分支
                    context.beginPath();
                    context.moveTo(centerX, centerY);
                    context.lineTo(
                        centerX + Math.cos(angle) * size,
                        centerY + Math.sin(angle) * size
                    );
                    context.stroke();
                    
                    // 侧分支
                    const sideAngle1 = angle + Math.PI / 6;
                    const sideAngle2 = angle - Math.PI / 6;
                    
                    context.beginPath();
                    context.moveTo(
                        centerX + Math.cos(angle) * size * 0.5,
                        centerY + Math.sin(angle) * size * 0.5
                    );
                    context.lineTo(
                        centerX + Math.cos(angle) * size * 0.5 + Math.cos(sideAngle1) * size * 0.3,
                        centerY + Math.sin(angle) * size * 0.5 + Math.sin(sideAngle1) * size * 0.3
                    );
                    context.stroke();
                    
                    context.beginPath();
                    context.moveTo(
                        centerX + Math.cos(angle) * size * 0.5,
                        centerY + Math.sin(angle) * size * 0.5
                    );
                    context.lineTo(
                        centerX + Math.cos(angle) * size * 0.5 + Math.cos(sideAngle2) * size * 0.3,
                        centerY + Math.sin(angle) * size * 0.5 + Math.sin(sideAngle2) * size * 0.3
                    );
                    context.stroke();
                }
            };
            
            createSnowflake();
            
            const snowTexture = new THREE.CanvasTexture(canvas);
            snowTexture.magFilter = THREE.LinearFilter;
            snowTexture.minFilter = THREE.LinearFilter;
            
            // 创建雪花粒子
            const snowflakesGeometry = new THREE.BufferGeometry();
            const snowflakesCount = 1000;
            
            const positions = new Float32Array(snowflakesCount * 3);
            const scales = new Float32Array(snowflakesCount);
            const velocities = new Float32Array(snowflakesCount * 3);
            const rotations = new Float32Array(snowflakesCount);
            const rotationSpeeds = new Float32Array(snowflakesCount);
            
            for (let i = 0; i < snowflakesCount; i++) {
                // 位置
                positions[i * 3] = (Math.random() - 0.5) * 100;
                positions[i * 3 + 1] = Math.random() * 50;
                positions[i * 3 + 2] = (Math.random() - 0.5) * 100;
                
                // 缩放
                scales[i] = Math.random() * 0.5 + 0.1;
                
                // 速度
                velocities[i * 3] = (Math.random() - 0.5) * 0.05;
                velocities[i * 3 + 1] = -(Math.random() * 0.05 + 0.01);
                velocities[i * 3 + 2] = (Math.random() - 0.5) * 0.05;
                
                // 旋转
                rotations[i] = Math.random() * Math.PI * 2;
                rotationSpeeds[i] = (Math.random() - 0.5) * 0.02;
            }
            
            snowflakesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
            snowflakesGeometry.setAttribute('scale', new THREE.BufferAttribute(scales, 1));
            snowflakesGeometry.setAttribute('velocity', new THREE.BufferAttribute(velocities, 3));
            snowflakesGeometry.setAttribute('rotation', new THREE.BufferAttribute(rotations, 1));
            snowflakesGeometry.setAttribute('rotationSpeed', new THREE.BufferAttribute(rotationSpeeds, 1));
            
            // 创建雪花材质
            const snowflakesMaterial = new THREE.PointsMaterial({
                size: 0.5,
                map: snowTexture,
                transparent: true,
                opacity: 0.8,
                blending: THREE.AdditiveBlending,
                depthTest: false
            });
            
            // 创建雪花粒子系统
            const snowflakesParticles = new THREE.Points(snowflakesGeometry, snowflakesMaterial);
            scene.add(snowflakesParticles);
            
            // 存储雪花系统
            snowflakes = {
                particles: snowflakesParticles,
                positions: positions,
                velocities: velocities,
                rotations: rotations,
                rotationSpeeds: rotationSpeeds,
                count: snowflakesCount
            };
        }
        
        // 创建圣诞老人
        function createSanta() {
            const santaGroup = new THREE.Group();
            
            // 身体
            const bodyGeometry = new THREE.CylinderGeometry(0.8, 1, 2, 16);
            const bodyMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xff0000,
                roughness: 0.7,
                metalness: 0.2
            });
            
            const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
            body.position.y = 1;
            body.castShadow = true;
            body.receiveShadow = true;
            santaGroup.add(body);
            
            // 手臂
            const armGeometry = new THREE.CylinderGeometry(0.2, 0.15, 1.5, 8);
            const armMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
            
            const leftArm = new THREE.Mesh(armGeometry, armMaterial);
            leftArm.position.set(-0.9, 1.2, 0);
            leftArm.rotation.z = Math.PI / 6;
            leftArm.castShadow = true;
            leftArm.receiveShadow = true;
            santaGroup.add(leftArm);
            
            const rightArm = new THREE.Mesh(armGeometry, armMaterial);
            rightArm.position.set(0.9, 1.2, 0);
            rightArm.rotation.z = -Math.PI / 6;
            rightArm.castShadow = true;
            rightArm.receiveShadow = true;
            santaGroup.add(rightArm);
            
            // 头部
            const headGeometry = new THREE.SphereGeometry(0.6, 16, 16);
            const headMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff });
            
            const head = new THREE.Mesh(headGeometry, headMaterial);
            head.position.y = 2.6;
            head.castShadow = true;
            head.receiveShadow = true;
            santaGroup.add(head);
            
            // 帽子
            const hatGeometry = new THREE.ConeGeometry(0.6, 1, 16);
            const hatMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
            
            const hat = new THREE.Mesh(hatGeometry, hatMaterial);
            hat.position.y = 3.3;
            hat.castShadow = true;
            hat.receiveShadow = true;
            santaGroup.add(hat);
            
            // 胡子
            const beardGeometry = new THREE.ConeGeometry(0.5, 0.8, 16);
            const beardMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff });
            
            const beard = new THREE.Mesh(beardGeometry, beardMaterial);
            beard.rotation.x = Math.PI;
            beard.position.y = 2.2;
            beard.castShadow = true;
            beard.receiveShadow = true;
            santaGroup.add(beard);
            
            // 眼睛
            const eyeGeometry = new THREE.SphereGeometry(0.08, 8, 8);
            const eyeMaterial = new THREE.MeshStandardMaterial({ color: 0x000000 });
            
            const leftEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
            leftEye.position.set(-0.2, 2.8, 0.5);
            santaGroup.add(leftEye);
            
            const rightEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
            rightEye.position.set(0.2, 2.8, 0.5);
            santaGroup.add(rightEye);
            
            // 鼻子
            const noseGeometry = new THREE.ConeGeometry(0.15, 0.3, 8);
            const noseMaterial = new THREE.MeshStandardMaterial({ color: 0xff6600 });
            
            const nose = new THREE.Mesh(noseGeometry, noseMaterial);
            nose.position.set(0, 2.6, 0.5);
            nose.rotation.x = Math.PI;
            santaGroup.add(nose);
            
            // 礼物袋
            const bagGeometry = new THREE.CylinderGeometry(0.4, 0.6, 1, 16);
            const bagMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
            
            const bag = new THREE.Mesh(bagGeometry, bagMaterial);
            bag.position.set(0, -0.2, 0);
            bag.castShadow = true;
            bag.receiveShadow = true;
            santaGroup.add(bag);
            
            // 放置圣诞老人
            santaGroup.position.set(8, 0, 8);
            santaGroup.rotation.y = Math.PI / 4;
            
            // 存储圣诞老人数据
            santa = {
                mesh: santaGroup,
                targetPosition: new THREE.Vector3(8, 0, 8),
                currentPosition: new THREE.Vector3(8, 0, 8),
                animationPhase: 0,
                wavePhase: 0
            };
            
            scene.add(santa.mesh);
            isSantaVisible = true;
        }
        
        // 窗口大小调整
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
        
        // 点击事件
        function onClick(event) {
            // 计算鼠标位置
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            
            // 更新射线
            raycaster.setFromCamera(mouse, camera);
            
            // 检测是否点击了装饰球
            const intersects = raycaster.intersectObjects(ornaments.map(o => o.mesh));
            
            if (intersects.length > 0) {
                // 找到被点击的装饰球
                const clickedOrnament = intersects[0].object;
                const ornamentData = ornaments.find(o => o.mesh === clickedOrnament);
                
                if (ornamentData) {
                    // 设置装饰球开始闪烁
                    ornamentData.pulseIntensity = 1;
                    ornamentData.pulseSpeed = Math.random() * 0.05 + 0.02;
                    
                    // 显示圣诞快乐文字
                    showMerryChristmas();
                }
            } else {
                // 随机点亮一些装饰球
                for (let i = 0; i < 3; i++) {
                    const randomIndex = Math.floor(Math.random() * ornaments.length);
                    ornaments[randomIndex].pulseIntensity = 1;
                    ornaments[randomIndex].pulseSpeed = Math.random() * 0.05 + 0.02;
                }
            }
        }
        
        // 显示圣诞快乐文字
        function showMerryChristmas() {
            const element = document.getElementById('merry-christmas');
            element.style.opacity = '1';
            
            setTimeout(() => {
                element.style.opacity = '0';
            }, 3000);
        }
        
        // 切换圣诞老人显示
        function toggleSanta() {
            if (isSantaVisible) {
                if (santa && santa.mesh) {
                    scene.remove(santa.mesh);
                }
                isSantaVisible = false;
                document.getElementById('santa-btn').textContent = '召唤圣诞老人';
            } else {
                if (!santa) {
                    createSanta();
                } else {
                    scene.add(santa.mesh);
                    isSantaVisible = true;
                }
                document.getElementById('santa-btn').textContent = '隐藏圣诞老人';
            }
        }
        
        // 动画循环
        function animate() {
            requestAnimationFrame(animate);
            
            // 更新控制器
            controls.update();
            
            // 更新雪花
            updateSnowflakes();
            
            // 更新灯光
            updateLights();
            
            // 更新装饰球
            updateOrnaments();
            
            // 更新圣诞老人
            if (santa && isSantaVisible) {
                updateSanta();
            }
            
            // 渲染场景
            renderer.render(scene, camera);
        }
        
        // 更新雪花
        function updateSnowflakes() {
            if (!snowflakes.particles) return;
            
            const positions = snowflakes.positions;
            const velocities = snowflakes.velocities;
            const rotations = snowflakes.rotations;
            const rotationSpeeds = snowflakes.rotationSpeeds;
            
            for (let i = 0; i < snowflakes.count; i++) {
                // 更新位置
                positions[i * 3] += velocities[i * 3];
                positions[i * 3 + 1] += velocities[i * 3 + 1];
                positions[i * 3 + 2] += velocities[i * 3 + 2];
                
                // 更新旋转
                rotations[i] += rotationSpeeds[i];
                
                // 如果雪花超出边界,重置位置
                if (
                    positions[i * 3] < -50 ||
                    positions[i * 3] > 50 ||
                    positions[i * 3 + 1] < -5 ||
                    positions[i * 3 + 1] > 50 ||
                    positions[i * 3 + 2] < -50 ||
                    positions[i * 3 + 2] > 50
                ) {
                    positions[i * 3] = Math.random() * 100 - 50;
                    positions[i * 3 + 1] = 50;
                    positions[i * 3 + 2] = Math.random() * 100 - 50;
                    
                    velocities[i * 3] = (Math.random() - 0.5) * 0.05;
                    velocities[i * 3 + 1] = -(Math.random() * 0.05 + 0.01);
                    velocities[i * 3 + 2] = (Math.random() - 0.5) * 0.05;
                }
            }
            
            snowflakes.particles.geometry.attributes.position.needsUpdate = true;
            snowflakes.particles.geometry.attributes.rotation.needsUpdate = true;
        }
        
        // 更新灯光
        function updateLights() {
            lights.forEach(lightData => {
                // 灯光闪烁效果
                lightData.pulseIntensity += lightData.pulseSpeed;
                
                if (lightData.pulseIntensity > 1 || lightData.pulseIntensity < 0) {
                    lightData.pulseSpeed *= -1;
                }
                
                // 调整发光强度
                const intensity = 0.5 + Math.abs(Math.sin(lightData.pulseIntensity * Math.PI)) * 0.5;
                lightData.mesh.material.emissiveIntensity = intensity;
            });
        }
        
        // 更新装饰球
        function updateOrnaments() {
            ornaments.forEach(ornament => {
                if (ornament.pulseIntensity > 0) {
                    // 装饰球闪烁效果
                    ornament.pulseIntensity -= ornament.pulseSpeed;
                    
                    if (ornament.pulseIntensity < 0) {
                        ornament.pulseIntensity = 0;
                    }
                    
                    // 计算当前颜色(在原始颜色和亮白色之间插值)
                    const pulseColor = new THREE.Color().lerpVectors(
                        ornament.originalColor,
                        new THREE.Color(0xffffff),
                        Math.sin(ornament.pulseIntensity * Math.PI) * 0.5 + 0.5
                    );
                    
                    ornament.mesh.material.color.copy(pulseColor);
                }
            });
        }
        
        // 更新圣诞老人
        function updateSanta() {
            if (!santa) return;
            
            // 更新动画阶段
            santa.animationPhase += 0.02;
            santa.wavePhase += 0.05;
            
            // 随机改变目标位置
            if (Math.random() < 0.01) {
                santa.targetPosition.set(
                    Math.random() * 12 - 6,
                    0,
                    Math.random() * 12 - 6
                );
            }
            
            // 向目标位置移动
            santa.currentPosition.lerp(santa.targetPosition, 0.01);
            santa.mesh.position.copy(santa.currentPosition);
            
            // 朝向相机
            santa.mesh.lookAt(camera.position);
            santa.mesh.rotation.x = 0;
            santa.mesh.rotation.z = 0;
            
            // 手臂摆动动画
            const rightArm = santa.mesh.children[3]; // 假设右手臂是第四个子元素
            if (rightArm) {
                rightArm.rotation.z = -Math.PI / 6 + Math.sin(santa.wavePhase) * 0.3;
            }
            
            // 身体轻微摆动
            santa.mesh.rotation.z = Math.sin(santa.animationPhase) * 0.05;
        }
        
        // 页面加载完成后初始化
        if (typeof THREE !== 'undefined') {
            window.addEventListener('load', init);
            
            // 立即尝试初始化
            if (document.readyState !== 'loading') {
                setTimeout(init, 100);
            }
        } else {
            console.error('Three.js库没有正确加载!');
            document.body.innerHTML = '<h1 style="color: red;">错误:Three.js库没有正确加载!</h1>';
        }
    </script>
</body>
</html>
posted @ 2025-12-25 21:32  懒惰的星期六  阅读(5)  评论(0)    收藏  举报