HTML音乐圣诞树

图片

目录

写在前面

完整代码

代码分析

系列文章

写在最后


写在前面

圣诞节(Christmas)亦称耶稣圣诞节、主降生节,天主教亦称耶稣圣诞瞻礼。译名为“基督弥撒”,它源自古罗马人迎接新年的农神节,与基督教本无关系。在基督教盛行罗马帝国后,教廷随波逐流地将这种民俗节日纳入基督教体系,同时以庆祝耶稣的降生。本文主要分享火爆全网的html圣诞树,一起来看看吧~

HTML是HyperText Markup Language的缩写,是一种用于创建网页的标记语言。HTML是一个Web设计和开发的基本技能,它包含了一些标签和元素,用于描述网页的结构和内容。HTML通过将标签放置在文本中,来定义文档的结构和显示。这些标签可以用于添加标题,段落,列表,表格,超链接等元素,以及其他的多媒体内容。

HTML的设计是为了创建静态和动态网页,以及Web应用程序。HTML结构包括文本,链接,图像,音频和视频等元素,理论上可以支持任何类型的媒体。这使得HTML成为一种灵活而强大的Web开发工具。

在Web开发中,HTML通常与CSS和JavaScript一起使用。CSS用于控制网页的样式和布局,JavaScript用于添加交互和动态效果。HTML、CSS和JavaScript共同构成了现代网页的三大基石。

HTML语言的基本语法很简单,学习起来也比较容易。HTML标记通常由一对左右尖括号和标记名称组成,例如:`<html>`。有些标记包含属性,例如:`<img src="image.jpg" alt="A beautiful image">`。属性值通常用引号括起来。标记也可以嵌套在其他标记中,例如:`<p><strong>Hello</strong> World!</p>`

以下是HTML入门的基本步骤:

1. 打开一个文本编辑器,例如Notepad或Sublime Text等。

2. 新建一个文件,并将其保存为.html文件扩展名。

3. 使用HTML标签包围文本以描述文档的内容和结构。标签是由尖括号包围的单词或单词组。

4. 使用属性来描述标签的内容。属性是将键值对应用于标签的元数据。

5. 使用CSS(层叠样式表)来定义网页的样式和布局。

6. 保存文件,并在浏览器中打开该文件以查看效果。

完整代码

<!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/three@0.115.0/build/three.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/EffectComposer.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/RenderPass.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/ShaderPass.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/CopyShader.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/LuminosityHighPassShader.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/UnrealBloomPass.js"></script>

  <div id="overlay">
    <ul>
      <li class="title">请选择音乐</li>
      <li><button class="btn" id="btnA" type="button">Music1</button></li>
      <li><button class="btn" id="btnB" type="button">Music2</button></li>
      <li><button class="btn" id="btnC" type="button">Music3</button></li>
      <li><button class="btn" id="btnD" type="button">Music4</button></li>
      <li class="separator">或者</li>
      <li>
        <input type="file" id="upload" hidden />
        <label for="upload">本地音乐</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文件,用于呈现一个音乐圣诞灯的页面。以下是对该页面中不同部分的简要分析:

1. CSS样式:

   - `normalize.min.css`:这是一个第三方CSS文件,用于重置浏览器默认样式,确保在不同浏览器中具有一致的外观。- `body`样式:设置了页面的一些基本样式,如页面居中、背景颜色、字体颜色等。- `label`样式:将元素设置为可点击的标签,并设置了一些基本的样式,如背景颜色、边框、内边距等。

   - `ul`样式:将无序列表设置为没有样式(去掉了默认的圆点)。

   - `.btn`样式:设置了按钮的样式,如背景颜色、边框、内边距等。

   - `.separator`样式:设置了分隔符的样式,如字体加粗、文本居中、颜色等。

   - `.title`样式:设置了标题的样式,如颜色、字体加粗、字体大小等。

   - `.text-loading`样式:设置了正在加载文本的样式,如字体大小等。

2. JavaScript代码:

   - 第一个脚本用于确保控制台对象可用。

  - 第二个脚本用于检测URL中是否包含"type=embed"参数,并通过`postMessage()`向父窗口发送消息,以实现页面的调整。

3. HTML内容:

   - `<!DOCTYPE html>`:定义了文档类型。

   - `<html>`:指定了HTML文档的语言为英语。

   - `<head>`:包含了一些元标记(meta)和外部资源引用。

   - `<meta charset="UTF-8">`:指定了文档的字符编码为UTF-8。

   - `<title>`:设置了页面的标题为"Musical Christmas Lights"。

   - `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">`:引用了一个外部CSS文件。

   - `<style>`:内联样式表,定义了页面的样式。

   - `<script>`:JavaScript脚本标签,用于添加一些功能。

   - `<body>`:HTML文档的主体部分,包含了页面的实际内容。

   - `<label>`:表示一个可点击的标签。

   - `<ul>`:定义了一个无序列表。

   - `.btn`:表示一个样式为"btn"的按钮。

   - `.separator`:表示一个具有"separator"样式的分隔符。

   - `.title`:表示一个具有"title"样式的标题。

   - `.text-loading`:表示一个具有"text-loading"样式的文本。

系列文章

序号目录
1HTML满屏跳动的爱心(可写字)
2HTML五彩缤纷的爱心
3HTML满屏漂浮爱心
4HTML情人节快乐
5HTML蓝色爱心射线
6HTML跳动的爱心(简易版)
7HTML粒子爱心
8HTML蓝色动态爱心
9HTML跳动的爱心(双心版)
10HTML橙色动态粒子爱心
11HTML旋转爱心
12HTML爱情树
13HTML3D相册
14HTML旋转相册
15HTML基础烟花秀
16HTML炫酷烟花秀
17HTML粉色烟花秀
18HTML新春烟花
19HTML龙年大吉
20HTML圣诞树
21HTML大雪纷飞
22HTML想见你
23HTML元素周期表
24HTML飞舞的花瓣
25HTML星空特效
26HTML黑客帝国字母雨
27HTML哆啦A梦
28HTML流星雨
29HTML沙漏爱心
30HTML爱心字母雨
31HTML爱心流星雨

写在最后

我是一只有趣的兔子,感谢你的喜欢! 

  • 49
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Want595

感谢小伙伴的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值