我正在做一个音乐可视化器项目。
在我的HTML页面上,我有一个使用CSS设置为黄色圆圈的div。
使用JAVASCRIPT,我想收集音频文件的频率数据,并使用该数据,只要频率达到特定数字(即代表音频瞬变的数字),就将圆圈的颜色更改为粉红色。基本上是一个黄色的圆圈,随着歌曲的跳动而变成粉红色。
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CSS Flower</title>
<style>
/* centering */
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
/* proportion and perspective */
#scene {
width: 200px;
height: 200px;
perspective: 600px;
perspective-origin: center top;
}
.flower {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
}
#center {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50px;
background: yellow; // THIS IS YELLOW CIRCLE, AND PARAMETER I WANT TO CHANGE
transform: rotateX(180deg) translateX(50px) translateZ(-140px);
}
</style>
</head>
<body>
<input type="file" id="file-input" accept="audio/*,video/*,image/*" />
<canvas id="canvas"></canvas>
<div id="scene">
<div class="flower">
<div class="center" id="center"></div>
</div>
</div>
<audio id="audio" controls></audio>
<script src="audio.js"></script>
</body>
</html>
我现在拥有的JS代码:
window.onload = function() {
const file = document.getElementById("file-input");
const canvas = document.getElementById("canvas");
const audio = document.getElementById("audio");
file.onchange = function() {
const files = this.files;
console.log('FILES[0]: ', files[0])
audio.src = URL.createObjectURL(files[0]);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
const flower = document.getElementById('center');
const context = new AudioContext();
let src = context.createMediaElementSource(audio);
const analyser = context.createAnalyser();
src.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 1024;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
function renderFrame() {
requestAnimationFrame(renderFrame); // Takes callback function to invoke before rendering
analyser.getByteFrequencyData(dataArray); // Copies the frequency data into dataArray
// Results in a normalized array of values between 0 and 255
// Before this step, dataArray's values are all zeros (but with length of 8192)
for (let i = 0; i < bufferLength; i++) {
console.log("data array: ", dataArray)
//from here I can see the different frequencies collected in the array, but I don't know how to proceed
}
audio.play();
renderFrame();
};
};
};
我不知道如何公式化FOR循环,然后如何将此信息与CSS参数连接。
任何帮助将不胜感激!我一直在想办法解决问题,但是没有运气。如您可能通过我的代码可以看出,我是一个完整的初学者!
祝一切顺利,
玉
最佳答案
只要做平均频率。这是工作示例:
const file = document.getElementById("file-input");
const canvas = document.getElementById("canvas");
const audio = document.getElementById("audio");
var threshold = 230; //Point where turn the "flower" pink
var frequencies = 10; //Number of records to count (You want to look for lower frequencies)
file.onchange = function() {
const files = this.files;
//console.log('FILES[0]: ', files[0])
audio.src = URL.createObjectURL(files[0]);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
const flower = document.getElementById('center');
const context = new AudioContext();
let src = context.createMediaElementSource(audio);
const analyser = context.createAnalyser();
src.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 1024;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
function renderFrame() {
requestAnimationFrame(renderFrame); // Takes callback function to invoke before rendering
analyser.getByteFrequencyData(dataArray); // Copies the frequency data into dataArray
// Results in a normalized array of values between 0 and 255
// Before this step, dataArray's values are all zeros (but with length of 8192)
let sum = 0;
for(let i = 0; i < bufferLength; i++) {
if(i < frequencies) sum += dataArray[i];
//Do some other stuff
}
//Change CSS according to threshold
let avg = sum / frequencies;
flower.style.backgroundColor = avg > threshold ? "pink" : "yellow";
flower.style.transform = `scale(${avg / 255})`;
flower.innerText = ~~avg;
};
//!!This functions have to be called outside of the rendering function (renderFrame)!!
audio.play();
renderFrame();
};
/* Sliders */
const sliderF = document.querySelector(".slider.f");
const sliderFvalue = document.querySelector(".slider-value.f");
const sliderT = document.querySelector(".slider.t");
const sliderTvalue = document.querySelector(".slider-value.t");
sliderF.oninput = function() {
sliderFvalue.innerText = this.value;
frequencies = +this.value;
}
sliderT.oninput = function() {
sliderTvalue.innerText = this.value;
threshold = +this.value;
}
/* centering */
body {
margin: 0;
}
canvas {
position: absolute;
pointer-events: none;
}
#audio {
width: 100vw;
}
#center {
width: 100px;
height: 100px;
border-radius: 50px;
background-color: yellow;
text-align: center;
line-height: 100px;
}
.slider-value {
display: inline-block;
width: 25px;
}
.slider {
width: 90vw;
}
<input type="file" id="file-input" accept="audio/*,video/*,image/*" /><br>
<canvas id="canvas"></canvas>
<audio id="audio" controls></audio>
<div class="center" id="center"></div>
<!-- Frequences Slider --->
<input type="range" min="0" max="500" value="10" step="1" class="slider f">
<span class="slider-value f">10</span>
<!-- Threshold Slider --->
<input type="range" min="0" max="255" value="230" step="1" class="slider t">
<span class="slider-value t">230</span>
您只需要调整滑块使其完美即可,但是使用一些低通均衡器可能会更好,这样您可以获得更接近的结果。
关于javascript - 如何在Javascript中使用Web Audio API更改CSS参数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61560792/