音频&案例
知识点:
案例效果图:
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
*{
margin: 0;
padding: 0;
}
.controlls {
display: flex;
justify-content: space-around;
align-items: center;
margin-bottom: 16px;
}
.music-wrapper {
position: relative;
display: flex;
flex-direction: row;
justify-content: space-between;
list-style: none;
width: 100%;
height: 148px;
padding: 16px;
border-top:1px solid #ccc;
}
.music-draw{
width: 20px;
height: 50px;
transition: .5s;
}
#controll{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
padding: 8px;
background-color: #64c239;
border: none;
color: #fff;
width: 80px;
height: 80px;
border-radius: 50%;
cursor: pointer;
border: 2px solid #ccc;
}
#controll:hover{
opacity: .8;
}
</style>
</head>
<body>
<!-- 控制音量 -->
<div class="controlls">
<div>
<h3>控制音量</h3>
<input type="range" id="volume" min="0" max="2" value="1" step="0.01">
</div>
<div>
<h3>控制立体声方向</h3>
<input type="range" id="panner" min="-1" max="1" value="0" step="0.01">
</div>
</div>
<ul class="music-wrapper">
<button id="controll" data-playing="false">播放</button>
</ul>
<!-- 如果你要加载的声音文件保留在其他域中,则需要使用 crossorigin 属性 -->
<audio src="./audio.mp3" type="audio/mpeg" id="source"></audio>
<script>
const pillarNumber = 128;
/** 创建负责动效的长方形的个数 */
const ulWrapper = document.querySelector(".music-wrapper");
new Array(pillarNumber).fill("").forEach(()=>{
const li = document.createElement("li");
li.classList.add("music-draw");
li.style.backgroundColor = "#"+new Array(6).fill(0).map(()=> [0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f"][Math.floor(Math.random()*16)]).join("");
ulWrapper.appendChild(li);
});
/** 创建音频上下文 */
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
/** 获取音频源 */
const audioElement = document.querySelector("#source");
/** 讲音频源放在音频上下文中 */
const track = audioContext.createMediaElementSource(audioElement);
/** 修改音量 */
const gainNode = audioContext.createGain();
/** 为应用程序增加立体声平移 */
const pannerOptions = { pan: 0 };
const panner = new StereoPannerNode(audioContext,pannerOptions);
/** 获取数据分析 */
const analyser = audioContext.createAnalyser();
/** 连接 */
track.connect(gainNode).connect(panner).connect(analyser).connect(audioContext.destination);
/** 控制播放 */
const controllBtn = document.querySelector("#controll");
controllBtn.onclick = function () {
if(audioContext.state === "suspended"){
audioContext.resume();
}
if(this.dataset.playing === "false"){
audioElement.play();
this.dataset.playing = "true";
this.innerHTML = "暂停";
this.style.backgroundColor = "#e61021";
}else {
audioElement.pause();
this.dataset.playing = "false";
this.innerHTML = "播放";
this.style.backgroundColor = "#64c239";
}
}
/** 音频播放结束,将状态更新 */
audioElement.addEventListener("ended",()=>{
controllBtn.dataset.playing = "false";
});
/** 修改音量 */
const volumeInput = document.querySelector("#volume");
volumeInput.oninput = function () {
gainNode.gain.value = this.value;
}
/** 立体声平移 */
const pannerInput = document.querySelector("#panner");
pannerInput.oninput = function (){
panner.pan.value = this.value;
}
/** 获取音频数据 */
function getAudioData (){
const freqArry = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqArry);
const step = Math.round(freqArry.length / pillarNumber);
const results = freqArry.slice(0,pillarNumber).map(i => i * step);
if(audioElement.currentTime >= audioElement.duration){
audioElement.currentTime = 0;
}
results.currentTime = audioElement.currentTime ;
results.duration = audioElement.duration;
return results;
}
const musicDraws = document.querySelectorAll(".music-draw");
const timer = setInterval(()=>{
if(controllBtn.dataset.playing === "true"){
const data = getAudioData();
console.log('data:',data);
musicDraws.forEach((item,index)=>{
item.style.height = 20+Number(data[index])+"px";
})
}
},20)
</script>
</body>
</html>