背景
最近QQ音乐推出了个音乐播放的3d效果的功能,体验了下做的挺好的,但是我也发现其适合用来听慢歌,安静,抒情性的歌曲,不能实时反应音频数据的声调,没有感情色彩.
对于我这种喜欢DJ和摇滚且酷爱动感单车的用户,还是觉得不够带感,于是就决定写个自己专属的播放的音乐盒子效果
在线体验
music-3d - 码上掘金 (juejin.cn)
代码仓库地址
使用方式
左上角点击上传你的MP3文件即可,系统会自动的读取文件信息,并生成对应的音乐可视化效果,因为版权和一些法律等原因没有去从各大音乐平台拉取歌曲列表和资源请谅解
核心工具和技术
- glicon 一个根据SVG图标自动生成3d模型的网站,具体使用方法请参考 glicon 教程
- Three.js – JavaScript 3D Library (threejs.org)
准备素材
整个模型的制作非常简单,没有用到各种建模工具,直接把原始的SVG文件上传到glicon即可,然后调整模型的厚度,背景,边框等信息,调整好模型的效果后下载模型文件即可.
你可以把这些SVG代码保存成文件在glicon里亲自体验
完整的数据在仓库里 deyihu/music-3d (github.com)
手机模型
<svg xmlns="http://www.w3.org/2000/svg" class="icon" style="width: 128px; height: 128px; vertical-align: middle; fill: currentcolor; overflow: hidden;" viewBox="0 0 1024 1024" version="1.1"><path d="M669 961.1H355.2c-33.6 0-60.9-27.3-60.9-60.9V126c0-33.6 27.3-60.9 60.9-60.9H669c33.6 0 60.9 27.3 60.9 60.9v774.2c0 33.6-27.2 60.9-60.9 60.9z" fill="#E5ECFF"/><path d="M323 172h378.1v682.3H323z" fill="#5B79FB"/><path d="M512.1 903.6m-32.9 0a32.9 32.9 0 1 0 65.8 0 32.9 32.9 0 1 0-65.8 0Z" fill="#5B79FB"/><path d="M512.1 903.6m-29.1 0a29.1 29.1 0 1 0 58.2 0 29.1 29.1 0 1 0-58.2 0Z" fill="#E5ECFF"/><path d="M565 120.6h-73c-0.3 0-0.5-0.2-0.5-0.5v-7.2c0-0.3 0.2-0.5 0.5-0.5h73c0.3 0 0.5 0.2 0.5 0.5v7.2c0 0.3-0.2 0.5-0.5 0.5z" fill="#A4BEFF"/><path d="M466.9 116.5m-8.2 0a8.2 8.2 0 1 0 16.4 0 8.2 8.2 0 1 0-16.4 0Z" fill="#A4BEFF"/></svg>
QQ音乐LOGO
<svg xmlns="http://www.w3.org/2000/svg" class="icon" style="width: 128px; height: 128px; vertical-align: middle; fill: currentcolor; overflow: hidden;" viewBox="0 0 1024 1024" version="1.1"><path d="M684.94222222 586.752c-9.10222222-2.84444445-18.20444445-5.68888889-25.14488889-7.73688889-19.34222222 1.93422222-37.66044445 5.00622222-55.97866666 5.12-28.78577778 0.22755555-53.93066667-21.504-56.88888889-50.176-2.16177778-20.02488889-2.61688889-40.84622222 0.68266667-60.52977778 2.048-11.94666667 10.46755555-25.03111111 19.79733333-33.22311111 24.46222222-21.61777778 53.93066667-21.04888889 82.14755555-8.87466667 26.51022222 11.49155555 36.63644445 34.58844445 35.04355556 62.91911112-1.13777778 21.504 3.41333333 43.80444445-10.01244444 63.37422222-1.25155555 1.70666667 0.56888889 6.37155555 2.048 8.98844444 3.18577778 5.46133333 7.05422222 10.35377778 10.6951111 15.58755556-0.91022222 1.59288889-1.70666667 3.072-2.38933333 4.55111111z m-23.552-44.37333333c5.57511111-24.23466667 6.71288889-48.01422222 1.82044445-71.90755556-0.34133333-1.82044445-1.47911111-3.64088889-2.50311112-5.34755556-12.97066667-22.30044445-50.63111111-30.72-75.09333333-16.61155555-13.312 7.62311111-21.16266667 19.00088889-21.504 34.816-0.22755555 11.37777778 0.34133333 22.75555555-0.34133333 34.13333333-1.25155555 19.68355555 5.34755555 36.06755555 23.43822222 44.14577778 19.79733333 8.87466667 40.50488889 8.41955555 61.09866667-2.95822222-8.76088889-12.40177778-16.49777778-23.43822222-24.46222223-34.58844444 20.36622222-8.192 27.19288889 6.82666667 37.54666667 18.31822222zM525.19822222 586.29688889c-9.32977778-2.73066667-18.77333333-5.57511111-32.19911111-9.55733334-17.97688889 10.01244445-42.32533333 11.49155555-66.56 3.98222223-24.23466667-7.62311111-38.34311111-25.37244445-40.84622222-51.08622223-1.024-11.264 0.11377778-22.75555555-0.68266667-34.01955555-3.64088889-50.28977778 34.36088889-79.41688889 86.81244445-70.31466667 31.63022222 5.46133333 51.08622222 27.07911111 51.76888888 59.16444445 0.56888889 24.23466667 5.23377778 49.60711111-9.10222222 72.36266667-1.36533333 2.16177778 0.56888889 7.28177778 2.27555556 10.35377777 2.95822222 5.46133333 6.94044445 10.35377778 10.58133333 15.47377778-0.68266667 1.13777778-1.36533333 2.38933333-2.048 3.64088889z m-25.82755555-44.032c2.048-0.22755555 3.98222222-0.56888889 6.03022222-0.79644444 0-17.52177778 0.11377778-35.04355555 0-52.56533334-0.22755555-22.75555555-10.58133333-38.22933333-29.58222222-44.25955556-24.68977778-7.85066667-51.99644445-2.048-63.488 15.01866667-4.66488889 6.94044445-7.62311111 16.04266667-8.53333334 24.46222223-1.47911111 12.62933333-0.34133333 25.6-0.45511111 38.45688888-0.11377778 19.456 9.10222222 33.792 26.85155556 40.16355556 19.11466667 6.82666667 38.79822222 7.168 57.344-4.55111111-8.53333333-12.62933333-16.04266667-23.552-23.32444445-34.36088889 20.82133333-9.10222222 25.82755555 8.53333333 35.15733334 18.432zM944.128 498.00533333v-38.11555555c13.42577778-2.84444445 18.88711111 1.47911111 17.63555555 14.10844444-0.68266667 7.28177778-0.11377778 14.79111111-0.11377777 23.66577778h51.65511111v15.13244445h-52.33777778v71.33866666c-30.26488889 5.12-35.38488889 3.18577778-36.52266666-13.312 5.80266667-0.45511111 11.49155555-1.024 18.54577777-1.59288889v-56.32c-15.36 0-30.49244445-0.45511111-45.62488889 0.11377778-11.264 0.45511111-16.61155555-3.072-15.24622222-15.36 2.27555555-21.16266667 3.75466667-42.32533333 5.80266667-65.76355555h118.44266667v13.42577777h-99.66933334c-1.47911111 16.384-3.18577778 30.37866667-3.75466666 44.48711111-0.11377778 2.61688889 4.66488889 7.50933333 7.50933333 7.73688889 10.69511111 1.024 21.504 0.45511111 33.67822222 0.45511111zM721.92 584.13511111v-77.25511111c38.22933333 0 75.66222222-0.22755555 113.09511111 0.45511111 3.41333333 0.11377778 9.55733333 6.25777778 9.67111111 9.78488889 0.91022222 22.07288889 0.45511111 44.14577778 0.45511111 67.01511111H721.92z m18.31822222-46.30755556h86.35733333c-0.45511111-5.68888889-0.68266667-10.24-1.13777777-15.24622222h-85.21955556v15.24622222z m-0.68266667 16.83911112c0.45511111 5.68888889 0.68266667 9.89866667 1.024 14.336h85.78844445c-0.22755555-5.34755555-0.45511111-9.78488889-0.79644445-14.336H739.55555555zM741.48977778 481.16622222c-3.18577778-8.64711111-5.23377778-14.10844445-7.50933333-20.36622222 10.24-2.73066667 18.54577778-3.18577778 21.73155555 9.32977778 2.16177778 8.53333333 7.73688889 11.49155555 16.49777778 10.80888889 7.85066667-0.68266667 16.04266667 0.91022222 23.66577777-0.56888889 5.23377778-1.024 12.288-4.66488889 13.8808889-8.98844445 4.32355555-11.03644445 10.80888889-14.336 22.64177777-10.35377778-2.048 5.80266667-4.096 11.49155555-6.82666667 19.22844445h34.816c0.56888889 5.91644445 0.91022222 10.01244445 1.36533334 15.24622222H705.42222222V481.28c11.49155555-0.11377778 22.64177778-0.11377778 36.06755556-0.11377778zM713.84177778 452.83555555v-15.8151111H771.41333333v-14.44977778c7.96444445 2.27555555 18.88711111 2.61688889 20.13866667 6.25777778 3.41333333 9.67111111 9.78488889 8.07822222 16.384 8.192 14.22222222 0.11377778 28.55822222 0 43.34933333 0 2.048 8.41955555 5.34755555 15.81511111-7.39555555 15.8151111H713.84177778z" fill="#fff"/><path d="M874.83733333 580.608c7.39555555-17.18044445 12.74311111-29.80977778 18.09066667-42.32533333 5.80266667-13.42577778 5.80266667-13.42577778 24.34844445-10.58133334-6.82666667 15.92888889-12.62933333 31.97155555-20.70755556 46.64888889-2.27555555 3.86844445-11.83288889 3.64088889-21.73155556 6.25777778zM981.44711111 527.70133333c12.62933333-3.41333333 20.59377778-1.13777778 24.80355556 11.49155556 4.32355555 12.97066667 10.35377778 25.25866667 15.58755555 37.77422222-14.56355555 5.12-21.73155555-0.56888889-25.94133333-13.65333333-3.75466667-12.06044445-9.32977778-23.43822222-14.44977778-35.61244445z" fill="#fff"/><path d="M234.72355555 350.89066667s-0.22755555 0.11377778-0.4551111 0.34133333c0.22755555-0.11377778 0.45511111-0.34133333 0.4551111-0.34133333z" fill="#fff"/><path d="M239.38844445 379.33511111l-4.6648889-28.44444444s-3.072 28.78577778-36.97777777 59.61955555c-15.58755555 14.22222222-43.12177778 29.80977778-43.12177778 29.80977778l64.73955555 112.07111111s6.144 18.54577778-2.048 35.95377778c-9.55733333 20.36622222-28.78577778 32.88177778-65.76355555 33.90577778-32.88177778 0.91022222-55.52355555-18.54577778-59.61955555-45.16977778-4.096-26.39644445 13.08444445-46.76266667 32.88177777-54.49955556 18.54577778-7.168 49.37955555-4.096 49.37955556-4.096l-71.90755556-121.28711111 1.024-12.288s23.09688889 2.95822222 63.71555556-5.12c18.54577778-3.75466667 34.13333333-9.89866667 45.73866667-15.58755555-17.74933333-7.73688889-37.43288889-12.06044445-58.02666667-12.06044445-79.98577778 0-144.95288889 64.85333333-144.95288889 144.95288889 0 79.98577778 64.85333333 144.95288889 144.95288889 144.95288889 79.98577778 0 144.95288889-64.85333333 144.95288889-144.95288889-0.22755555-48.58311111-23.89333333-91.36355555-60.30222222-117.76z" fill="#FFDC00"/><path d="M234.72355555 350.89066667s-26.73777778 20.59377778-67.81155555 28.78577778c-40.61866667 8.07822222-63.71555555 5.12-63.71555555 5.12l-1.024 12.288L174.08 518.48533333s-30.83377778-3.072-49.37955555 4.096c-19.79733333 7.62311111-36.97777778 28.10311111-32.88177778 54.49955556 4.096 26.73777778 26.73777778 46.08 59.61955555 45.16977778 36.97777778-1.024 56.20622222-13.53955555 65.76355556-33.90577778 8.192-17.52177778 2.048-35.95377778 2.048-35.95377778L154.51022222 440.32s27.53422222-15.58755555 43.12177778-29.80977778c34.01955555-30.83377778 37.09155555-59.61955555 37.09155555-59.61955555z" fill="#0AC094"/></svg>
CD磁盘模型
<svg xmlns="http://www.w3.org/2000/svg" class="icon" style="width: 128px; height: 128px; vertical-align: middle; fill: currentcolor; overflow: hidden;" viewBox="0 0 1024 1024" version="1.1"><path d="M983.612496 312.49932a512.038921 512.038921 0 1 0-834.395873 560.843838c0.282109 0.282109 0.606013 0.55377 0.888123 0.888122a512.038921 512.038921 0 0 0 833.50775-561.533439m-221.936471-50.152773a353.159114 353.159114 0 1 1-499.229067-0.229867 353.754678 353.754678 0 0 1 384.807604-76.806883 347.057193 347.057193 0 0 1 114.411014 76.806883z" fill="#fff"/><path d="M871.468805 362.725233A393.02012 393.02012 0 0 0 660.639083 152.073135a389.519874 389.519874 0 1 0 210.317745 510.314919 393.584339 393.584339 0 0 0 0.616462-299.662821m-96.805302-113.88859a370.754378 370.754378 0 0 1 1.18068 524.263659l-1.18068 1.18068a371.621603 371.621603 0 1 1-525.653309-525.444339 376.856299 376.856299 0 0 1 120.701009-80.453408 371.548464 371.548464 0 0 1 405.056785 80.662378M511.946558 357.647264a153.833184 153.833184 0 0 0-0.511976 307.666369h0.511976a153.007753 153.007753 0 0 0 153.822736-152.443535v-1.285164a153.822736 153.822736 0 0 0-153.822736-153.833185m-96.700816 57.46672a136.175229 136.175229 0 0 1 192.534407-0.303006l0.303007 0.303006a136.206574 136.206574 0 0 1 0.355249 192.597099l-0.355249 0.303006a136.122986 136.122986 0 0 1-192.534408 0.355249l-0.303006-0.355249a136.154332 136.154332 0 0 1-0.355249-192.544856l0.355249-0.355249m153.822735 96.450053a80.662377 80.662377 0 1 0-0.156727 0.564218v-0.355249m-17.480331 0a37.896689 37.896689 0 0 1-11.284374 28.210936 39.787867 39.787867 0 0 1-56.421871 0 37.896689 37.896689 0 0 1-11.284374-28.210936 39.484861 39.484861 0 1 1 78.959273-0.208969z"/><path d="M855.461711 369.589894a367.327272 367.327272 0 0 0-80.64148-120.439796 371.339494 371.339494 0 1 0 80.64148 120.439796m-78.959273 31.02158a8.567765 8.567765 0 0 1-4.670477 11.127646h-0.407491l-3.134548 0.564219a8.202068 8.202068 0 0 1-8.149826-5.642187 250.325031 250.325031 0 0 0-56.42187-86.597122 254.295459 254.295459 0 0 0-86.900129-56.808465 7.313946 7.313946 0 0 1-4.51375-4.179398 9.079742 9.079742 0 0 1 0-6.770624 8.620008 8.620008 0 0 1 4.51375-4.51375 9.591718 9.591718 0 0 1 6.770625-0.303006 277.104522 277.104522 0 0 1 92.281103 60.350504 267.648635 267.648635 0 0 1 60.904274 92.803528m48.501912 1.38965a7.899062 7.899062 0 0 1-8.202069-5.642187 301.846557 301.846557 0 0 0-73.317085-115.873804 307.10215 307.10215 0 0 0-115.863356-73.317086 9.842482 9.842482 0 0 1-4.816756-4.513749 9.330506 9.330506 0 0 1-0.261212-6.770625 7.585607 7.585607 0 0 1 4.179398-4.816756 7.846819 7.846819 0 0 1 6.770624 0 327.319987 327.319987 0 0 1 199.566245 199.399069 8.160274 8.160274 0 0 1-0.303007 6.206406 10.866434 10.866434 0 0 1-5.13021 4.764513l-2.737506 0.564219m-422.119177 1.431444a153.133135 153.133135 0 0 1 216.565945-1.04485l1.04485 1.04485a153.812287 153.812287 0 1 1-217.997389 0.303006l0.303006-0.303006m204.790492-106.574644a8.202068 8.202068 0 0 1 6.770624 0 223.994825 223.994825 0 0 1 66.650947 46.151 219.146723 219.146723 0 0 1 45.680817 66.661395 8.923014 8.923014 0 0 1 0 6.509412 9.894724 9.894724 0 0 1-4.816755 5.130211 4.764513 4.764513 0 0 1-3.071858 0.825431 7.846819 7.846819 0 0 1-7.899062-5.642187 217.328685 217.328685 0 0 0-42.295505-61.165487 202.199265 202.199265 0 0 0-61.520736-42.295506 7.533365 7.533365 0 0 1-4.513749-4.816756 8.202068 8.202068 0 0 1 0-6.770624 7.585607 7.585607 0 0 1 4.764513-4.51375M297.324033 614.502604a8.661802 8.661802 0 0 1 4.816756-11.284374 8.557317 8.557317 0 0 1 6.457169 0 8.818529 8.818529 0 0 1 5.130211 4.51375 201.102173 201.102173 0 0 0 42.044742 61.531184 208.050422 208.050422 0 0 0 61.520735 42.044742 8.714044 8.714044 0 0 1 4.764514 4.764513 9.079742 9.079742 0 0 1 0 6.770625 8.358796 8.358796 0 0 1-8.149826 5.13021 6.969146 6.969146 0 0 1-3.385312-0.564218 223.691818 223.691818 0 0 1-112.84374-112.843741m-45.1166-1.94342a10.918677 10.918677 0 0 1 6.770625 0 8.870772 8.870772 0 0 1 4.816756 4.51375 254.201422 254.201422 0 0 0 143.248859 143.823526 7.846819 7.846819 0 0 1 5.130211 4.179398 8.609559 8.609559 0 0 1 0 6.770625 7.439328 7.439328 0 0 1-7.899062 5.642187 5.130211 5.130211 0 0 1-3.134548-0.564219 263.678207 263.678207 0 0 1-92.699043-61.374457 267.230695 267.230695 0 0 1-60.601268-92.291551 8.620008 8.620008 0 0 1 0-6.770625 7.637849 7.637849 0 0 1 4.513749-4.179398m-49.316894 10.720156a7.690092 7.690092 0 0 1 4.51375 4.764513 310.320286 310.320286 0 0 0 188.072901 189.713314 9.946967 9.946967 0 0 1 5.13021 4.51375 9.64396 9.64396 0 0 1 0.303007 6.770625 8.661802 8.661802 0 0 1-8.463281 5.642187h-2.821093a330.90382 330.90382 0 0 1-199.639384-199.963288 8.463281 8.463281 0 0 1 0.564218-6.770624 7.742334 7.742334 0 0 1 5.130211-4.179398 7.125873 7.125873 0 0 1 6.206406 0.261212z" fill="#E3B814"/><path d="M206.91321 628.022956a7.690092 7.690092 0 0 0-4.51375-4.764513 7.313946 7.313946 0 0 0-6.509412 0 7.585607 7.585607 0 0 0-5.13021 4.179397 8.463281 8.463281 0 0 0-0.564219 6.770625 330.872475 330.872475 0 0 0 199.900596 199.566244h2.821094a8.609559 8.609559 0 0 0 8.452832-5.642187 9.330506 9.330506 0 0 0-0.261213-6.770624 10.249973 10.249973 0 0 0-5.13021-4.51375 310.215801 310.215801 0 0 1-189.11775-188.898331m51.56332-15.380184a10.249973 10.249973 0 0 0-6.770625 0 7.313946 7.313946 0 0 0-4.513749 4.179398 8.202068 8.202068 0 0 0 0 6.770624 273.823695 273.823695 0 0 0 153.363002 153.780942 5.892951 5.892951 0 0 0 3.071857 0.564218 7.481122 7.481122 0 0 0 7.888614-5.642187 8.202068 8.202068 0 0 0 0-6.770624 7.794577 7.794577 0 0 0-5.130211-4.252537 254.138731 254.138731 0 0 1-143.207066-143.792181 8.766287 8.766287 0 0 0-4.764513-4.51375m38.293732-4.712271a8.463281 8.463281 0 0 0 0 6.509412 224.09931 224.09931 0 0 0 112.457146 112.770601 9.403645 9.403645 0 0 0 11.587381-4.51375 9.581269 9.581269 0 0 0 0-6.770624 8.557317 8.557317 0 0 0-4.816756-4.816756 209.126617 209.126617 0 0 1-61.510287-41.982051 200.799167 200.799167 0 0 1-41.982051-61.771499 8.964808 8.964808 0 0 0-5.130211-4.51375 8.452832 8.452832 0 0 0-6.509412 0.303007 8.714044 8.714044 0 0 0-4.764514 4.764513M613.422336 297.202724a8.202068 8.202068 0 0 0-6.770624 0 7.637849 7.637849 0 0 0-4.816756 4.513749 8.609559 8.609559 0 0 0 0 6.770625 7.585607 7.585607 0 0 0 4.51375 4.764513 200.934997 200.934997 0 0 1 61.510287 42.295506 215.709169 215.709169 0 0 1 42.285057 61.207281 8.045341 8.045341 0 0 0 7.888613 5.642187 5.119762 5.119762 0 0 0 3.134548-0.867225 9.633512 9.633512 0 0 0 4.764514-5.130211 8.358796 8.358796 0 0 0 0-6.45717 216.597291 216.597291 0 0 0-44.844938-67.047989 222.772351 222.772351 0 0 0-66.63005-46.140552m202.700793 99.260698a7.846819 7.846819 0 0 0 8.149826 5.642187l2.821094-0.564219a11.169441 11.169441 0 0 0 5.13021-4.764513 7.690092 7.690092 0 0 0 0.303007-6.206406 327.037877 327.037877 0 0 0-200.151361-199.461759 7.836371 7.836371 0 0 0-6.770624 0 7.585607 7.585607 0 0 0-4.252537 4.764513 9.633512 9.633512 0 0 0 0.303006 6.770624 9.946967 9.946967 0 0 0 4.764513 4.51375 308.042514 308.042514 0 0 1 115.894701 73.306637 301.627139 301.627139 0 0 1 73.296189 115.90515m-40.341637 11.273925a7.637849 7.637849 0 0 0 0-6.509412 266.144051 266.144051 0 0 0-60.329607-92.730388 275.599939 275.599939 0 0 0-92.71994-60.601268 9.633512 9.633512 0 0 0-6.770625 0.303006 8.609559 8.609559 0 0 0-4.513749 4.51375 9.069293 9.069293 0 0 0 0 6.770624 7.313946 7.313946 0 0 0 4.513749 4.179398 252.372936 252.372936 0 0 1 87.140444 57.25775 249.719018 249.719018 0 0 1 56.693531 86.837437 8.202068 8.202068 0 0 0 8.149826 5.642187l3.134548-0.564219a7.690092 7.690092 0 0 0 5.130211-5.13021z" fill="#F8F7F9"/><path d="M511.936109 375.221632a136.697653 136.697653 0 1 0 136.875278 136.697653 136.697653 136.697653 0 0 0-136.875278-136.697653m41.083481 96.596332a56.954743 56.954743 0 0 1 0 80.453407 55.377021 55.377021 0 0 1-40.675989 16.717591 57.04878 57.04878 0 1 1 40.675989-97.170998z" fill="#02B053"/><path d="M540.136596 540.161566a38.053417 38.053417 0 0 0 11.294823-28.210935 39.495309 39.495309 0 1 0-78.98017-0.104485 38.053417 38.053417 0 0 0 11.294822 28.210935 39.850558 39.850558 0 0 0 56.484562 0z" fill="#FFFFFF"/><path d="M704.292893 396.787325l-16.498173-16.425034 21.388068-21.482104a106.261189 106.261189 0 0 0 30.520053-53.694813 122.863847 122.863847 0 0 1 34.271062-60.601268c10.741052-10.782846 53.527637-51.876775 55.37702-53.632123l16.122027 16.811628c-0.438837 0.428388-44.41655 42.650754-54.959081 53.287322a99.072625 99.072625 0 0 0-28.388559 50.581162 128.819488 128.819488 0 0 1-36.413003 63.735816z"/><path d="M798.287549 200.052622A38.053417 38.053417 0 1 0 836.340966 161.999205a38.053417 38.053417 0 0 0-38.063865 38.053417z"/><path d="M689.779934 423.754889a15.296596 15.296596 0 0 1-21.565693 0l-7.313946-7.240807a15.296596 15.296596 0 0 1 0-21.565692l13.133758-13.196449a15.296596 15.296596 0 0 1 21.565692 0l7.313947 7.240807a15.296596 15.296596 0 0 1 0 21.565692z"/></svg>
音响模型
<svg xmlns="http://www.w3.org/2000/svg" class="icon" style="width: 128px; height: 128px; vertical-align: middle; fill: currentcolor; overflow: hidden;" viewBox="0 0 1024 1024" version="1.1"><path d="M510.3 637.8m-189.1 0a189.1 189.1 0 1 0 378.2 0 189.1 189.1 0 1 0-378.2 0Z" fill="#54B0E6"/><path d="M510.3 836.8c-109.7 0-199-89.3-199-199s89.3-199 199-199 199 89.3 199 199-89.3 199-199 199z m0-378.2C411.4 458.6 331 539 331 637.8S411.4 817 510.3 817s179.2-80.4 179.2-179.2-80.4-179.2-179.2-179.2z" fill="#2D415C"/><path d="M510.3 637.8m-113.5 0a113.5 113.5 0 1 0 227 0 113.5 113.5 0 1 0-227 0Z" fill="#54B0E6"/><path d="M510.3 761.1c-68 0-123.3-55.3-123.3-123.3s55.3-123.3 123.3-123.3 123.3 55.3 123.3 123.3-55.3 123.3-123.3 123.3z m0-226.9c-57.1 0-103.6 46.5-103.6 103.6s46.5 103.6 103.6 103.6c57.1 0 103.6-46.5 103.6-103.6s-46.5-103.6-103.6-103.6z" fill="#2D415C"/><path d="M510.3 637.8m-68.7 0a68.7 68.7 0 1 0 137.4 0 68.7 68.7 0 1 0-137.4 0Z" fill="#FDD65D"/><path d="M510.3 716.4c-43.3 0-78.6-35.2-78.6-78.6s35.2-78.6 78.6-78.6c43.3 0 78.6 35.2 78.6 78.6s-35.3 78.6-78.6 78.6z m0-137.4c-32.4 0-58.8 26.4-58.8 58.8s26.4 58.8 58.8 58.8 58.8-26.4 58.8-58.8-26.4-58.8-58.8-58.8z" fill="#2D415C"/><path d="M510.3 281m-113.5 0a113.5 113.5 0 1 0 227 0 113.5 113.5 0 1 0-227 0Z" fill="#54B0E6"/><path d="M510.3 404.3C442.3 404.3 387 349 387 281s55.3-123.3 123.3-123.3S633.6 213 633.6 281s-55.3 123.3-123.3 123.3z m0-226.9c-57.1 0-103.6 46.5-103.6 103.6 0 57.1 46.5 103.6 103.6 103.6 57.1 0 103.6-46.5 103.6-103.6-0.1-57.2-46.5-103.6-103.6-103.6z" fill="#2D415C"/><path d="M510.3 281m-51.3 0a51.3 51.3 0 1 0 102.6 0 51.3 51.3 0 1 0-102.6 0Z" fill="#FDD65D"/><path d="M510.3 342.1c-33.7 0-61.2-27.4-61.2-61.2 0-33.7 27.4-61.2 61.2-61.2 33.7 0 61.2 27.4 61.2 61.2-0.1 33.8-27.5 61.2-61.2 61.2z m0-102.5c-22.8 0-41.4 18.6-41.4 41.4 0 22.8 18.6 41.4 41.4 41.4s41.4-18.6 41.4-41.4c0-22.9-18.6-41.4-41.4-41.4z" fill="#2D415C"/></svg>
编码
这里默认了你对threejs很熟悉了,如果你对threejs还不熟悉请参考 Three.js – JavaScript 3D Library (threejs.org)
首先按照three的套路创建一个基本的场景
function init() {
const width = window.innerWidth, height = window.innerHeight;
const THREE = window.THREE;
const scene = new THREE.Scene();
// scene.background = new THREE.Color('#fff');
// scene.rotation.z = Math.PI;
//
camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 100000);
camera.position.set(0.0021618414672400815, -2.1584257035785575, 0.8339931995638086);
//
const directionalLight = new THREE.DirectionalLight('#fff', 0.4);
directionalLight.position.set(0.75, 1.75, 5.0).normalize();
scene.add(directionalLight);
// directionalLight.castShadow = true;
// directionalLight.shadow.mapSize.width = 512 * 10;
// directionalLight.shadow.mapSize.height = 512 * 10;
// const lightHelper = new THREE.DirectionalLightHelper(directionalLight, 1, 'red');
// scene.add(lightHelper);
const ambientLight = new THREE.AmbientLight(0x404040, 2);
scene.add(ambientLight);
// const pointLight = new THREE.PointLight('#fff', 0.40);
// pointLight.position.set(0, 1.5, -4);
// pointLight.castShadow = false;
// scene.add(pointLight);
const spotLight = new THREE.SpotLight('white');
// spotLight.castShadow = true;
spotLight.intensity = 0.5;
spotLight.angle = 0.46;
// spotLight.shadow.mapSize.width = 512 * 10;
// spotLight.shadow.mapSize.height = 512 * 10;
// spotLight.penumbra = 0.05;
// spotLight.decay = 2;
spotLight.distance = 200;
spotLight.position.set(0, 50, 100);
spotLight.target.position.set(0, 0, 0);
scene.add(spotLight);
// const texture = new THREE.TextureLoader().load('./data/R-C.jfif');
// texture.needsUpdate = true; //使用贴图时进行更新
// texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
// // texture.repeat.set(0.002, 0.002);
// texture.repeat.set(1, 1);
const planeGeometry = new THREE.PlaneBufferGeometry(6, 6);
ground = new THREE.Mesh(planeGeometry, new THREE.MeshStandardMaterial({
opacity: 1, color: params.groundColor, side: 2, roughness: 0,
metalness: 0,
// map: texture
}));
ground.position.z = -0.06;
// ground.rotation.x = -Math.PI / 2;
// ground.position.set(0, -0.9, 0);
// ground.receiveShadow = true;
scene.add(ground);
// const pointLight1 = new THREE.PointLight('#fff', 1);
// pointLight1.position.set(2, 0, 0.5);
// scene.add(pointLight1);
const renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: false });
renderer.setPixelRatio(window.devicePixelRatio);
// const { width, height } = renderDom.getBoundingClientRect();
renderer.setSize(width, height);
renderer.setClearColor(new THREE.Color(1, 1, 1), 0);
renderer.shadowMap.enabled = true;
renderer.shadowMap.needsUpdate = true;
// renderer.outputEncoding = THREE.sRGBEncoding;
// renderer.toneMapping = THREE.ACESFilmicToneMapping;
document.body.appendChild(renderer.domElement);
//
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minDistance = 0.1;
controls.maxDistance = 2000;
function animation() {
requestAnimationFrame(animation);
renderer.render(scene, camera);
loopCD();
loopMusicBox();
}
animation();
window.addEventListener('resize', () => {
const width = window.innerWidth, height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
});
return scene;
}
加载各个模型并调整每个模型的位置,缩放,旋转等参数
function ignoreLights(scene) {
scene.children = scene.children.filter(object3d => {
return !(object3d instanceof THREE.Light);
})
}
function addPhone() {
loader.load('./data/手机.glb', function (gltf) {
ignoreLights(gltf.scene);
scene.add(gltf.scene);
});
}
function addQQMusicModel() {
loader.load('./data/QQ音乐-01 (1).glb', function (gltf) {
ignoreLights(gltf.scene);
const group = new THREE.Group();
group.position.x = -0.95;
group.position.z = 0.06;
group.rotation.z = Math.PI / 4;
group.add(gltf.scene);
scene.add(group);
gltf.scene.rotation.x = Math.PI / 2;
gltf.scene.scale.x = .4;
gltf.scene.scale.y = .4;
gltf.scene.scale.z = .75;
});
}
function addCD() {
loader.load('./data/cd.glb', function (gltf) {
ignoreLights(gltf.scene);
scene.add(gltf.scene);
gltf.scene.scale.x = .5;
gltf.scene.scale.y = .5;
gltf.scene.scale.z = .6;
// gltf.scene.scale.z = 1;
gltf.scene.position.y = -0.45;
gltf.scene.position.z = 0.02;
cd = gltf.scene;
});
}
function loopCD() {
if (!runing) {
return;
}
cd.rotation.z -= 0.01;
}
function addMusicBox() {
loader.load('./data/音响 (1).glb', function (gltf) {
ignoreLights(gltf.scene);
const musicBox = gltf.scene;
musicBox.rotation.x = -Math.PI / 2;
scene.add(musicBox);
musicBox.scale.x = .1;
musicBox.scale.y = .1;
musicBox.scale.z = .2;
musicBox.position.x = -0.35;
musicBox.position.y = -0.50;
musicBox.position.z = 0.16
const musicBox1 = musicBox.clone();
musicBox1.position.x = -musicBox1.position.x;
scene.add(musicBox1);
musicBoxList.push(musicBox, musicBox1);
});
}
function loopMusicBox() {
if (!runing) {
return;
}
musicBoxList.forEach(group => {
if (group._scaleZ === undefined) {
group._scaleZ = 1;
}
if (group._scaleZ > 1.4) {
group._scaleZ = 1;
}
group._scaleZ += 0.1;
const children = group.children;
children.forEach(child => {
const len = child.children.length;
child.children.slice(0, len - 2).forEach(object3d => {
object3d.scale.z = group._scaleZ;
})
});
});
}
读取MP3文件为ArrayBuffer
const musicFileDom = document.querySelector('#musicfile');
musicFileDom.addEventListener('change', () => {
if (audioContext) {
audioContext.close();
}
audioContext = new AudioContext();
clear();
const fileRender = new FileReader();
fileRender.onload = () => {
if (updateId) {
clearTimeout(updateId);
}
audioContext.decodeAudioData(fileRender.result, initVisualizer);
runing = true;
};
fileRender.readAsArrayBuffer(musicFileDom.files[0]);
})
解析ArrayBuffer的数据,组装成网格柱子的数据
这里主要利用 AudioContext - Web API 接口参考 | MDN (mozilla.org) 来解析音频的数据,音频数据的读取和解析代码阅读不懂,需要你仔细的参考 BaseAudioContext - Web APIs | MDN (mozilla.org)
function initVisualizer(audioBuffer) {
//创建 AudioBufferSourceNode
var source = audioContext.createBufferSource();
source.buffer = audioBuffer;
// Must invoked right after click event
source.start(0);
// AudioContext的createAnalyser()方法能创建一个AnalyserNode,可以用来获取音频时间和频率数据,以及实现数据可视化。
var analyzer = audioContext.createAnalyser();
analyzer.fftSize = 4096;
var gainNode = audioContext.createGain();
gainNode.gain.value = 1;
source.connect(gainNode);
gainNode.connect(analyzer);
// Connect the source to be analysed
analyzer.connect(audioContext.destination);
// https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode
var frequencyBinCount = analyzer.frequencyBinCount;
var dataArray = new Uint8Array(frequencyBinCount);
//循环读取音频的数据
function update() {
analyzer.getByteFrequencyData(dataArray);
const scale = 1;
var dataProvider = [];
let isEmpty = true;
//将音频的数据分布到50x50个格子上
for (var i = 0; i < size * size; i++) {
var x = i % size;
var y = Math.floor(i / size);
var dx = x - size / 2;
var dy = y - size / 2;
var angle = Math.atan2(dy, dx);
if (angle < 0) {
angle = Math.PI * 2 + angle;
}
var dist = Math.sqrt(dx * dx + dy * dy);
var idx = Math.min(
frequencyBinCount - 1, Math.round(angle / Math.PI / 2 * 60 + dist * 60) + 100
);
var val = Math.pow(dataArray[idx] / 100, 3);
dataProvider.push([x, y, Math.max(val, 0.1)]);
if (val > 0) {
isEmpty = false;
}
}
runing = !isEmpty;
var musdata = [];
let min = Infinity, max = -Infinity;
//组装每个格子的位置和高度数据
for (var i = 0; i < dataProvider.length; i++) {
var d = dataProvider[i];
var x = d[0],
y = d[1],
z = d[2];
var px = -1 + x * offsetX;
var py = -1 + y * offsetY;
//音频的高度,调越高改值越大
var height = z * scale;
min = Math.min(height, min);
max = Math.max(height, max);
if (height < 0.650 || musdata.length > 2000) continue;
musdata.push({
value: [px, py, height]
});
}
// console.log(min, max);
//利用柱子可视化音频数据
addBar(musdata);
updateId = setTimeout(update, UPDATE_DURATION);
}
update();
}
用柱子高低和颜色来可视化音频的数据
原理也比较简单,音频数据声调越高柱子越高,然后根据不同的高度给柱子不同的颜色
function addBar(data) {
clear();
bars = data.map(function (d) {
const [x, y, z] = d.value;
const material = getMaterial(z);
const bar = new THREE.Mesh(boxGeometry, material);
bar.scale.z = z;
bar.position.x = x + musicCenter[0];
bar.position.y = y + musicCenter[1];
scene.add(bar);
return bar;
});
}
function getColor(z) {
if (z <= 0.3) {
return color[0];
}
if (z > 0.3 && z <= 1.2) {
return color[1];
}
if (z > 1.2 && z <= 2) {
return color[2];
}
if (z > 2 && z <= 3) {
return color[3];
}
return color[4];
}
function getMaterial(z) {
var color = getColor(z);
var material = materialMap[color];
if (!material) {
material = materialMap[color] = new THREE.MeshStandardMaterial({
color,
roughness: 0,
metalness: 0,
// blending: THREE.AdditiveBlending
});
}
return material;
}
注意:因为柱子的数据量比较大,且音频每帧的数据都要可视化展现,典型的数据量大且高频场景,所以要复用Geometry和Material对象
1.所有的Mesh都复用一个Geometry,柱子的高度通过缩放Mesh的scale来实现
2.同一个颜色的材质进行复用和缓存,不要总是创建Material
为场景里的CD和音响开启动画
原理也比较简单:
- 当音频数据读取完成时开启动画
- 音频数据播放完成停止动画
//CD动画
function loopCD() {
if (!runing) {
return;
}
cd.rotation.z -= 0.01;
}
//音响动画
function loopMusicBox() {
if (!runing) {
return;
}
musicBoxList.forEach(group => {
if (group._scaleZ === undefined) {
group._scaleZ = 1;
}
if (group._scaleZ > 1.4) {
group._scaleZ = 1;
}
group._scaleZ += 0.1;
const children = group.children;
children.forEach(child => {
const len = child.children.length;
child.children.slice(0, len - 2).forEach(object3d => {
object3d.scale.z = group._scaleZ;
})
});
});
}
总结
- 该项目仅为自己练手使用
- 音乐可视化也可以丰富多彩
- glicon 是一个简单快捷的3d模型图标工具,一分钟给你个高颜值高质感的模型图标,欢迎使用