南锣鼓巷
<style>#papa { margin: 0 0 0 calc(50% - 593px); width: 1024px; height: 640px; background: gray url('https://638183.freep.cn/638183/t22/webp/nlgx.webp') no-repeat center/cover; box-shadow: 6px 3px 20px #000; position: relative; display: grid; place-items: end center; user-select: none; z-index: 1; }
#mplayer { position: absolute; width: 60%; height: 160px; bottom: 0; display: flex; place-items: end; }
.mLine { position: relative; margin: 0 2px 0 0; width: 4px; height: 10px; background: gray linear-gradient(to top,darkgreen,green,lightgreen); transition: height .45s; }
.mLine::after { position: absolute; content: ''; width: 100%; height: 3px; background: pink; top: -4px; }
.tit { position: absolute; top: 20px; font: bold 3em sans-serif; color: hsla(90,50%,50%,.3); text-shadow: 1px 1px 2px #000, -5px -5px 10px snow, 5px 5px 10px snow; animation: flash 3s infinite alternate linear; }
@keyframes flash { to { text-shadow: 1px 1px 2px #000, -5px -5px 20px darkgreen, 5px 5px 20px darkgreen; } }
</style>
<div id="papa">
<div class="tit">南锣鼓巷</div>
<div id="mplayer"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=433059656.mp3" loop autoplay></audio>
</div>
<script>
(function() {
let ybData = ;
let total = Math.ceil(mplayer.offsetWidth / 6);
let cNum = 0;
for(j=0; j<total; j++) {
let el = document.createElement('span');
el.className = 'mLine';
el.style.height = Math.floor(Math.random()* 100) + 'px';
mplayer.appendChild(el);
}
let lines = document.querySelectorAll('.mLine');
mplayer.onclick = () => aud.paused ? aud.play() : aud.pause();
aud.addEventListener('timeupdate', () => {
cNum ++;
if(cNum >= ybData.length) cNum = 0;
setPinpu(cNum);
});
function setPinpu(num) {
let data = ybData;
for(j=0; j<total; j++) {
lines.style.height = Math.floor(Math.random() * data / 1.5) + Math.floor(Math.random() *50) + 'px';
}
}
})();
</script>
本帖尝试性质。频谱能反映音频数据变化,但不完全,我只抓去了音频众多音轨数据中的一个并存储起来,并以其作为频谱变化的参考依据之一。由于音轨数据太少,并不能表现音乐自身丰富的声音信息,仅是有一定的响应能力。
同时,由于不是实时抓取音频数据,响应音频而变化的频谱不是十分精准,大致的、差不多的效果吧。
这个尝试仍然有价值:它能超越音频来源的跨域限制,任何可用的音乐来源均可使用。但也有一个前提——要事先抓取音轨信息。 贴出代码,方便大家研究、完善:
<style>
#papa { margin: 0 0 0 calc(50% - 593px); width: 1024px; height: 640px; background: gray url('https://638183.freep.cn/638183/t22/webp/nlgx.webp') no-repeat center/cover; box-shadow: 6px 3px 20px #000; position: relative; display: grid; place-items: end center; user-select: none; z-index: 1; }
#mplayer { position: absolute; width: 60%; height: 160px; bottom: 0; display: flex; place-items: end; }
.mLine { position: relative; margin: 0 2px 0 0; width: 4px; height: 10px; background: gray linear-gradient(to top,darkgreen,green,lightgreen); transition: height .45s; }
.mLine::after { position: absolute; content: ''; width: 100%; height: 3px; background: pink; top: -4px; }
.tit { position: absolute; top: 20px; font: bold 3em sans-serif; color: hsla(90,50%,50%,.3); text-shadow: 1px 1px 2px #000, -5px -5px 10px snow, 5px 5px 10px snow; animation: flash 3s infinite alternate linear; }
@keyframes flash { to { text-shadow: 1px 1px 2px #000, -5px -5px 20px darkgreen, 5px 5px 20px darkgreen; } }
</style>
<div id="papa">
<div class="tit">南锣鼓巷</div>
<div id="mplayer"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=433059656.mp3" loop autoplay></audio>
</div>
<script>
(function() {
let ybData = ;
let total = Math.ceil(mplayer.offsetWidth / 6);
let cNum = 0;
for(j=0; j<total; j++) {
let el = document.createElement('span');
el.className = 'mLine';
el.style.height = Math.floor(Math.random()* 100) + 'px';
mplayer.appendChild(el);
}
let lines = document.querySelectorAll('.mLine');
mplayer.onclick = () => aud.paused ? aud.play() : aud.pause();
aud.addEventListener('timeupdate', () => {
cNum ++;
if(cNum >= ybData.length) cNum = 0;
setPinpu(cNum);
});
function setPinpu(num) {
let data = ybData;
for(j=0; j<total; j++) {
lines.style.height = Math.floor(Math.random() * data / 1.5) + Math.floor(Math.random() *50) + 'px';
}
}
})();
</script>
JS中,音频数据变量 ybData 就是抓取的整个曲子的一个音轨数据,它是什么样就是什么样,每首歌都会不同。我是按 audio 控件的 timeupdate 抓取的,这样数据和将来的实际播放时进度能保持基本同步。
JS的实现代码并不多也不复杂,唯独 ybData 显得庞杂,但不用去管它。 如果愿意,可以抓取更多的声音信息,保证每一个频谱条拥有不同的信息指向,那么,频谱的变化就基本和实时获取音频上下文对象的声音信息效果高度一致了。不过,这么一来,ybData 数组将呈几何级膨胀。 我家离南锣鼓巷不远,所以,经常去那里溜溜。哪里简直就是小吃一条街。 高端的技术代码,我只能望尘莫及,我只能套用,惭愧! 很好听,感谢老师的分享!{:4_187:} 天哪,这简直就是天文数字。{:4_203:} 隔壁王奶奶和司马楠不就是住那儿吗。下次到北京一定切瞅眼{:4_173:} 那个倒挂的频谱像不像农村集市上做挂面的{:4_170:} 马黑黑 发表于 2022-12-7 09:39
本帖尝试性质。频谱能反映音频数据变化,但不完全,我只抓去了音频众多音轨数据中的一个并存储起来,并以其 ...
任何音乐都能用了,这可太方便了,黑黑厉害,太赞了{:4_199:} 我现在还听不了,效果要等回家再来看了。 频谱漂亮,只是要自己修改制作有难度,还得好好学习 黑神你太厉害了{:4_178:} 什么音乐都可以用,那是跨越问题解决了{:4_199:} 小辣椒 发表于 2022-12-7 11:55
什么音乐都可以用,那是跨越问题解决了
有前提:你需要事先制作音轨信息 小辣椒 发表于 2022-12-7 11:54
黑神你太厉害了
{:4_203:} 梦油 发表于 2022-12-7 10:17
我家离南锣鼓巷不远,所以,经常去那里溜溜。哪里简直就是小吃一条街。
是的,那里很有情调