0


HTML圣诞树代码(动态音效)

🏆今日学习目标:
🍀HTML圣诞树代码
✅创作者:林在闪闪发光
⏰预计时间:5分钟
🎉个人主页:林在闪闪发光的个人主页

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">
 <title>圣诞树</title>

 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">

 <style>
     * {
         box-sizing: border-box;
     }


     body {
         margin: 0;
         height: 100vh;
         overflow: hidden;
         display: flex;
         align-items: center;
         justify-content: center;
         background: #161616;
         color: #c5a880;
         font-family: sans-serif;
     }


     label {
         display: inline-block;
         background-color: #161616;
         padding: 16px;
         border-radius: 0.3rem;
         cursor: pointer;
         margin-top: 1rem;
         width: 300px;
         border-radius: 10px;
         border: 1px solid #c5a880;
         text-align: center;
     }


     ul {
         list-style-type: none;
         padding: 0;
         margin: 0;
     }


     .btn {
         background-color: #161616;
         border-radius: 10px;
         color: #c5a880;
         border: 1px solid #c5a880;
         padding: 16px;
         width: 300px;
         margin-bottom: 16px;
         line-height: 1.5;
         cursor: pointer;
     }

     .separator {
         font-weight: bold;
         text-align: center;
         width: 300px;
         margin: 16px 0px;
         color: #a07676;
     }


     .title {
         color: #a07676;
         font-weight: bold;
         font-size: 1.25rem;
         margin-bottom: 16px;
     }


     .text-loading {
         font-size: 2rem;
     }
 </style>

 <script>
     window.console = window.console || function (t) { };
 </script>



 <script>
     if (document.location.search.match(/type=embed/gi)) {
         window.parent.postMessage("resize", "*");
     }
 </script>
</head> <body translate="no"> <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/EffectComposer.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/RenderPass.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/ShaderPass.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/CopyShader.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/LuminosityHighPassShader.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/UnrealBloomPass.js"></script>
 <div id="overlay">
     <ul>
         <li class="title">请选择音乐</li>
         <li>
             <button class="btn" id="btnA" type="button">
                 Snowflakes Falling Down by Simon Panrucker
             </button>
         </li>
         <li><button class="btn" id="btnB" type="button">This Christmas by Dott</button></li>
         <li><button class="btn" id="btnC" type="button">No room at the inn by TRG Banks</button></li>
         <li><button class="btn" id="btnD" type="button">Jingle Bell Swing by Mark Smeby</button></li>
         <li class="separator">或者</li>
         <li>
             <input type="file" id="upload" hidden />
             <label for="upload">Upload File</label>
         </li>
     </ul>
 </div>

 <script id="rendered-js">
     const { PI, sin, cos } = Math;
     const TAU = 2 * PI;

     const map = (value, sMin, sMax, dMin, dMax) => {
         return dMin + (value - sMin) / (sMax - sMin) * (dMax - dMin);
     };

     const range = (n, m = 0) =>
         Array(n).
             fill(m).
             map((i, j) => i + j);

     const rand = (max, min = 0) => min + Math.random() * (max - min);
     const randInt = (max, min = 0) => Math.floor(min + Math.random() * (max - min));
     const randChoise = arr => arr[randInt(arr.length)];
     const polar = (ang, r = 1) => [r * cos(ang), r * sin(ang)];

     let scene, camera, renderer, analyser;
     let step = 0;
     const uniforms = {
         time: { type: "f", value: 0.0 },
         step: { type: "f", value: 0.0 }
     };

     const params = {
         exposure: 1,
         bloomStrength: 0.9,
         bloomThreshold: 0,
         bloomRadius: 0.5
     };

     let composer;

     const fftSize = 2048;
     const totalPoints = 4000;

     const listener = new THREE.AudioListener();

     const audio = new THREE.Audio(listener);

     document.querySelector("input").addEventListener("change", uploadAudio, false);

     const buttons = document.querySelectorAll(".btn");
     buttons.forEach((button, index) =>
         button.addEventListener("click", () => loadAudio(index)));


     function init() {
         const overlay = document.getElementById("overlay");
         overlay.remove();

         scene = new THREE.Scene();
         renderer = new THREE.WebGLRenderer({ antialias: true });
         renderer.setPixelRatio(window.devicePixelRatio);
         renderer.setSize(window.innerWidth, window.innerHeight);
         document.body.appendChild(renderer.domElement);

         camera = new THREE.PerspectiveCamera(
             60,
             window.innerWidth / window.innerHeight,
             1,
             1000);

         camera.position.set(-0.09397456774197047, -2.5597086635726947, 24.420789670889008);
         camera.rotation.set(0.10443543723052419, -0.003827152981119352, 0.0004011488708739715);

         const format = renderer.capabilities.isWebGL2 ?
             THREE.RedFormat :
             THREE.LuminanceFormat;

         uniforms.tAudioData = {
             value: new THREE.DataTexture(analyser.data, fftSize / 2, 1, format)
         };


         addPlane(scene, uniforms, 3000);
         addSnow(scene, uniforms);

         range(10).map(i => {
             addTree(scene, uniforms, totalPoints, [20, 0, -20 * i]);
             addTree(scene, uniforms, totalPoints, [-20, 0, -20 * i]);
         });

         const renderScene = new THREE.RenderPass(scene, camera);

         const bloomPass = new THREE.UnrealBloomPass(
             new THREE.Vector2(window.innerWidth, window.innerHeight),
             1.5,
             0.4,
             0.85);

         bloomPass.threshold = params.bloomThreshold;
         bloomPass.strength = params.bloomStrength;
         bloomPass.radius = params.bloomRadius;

         composer = new THREE.EffectComposer(renderer);
         composer.addPass(renderScene);
         composer.addPass(bloomPass);

         addListners(camera, renderer, composer);
         animate();
     }

     function animate(time) {
         analyser.getFrequencyData();
         uniforms.tAudioData.value.needsUpdate = true;
         step = (step + 1) % 1000;
         uniforms.time.value = time;
         uniforms.step.value = step;
         composer.render();
         requestAnimationFrame(animate);
     }

     function loadAudio(i) {
         document.getElementById("overlay").innerHTML =
             '<div class="text-loading">正在下载音乐,请稍等...</div>';
         const files = [
             "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Simon_Panrucker/Happy_Christmas_You_Guys/Simon_Panrucker_-_01_-_Snowflakes_Falling_Down.mp3",
             "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Dott/This_Christmas/Dott_-_01_-_This_Christmas.mp3",
             "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/TRG_Banks/TRG_Banks_Christmas_Album/TRG_Banks_-_12_-_No_room_at_the_inn.mp3",
             "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/Mark_Smeby/En_attendant_Nol/Mark_Smeby_-_07_-_Jingle_Bell_Swing.mp3"];

         const file = files[i];

         const loader = new THREE.AudioLoader();
         loader.load(file, function (buffer) {
             audio.setBuffer(buffer);
             audio.play();
             analyser = new THREE.AudioAnalyser(audio, fftSize);
             init();
         });




     }


     function uploadAudio(event) {
         document.getElementById("overlay").innerHTML =
             '<div class="text-loading">请稍等...</div>';
         const files = event.target.files;
         const reader = new FileReader();

         reader.onload = function (file) {
             var arrayBuffer = file.target.result;

             listener.context.decodeAudioData(arrayBuffer, function (audioBuffer) {
                 audio.setBuffer(audioBuffer);
                 audio.play();
                 analyser = new THREE.AudioAnalyser(audio, fftSize);
                 init();
             });
         };

         reader.readAsArrayBuffer(files[0]);
     }

     function addTree(scene, uniforms, totalPoints, treePosition) {
         const vertexShader = `
   attribute float mIndex;
   varying vec3 vColor;
   varying float opacity;
   uniform sampler2D tAudioData;
   float norm(float value, float min, float max ){
    return (value - min) / (max - min);
   }
   float lerp(float norm, float min, float max){
    return (max - min) * norm + min;
   }
   float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
    return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
   }
   void main() {
    vColor = color;
    vec3 p = position;
    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
    float amplitude = texture2D( tAudioData, vec2( mIndex, 0.1 ) ).r;
    float amplitudeClamped = clamp(amplitude-0.4,0.0, 0.6 );
    float sizeMapped = map(amplitudeClamped, 0.0, 0.6, 1.0, 20.0);
    opacity = map(mvPosition.z , -200.0, 15.0, 0.0, 1.0);
    gl_PointSize = sizeMapped * ( 100.0 / -mvPosition.z );
    gl_Position = projectionMatrix * mvPosition;
   }
   `;
         const fragmentShader = `
   varying vec3 vColor;
   varying float opacity;
   uniform sampler2D pointTexture;
   void main() {
    gl_FragColor = vec4( vColor, opacity );
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); 
   }
   `;
         const shaderMaterial = new THREE.ShaderMaterial({
             uniforms: {
                 ...uniforms,
                 pointTexture: {
                     value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
                 }
             },


             vertexShader,
             fragmentShader,
             blending: THREE.AdditiveBlending,
             depthTest: false,
             transparent: true,
             vertexColors: true
         });


         const geometry = new THREE.BufferGeometry();
         const positions = [];
         const colors = [];
         const sizes = [];
         const phases = [];
         const mIndexs = [];

         const color = new THREE.Color();

         for (let i = 0; i < totalPoints; i++) {
             const t = Math.random();
             const y = map(t, 0, 1, -8, 10);
             const ang = map(t, 0, 1, 0, 6 * TAU) + TAU / 2 * (i % 2);
             const [z, x] = polar(ang, map(t, 0, 1, 5, 0));

             const modifier = map(t, 0, 1, 1, 0);
             positions.push(x + rand(-0.3 * modifier, 0.3 * modifier));
             positions.push(y + rand(-0.3 * modifier, 0.3 * modifier));
             positions.push(z + rand(-0.3 * modifier, 0.3 * modifier));

             color.setHSL(map(i, 0, totalPoints, 1.0, 0.0), 1.0, 0.5);

             colors.push(color.r, color.g, color.b);
             phases.push(rand(1000));
             sizes.push(1);
             const mIndex = map(i, 0, totalPoints, 1.0, 0.0);
             mIndexs.push(mIndex);
         }

         geometry.setAttribute(
             "position",
             new THREE.Float32BufferAttribute(positions, 3).setUsage(
                 THREE.DynamicDrawUsage));


         geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
         geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
         geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
         geometry.setAttribute("mIndex", new THREE.Float32BufferAttribute(mIndexs, 1));

         const tree = new THREE.Points(geometry, shaderMaterial);

         const [px, py, pz] = treePosition;

         tree.position.x = px;
         tree.position.y = py;
         tree.position.z = pz;

         scene.add(tree);
     }

     function addSnow(scene, uniforms) {
         const vertexShader = `
   attribute float size;
   attribute float phase;
   attribute float phaseSecondary;
   varying vec3 vColor;
   varying float opacity;
   uniform float time;
   uniform float step;
   float norm(float value, float min, float max ){
    return (value - min) / (max - min);
   }
   float lerp(float norm, float min, float max){
    return (max - min) * norm + min;
   }
   float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
    return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
   }
   void main() {
    float t = time* 0.0006;
    vColor = color;
    vec3 p = position;
    p.y = map(mod(phase+step, 1000.0), 0.0, 1000.0, 25.0, -8.0);
    p.x += sin(t+phase);
    p.z += sin(t+phaseSecondary);
    opacity = map(p.z, -150.0, 15.0, 0.0, 1.0);
    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
    gl_PointSize = size * ( 100.0 / -mvPosition.z );
    gl_Position = projectionMatrix * mvPosition;
   }
   `;

         const fragmentShader = `
   uniform sampler2D pointTexture;
   varying vec3 vColor;
   varying float opacity;
   void main() {
    gl_FragColor = vec4( vColor, opacity );
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); 
   }
   `;
         function createSnowSet(sprite) {
             const totalPoints = 300;
             const shaderMaterial = new THREE.ShaderMaterial({
                 uniforms: {
                     ...uniforms,
                     pointTexture: {
                         value: new THREE.TextureLoader().load(sprite)
                     }
                 },


                 vertexShader,
                 fragmentShader,
                 blending: THREE.AdditiveBlending,
                 depthTest: false,
                 transparent: true,
                 vertexColors: true
             });


             const geometry = new THREE.BufferGeometry();
             const positions = [];
             const colors = [];
             const sizes = [];
             const phases = [];
             const phaseSecondaries = [];

             const color = new THREE.Color();

             for (let i = 0; i < totalPoints; i++) {
                 const [x, y, z] = [rand(25, -25), 0, rand(15, -150)];
                 positions.push(x);
                 positions.push(y);
                 positions.push(z);

                 color.set(randChoise(["#f1d4d4", "#f1f6f9", "#eeeeee", "#f1f1e8"]));

                 colors.push(color.r, color.g, color.b);
                 phases.push(rand(1000));
                 phaseSecondaries.push(rand(1000));
                 sizes.push(rand(4, 2));
             }

             geometry.setAttribute(
                 "position",
                 new THREE.Float32BufferAttribute(positions, 3));

             geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
             geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
             geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
             geometry.setAttribute(
                 "phaseSecondary",
                 new THREE.Float32BufferAttribute(phaseSecondaries, 1));


             const mesh = new THREE.Points(geometry, shaderMaterial);

             scene.add(mesh);
         }
         const sprites = [
             "https://assets.codepen.io/3685267/snowflake1.png",
             "https://assets.codepen.io/3685267/snowflake2.png",
             "https://assets.codepen.io/3685267/snowflake3.png",
             "https://assets.codepen.io/3685267/snowflake4.png",
             "https://assets.codepen.io/3685267/snowflake5.png"];

         sprites.forEach(sprite => {
             createSnowSet(sprite);
         });
     }

     function addPlane(scene, uniforms, totalPoints) {
         const vertexShader = `
   attribute float size;
   attribute vec3 customColor;
   varying vec3 vColor;
   void main() {
    vColor = customColor;
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_PointSize = size * ( 300.0 / -mvPosition.z );
    gl_Position = projectionMatrix * mvPosition;
   }
   `;
         const fragmentShader = `
   uniform vec3 color;
   uniform sampler2D pointTexture;
   varying vec3 vColor;
   void main() {
    gl_FragColor = vec4( vColor, 1.0 );
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
   }
   `;
         const shaderMaterial = new THREE.ShaderMaterial({
             uniforms: {
                 ...uniforms,
                 pointTexture: {
                     value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
                 }
             },


             vertexShader,
             fragmentShader,
             blending: THREE.AdditiveBlending,
             depthTest: false,
             transparent: true,
             vertexColors: true
         });


         const geometry = new THREE.BufferGeometry();
         const positions = [];
         const colors = [];
         const sizes = [];

         const color = new THREE.Color();

         for (let i = 0; i < totalPoints; i++) {
             const [x, y, z] = [rand(-25, 25), 0, rand(-150, 15)];
             positions.push(x);
             positions.push(y);
             positions.push(z);

             color.set(randChoise(["#93abd3", "#f2f4c0", "#9ddfd3"]));

             colors.push(color.r, color.g, color.b);
             sizes.push(1);
         }

         geometry.setAttribute(
             "position",
             new THREE.Float32BufferAttribute(positions, 3).setUsage(
                 THREE.DynamicDrawUsage));


         geometry.setAttribute(
             "customColor",
             new THREE.Float32BufferAttribute(colors, 3));

         geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));

         const plane = new THREE.Points(geometry, shaderMaterial);

         plane.position.y = -8;
         scene.add(plane);
     }

     function addListners(camera, renderer, composer) {
         document.addEventListener("keydown", e => {
             const { x, y, z } = camera.position;
             console.log(`camera.position.set(${x},${y},${z})`);
             const { x: a, y: b, z: c } = camera.rotation;
             console.log(`camera.rotation.set(${a},${b},${c})`);
         });

         window.addEventListener(
             "resize",
             () => {
                 const width = window.innerWidth;
                 const height = window.innerHeight;

                 camera.aspect = width / height;
                 camera.updateProjectionMatrix();

                 renderer.setSize(width, height);
                 composer.setSize(width, height);
             },
             false);

     }
 </script>
</body> </html>
标签: html css 前端

本文转载自: https://blog.csdn.net/weixin_68829137/article/details/128257945
版权归原作者 林在闪闪发光 所有, 如有侵权,请联系我们删除。

“HTML圣诞树代码(动态音效)”的评论:

还没有评论