我正在做一个音乐可视化器项目。

在我的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/

10-12 06:58
查看更多