返回博主主页

抽象圣诞树2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Christmas Tree</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>
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.2/dist/gsap.min.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background-color: #1a1a2e;
        }
        #info {
            position: absolute;
            top: 10px;
            left: 10px;
            color: white;
            font-family: Arial, sans-serif;
            z-index: 100;
        }
    </style>
</head>
<body>
    <div id="info">
        <p>Click and drag to rotate the scene</p>
        <p>Scroll to zoom in/out</p>
    </div>
    <script>
        // Scene setup
        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(0x1a1a2e);
        document.body.appendChild(renderer.domElement);

        // Controls
        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;
        camera.position.set(0, 5, 15);

        // Snow ground
        const groundGeometry = new THREE.PlaneGeometry(100, 100);
        const groundMaterial = new THREE.MeshStandardMaterial({ 
            color: 0xffffff,
            roughness: 0.8,
            metalness: 0.2
        });
        const ground = new THREE.Mesh(groundGeometry, groundMaterial);
        ground.rotation.x = -Math.PI / 2;
        ground.position.y = -0.5;
        scene.add(ground);

        // Christmas tree (Pixar style)
        function createChristmasTree() {
            const treeGroup = new THREE.Group();

            // Tree trunk
            const trunkGeometry = new THREE.CylinderGeometry(0.5, 0.7, 2, 16);
            const trunkMaterial = new THREE.MeshStandardMaterial({ 
                color: 0x8B4513,
                roughness: 0.9,
                metalness: 0.1
            });
            const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
            trunk.position.y = 1;
            treeGroup.add(trunk);

            // Tree leaves (conical sections with rounded edges for Pixar style)
            const leafColors = [0x006400, 0x228B22, 0x32CD32];
            for (let i = 0; i < 5; i++) {
                const radius = 2.5 - i * 0.4;
                const height = 2 - i * 0.3;
                const segments = 32;
                
                // Create a cone with rounded top
                const leafGeometry = new THREE.ConeGeometry(radius, height, segments);
                const leafMaterial = new THREE.MeshStandardMaterial({ 
                    color: leafColors[i % leafColors.length],
                    roughness: 0.8,
                    metalness: 0.2,
                    shininess: 30
                });
                const leaf = new THREE.Mesh(leafGeometry, leafMaterial);
                leaf.position.y = 3 + i * 0.8;
                
                // Add slight curve for more organic look
                leaf.scale.set(1, 1.1, 1);
                treeGroup.add(leaf);
            }

            // Tree topper (star)
            const starGeometry = new THREE.IcosahedronGeometry(0.5, 0);
            const starMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xFFD700,
                emissive: 0xFFD700,
                emissiveIntensity: 0.3,
                roughness: 0.2,
                metalness: 0.8
            });
            const star = new THREE.Mesh(starGeometry, starMaterial);
            star.position.y = 7.5;
            star.scale.set(1.2, 1.5, 1.2);
            treeGroup.add(star);

            // Decorations
            const decorationColors = [0xFF0000, 0xFFA500, 0xFFC0CB, 0x800080, 0x00BFFF];
            for (let i = 0; i < 30; i++) {
                const decorationGeometry = new THREE.SphereGeometry(0.2, 16, 16);
                const decorationMaterial = new THREE.MeshStandardMaterial({ 
                    color: decorationColors[i % decorationColors.length],
                    emissive: decorationColors[i % decorationColors.length],
                    emissiveIntensity: 0.2,
                    roughness: 0.1,
                    metalness: 0.9
                });
                const decoration = new THREE.Mesh(decorationGeometry, decorationMaterial);
                
                // Random position on tree
                const angle = Math.random() * Math.PI * 2;
                const radius = Math.random() * 2 + 0.5;
                const height = Math.random() * 5 + 2;
                
                decoration.position.x = Math.cos(angle) * radius;
                decoration.position.z = Math.sin(angle) * radius;
                decoration.position.y = height;
                
                // Check if decoration is inside the tree
                const maxRadiusAtHeight = 2.5 - (height - 2) * 0.4;
                if (Math.sqrt(decoration.position.x ** 2 + decoration.position.z ** 2) < maxRadiusAtHeight) {
                    treeGroup.add(decoration);
                }
            }

            return treeGroup;
        }

        const christmasTree = createChristmasTree();
        scene.add(christmasTree);

        // Santa Claus
        function createSanta() {
            const santaGroup = new THREE.Group();
            
            // Body
            const bodyGeometry = new THREE.SphereGeometry(0.8, 32, 32);
            const bodyMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xFF0000,
                roughness: 0.8,
                metalness: 0.2
            });
            const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
            body.position.y = 1.2;
            santaGroup.add(body);
            
            // Head
            const headGeometry = new THREE.SphereGeometry(0.5, 32, 32);
            const headMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xFFDAB9,
                roughness: 0.9,
                metalness: 0.1
            });
            const head = new THREE.Mesh(headGeometry, headMaterial);
            head.position.y = 2.5;
            santaGroup.add(head);
            
            // Hat
            const hatGeometry = new THREE.ConeGeometry(0.5, 0.8, 32);
            const hatMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xFF0000,
                roughness: 0.8,
                metalness: 0.2
            });
            const hat = new THREE.Mesh(hatGeometry, hatMaterial);
            hat.position.y = 3.2;
            santaGroup.add(hat);
            
            // Beard
            const beardGeometry = new THREE.ConeGeometry(0.4, 0.6, 32);
            const beardMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xFFFFFF,
                roughness: 0.9,
                metalness: 0.1
            });
            const beard = new THREE.Mesh(beardGeometry, beardMaterial);
            beard.position.y = 2.2;
            beard.rotation.x = Math.PI;
            santaGroup.add(beard);

            // Position Santa to the side
            santaGroup.position.set(-5, 0, 3);
            santaGroup.scale.set(0.8, 0.8, 0.8);
            
            return santaGroup;
        }

        const santa = createSanta();
        scene.add(santa);

        // Snowflakes
        function createSnowflakes(count) {
            const snowflakes = [];
            const snowflakeGeometry = new THREE.SphereGeometry(0.05, 8, 8);
            const snowflakeMaterial = new THREE.MeshStandardMaterial({ 
                color: 0xFFFFFF,
                transparent: true,
                opacity: 0.8,
                roughness: 0.1,
                metalness: 0.9
            });

            for (let i = 0; i < count; i++) {
                const snowflake = new THREE.Mesh(snowflakeGeometry, snowflakeMaterial);
                
                // Random position
                snowflake.position.x = (Math.random() - 0.5) * 50;
                snowflake.position.y = Math.random() * 20 + 5;
                snowflake.position.z = (Math.random() - 0.5) * 50;
                
                // Random size
                const size = Math.random() * 0.08 + 0.02;
                snowflake.scale.set(size, size, size);
                
                // Add to scene and array
                scene.add(snowflake);
                snowflakes.push({
                    mesh: snowflake,
                    speed: Math.random() * 0.03 + 0.01,
                    rotationSpeed: Math.random() * 0.05 - 0.025
                });
            }
            
            return snowflakes;
        }

        const snowflakes = createSnowflakes(200);

        // Lights
        function createLights() {
            // Main directional light (sun)
            const dirLight = new THREE.DirectionalLight(0xFFFFFF, 1);
            dirLight.position.set(5, 10, 7);
            dirLight.castShadow = true;
            scene.add(dirLight);

            // Ambient light
            const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
            scene.add(ambientLight);

            // Colored lights for Christmas atmosphere
            const coloredLight1 = new THREE.PointLight(0xFF0000, 0.5, 10);
            coloredLight1.position.set(3, 5, 3);
            scene.add(coloredLight1);

            const coloredLight2 = new THREE.PointLight(0x00FF00, 0.5, 10);
            coloredLight2.position.set(-3, 4, 3);
            scene.add(coloredLight2);

            const coloredLight3 = new THREE.PointLight(0xFFFF00, 0.5, 10);
            coloredLight3.position.set(0, 6, -3);
            scene.add(coloredLight3);
        }

        createLights();

        // Animation
        function animateSnowflakes() {
            snowflakes.forEach(snowflake => {
                // Move down
                snowflake.mesh.position.y -= snowflake.speed;
                
                // Rotate
                snowflake.mesh.rotation.x += snowflake.rotationSpeed;
                snowflake.mesh.rotation.y += snowflake.rotationSpeed;
                
                // Reset if fallen below ground
                if (snowflake.mesh.position.y < -1) {
                    snowflake.mesh.position.y = 20;
                    snowflake.mesh.position.x = (Math.random() - 0.5) * 50;
                    snowflake.mesh.position.z = (Math.random() - 0.5) * 50;
                }
            });
        }

        // Animate decorations
        function animateDecorations() {
            christmasTree.children.forEach(child => {
                if (child.material && child.material.emissive) {
                    // Pulsing effect for decorations
                    const time = Date.now() * 0.001;
                    const pulse = Math.sin(time * 3) * 0.2 + 0.8;
                    child.material.emissiveIntensity = pulse * 0.3;
                }
            });
        }

        // Main animation loop
        function animate() {
            requestAnimationFrame(animate);
            
            controls.update();
            animateSnowflakes();
            animateDecorations();
            
            // Rotate Santa slightly
            santa.rotation.y = Math.sin(Date.now() * 0.001) * 0.3;
            
            renderer.render(scene, camera);
        }

        // Handle window resize
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // Start animation
        animate();

        // Add some initial animation with GSAP
        gsap.from(christmasTree.scale, {
            x: 0.1,
            y: 0.1,
            z: 0.1,
            duration: 1.5,
            ease: "back.out(1.7)"
        });

        gsap.from(santa.position, {
            x: -10,
            duration: 2,
            delay: 0.5,
            ease: "power2.out"
        });

        gsap.from(snowflakes, {
            opacity: 0,
            duration: 2,
            stagger: 0.01
        });
    </script>
</body>
</html>
posted @ 2025-12-25 21:40  懒惰的星期六  阅读(6)  评论(0)    收藏  举报