HTML音乐圣诞树

写在前面

这是一个基于WebGL技术实现的3D圣诞树场景,融合了音乐可视化效果和粒子系统,营造出一个充满节日氛围的虚拟空间。通过Three.js引擎的强大渲染能力,结合着色器编程和音频分析技术,创造出一个可以与音乐互动的圣诞树森林。

系列文章

序号 目录
1 HTML满屏跳动的爱心
2 HTML五彩缤纷的爱心
3 HTML满屏漂浮爱心
4 HTML情人节爱心
5 HTML蓝色爱心射线
6 HTML跳动的爱心
7 HTML跳动的双爱心
8 HTML粒子爱心
9 HTML蓝色动态爱心
10 HTML橙色动态粒子爱心
11 HTML旋转爱心
12 HTML爱情树
13 HTML元素周期表
14 HTML飞舞的花瓣
15 HTML星空特效
16 HTML黑客帝国字母雨
17 HTML哆啦A梦
18 HTML流星雨
19 HTML沙漏爱心
20 HTML爱心字母雨
21 HTML爱心流星雨
22 HTML生日蛋糕
23 HTML流光爱心
24 HTML粉色爱心
25 HTML满屏飘字
26 HTML飞舞爱心
27 HTML音乐圣诞树
28 HTML星空圣诞树
29 HTML礼物圣诞树
30 HTML旋转圣诞树
31 HTML旋转相册①
32 HTML旋转相册②
33 HTML旋转相册③
34 HTML大雪纷飞①
35 HTML大雪纷飞②
36 HTML炫酷烟花①
37 HTML炫酷烟花②
38 HTML炫酷烟花③
39 HTML炫酷烟花④
40 HTML炫酷烟花⑤
41 HTML炫酷烟花⑥
42 HTML炫酷烟花⑦
43 HTML炫酷烟花⑧
44 HTML炫酷烟花⑨
45 HTML金色流星雨
敬请期待......

技术需求

  1. WebGL渲染引擎核心功能

    • Three.js框架集成:引入完整的Three.js库文件,提供3D场景渲染基础;加载EffectComposer、RenderPass等后期处理模块,实现高级视觉效果。
    • 场景管理:构建Scene对象作为容器,管理所有3D对象的层次结构;通过PerspectiveCamera设置透视投影,模拟人眼观察效果。
    • 渲染循环控制:使用requestAnimationFrame创建平滑动画循环,确保60FPS流畅体验;配合WebGLRenderer进行硬件加速渲染。
  2. 音频可视化处理机制

    • 音频分析器构建:集成AudioListener和AudioAnalyser对象,实时分析音频频谱数据;设置2048大小的FFT分析窗口,捕捉音乐细节变化。
    • 频谱数据映射:将音频频谱信息通过DataTexture传递给着色器,实现音乐节拍与视觉效果同步;通过纹理采样控制粒子大小和透明度变化。
  3. 粒子系统与着色器编程

    • 自定义着色器材质:编写vertexShader和fragmentShader程序,实现粒子的动态变换和颜色混合;利用attribute变量为每个粒子设置独立属性。
    • 缓冲几何体优化:使用BufferGeometry高效管理大量粒子数据;通过Float32BufferAttribute优化内存使用,提升渲染性能。
  4. 用户交互与界面设计

    • 文件上传处理:实现本地音频文件读取功能,支持多种音频格式;通过FileReader接口解析音频数据,提供个性化体验。
    • 界面响应式布局:构建HTML界面元素,提供音乐选择和上传功能;使用CSS样式美化界面,确保跨设备兼容性。
  5. 后期处理与视觉增强

    • 泛光效果实现:集成UnrealBloomPass后期处理通道,营造梦幻光晕效果;通过参数调节控制辉光强度和范围。
    • 抗锯齿优化:启用WebGL抗锯齿功能,提升画面质量;使用EffectComposer管理多个渲染通道,实现复合视觉效果。

主要代码

创作不易,订阅后可查看完整代码

html 复制代码
<!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)));
 
......

创作流程

当我开始构思这个圣诞树项目时,脑海中浮现的是一个充满魔法和温暖的冬日场景。我希望创造出一个不仅视觉上令人惊叹,还能与音乐产生共鸣的3D体验。整个创作过程就像是在构建一个虚拟的圣诞世界,每一个元素都承载着我对节日氛围的理解和想象。

首先,我需要确定整体的视觉风格和色彩搭配。我选择了深邃的暗色调作为背景,这样可以让圣诞树的光芒更加突出。金色、绿色和白色的组合让我联想到传统的圣诞装饰,而淡蓝色的点缀则增添了一丝冬日的清冷感。这种色彩方案既要营造节日气氛,又要确保视觉上的和谐统一。

接下来,我开始思考如何构建圣诞树的基本形状。我意识到使用粒子系统是最佳选择,因为它可以创造出轻盈、闪烁的效果,就像真正的圣诞灯饰一样。我设计了一个数学函数来生成树的轮廓,通过极坐标变换创造出螺旋上升的枝条效果。每棵树由数千个粒子组成,这些粒子按照特定的规律分布在空间中,形成逼真的树形结构。

为了让场景更加生动,我决定添加飘落的雪花效果。雪花同样使用粒子系统实现,但它们具有不同的运动轨迹和速度。我为每片雪花设置了随机的相位和振幅,让它们在空中以自然的方式飘舞。不同形状的雪花纹理增加了视觉层次,营造出真实的雪景氛围。

地面的设计也不能忽视。我创建了一个粒子平面,散布着各种颜色的光点,模拟雪地反射的光芒。这些光点随着音乐节拍闪烁,与空中的圣诞树形成呼应,构建出完整的场景层次。

音频可视化是这个项目的核心亮点。我需要将音乐的频谱数据实时映射到视觉元素上。通过分析音频的频率分布,我可以控制圣诞树粒子的大小、亮度和颜色变化。当音乐节奏强烈时,圣诞树会变得更加明亮和动态;而在柔和的旋律中,它则显得宁静而优雅。

用户交互体验是我关注的重点之一。我设计了一个简洁直观的界面,让用户可以选择预设音乐或上传自己的音频文件。加载过程中的动画提示增强了用户体验,让用户感受到即将到来的视觉盛宴。

后期处理效果的添加让整个场景更加梦幻。我集成了泛光效果,让光源产生柔和的光晕,营造出温暖的氛围。这种效果在暗色背景下特别突出,让圣诞树的光芒显得更加迷人。

在技术实现过程中,我特别注重性能优化。大量粒子的渲染对硬件要求很高,因此我使用了缓冲几何体和高效的着色器程序。通过合理管理内存和优化渲染循环,确保了流畅的动画效果。

测试阶段,我尝试了不同风格的音乐来验证可视化效果。从轻柔的圣诞颂歌到欢快的节日舞曲,每种音乐都能产生独特的视觉反馈。这种音乐与视觉的完美结合,让整个作品充满了生命力。

最终,当我看到满屏幕闪烁的圣诞树随着音乐节拍摇摆,雪花在空中优雅飞舞时,我知道这个项目成功地传达了我想要表达的节日温暖和魔法氛围。

写在后面

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

相关推荐
kyriewen3 小时前
Webpack vs Vite:一个是“老黄牛”,一个是“猎豹”,你选谁?
前端·webpack·vite
打小就很皮...3 小时前
html2canvas + jsPDF 生成 PDF 的踩坑与解决方案总结
前端·pdf
全栈前端老曹3 小时前
【前端地图】多地图平台适配方案——高德、百度、腾讯、Google Maps SDK 差异对比、封装统一地图接口
前端·javascript·百度·dubbo·wgs84·gcj-02·bd09
雾岛听风6913 小时前
JavaScript基础语法速查手册
开发语言·前端·javascript
遇见~未来4 小时前
第三篇_现代布局_从弹性到网格
前端·css3
前端那点事4 小时前
Vue前端SEO优化全攻略(实操落地版,新手也能上手)
前端·vue.js
Dxy12393102164 小时前
HTML 如何使用 SVG 画曲线
前端·算法·html
用户2367829801684 小时前
从零实现 GIF 制作工具:LZW 压缩与 Median Cut 色彩量化
前端·javascript
hahaha 1hhh4 小时前
中文乱码 ubuntu autodl
linux·运维·前端
棉猴4 小时前
Python海龟绘图之绘制文本
javascript·python·html·write·turtle·海龟绘图·输出文本