如何在Javascript中用Web音频API改变一个CSS参数?

问题描述 投票:0回答:1

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

在我的HTML页面上,我有一个使用CSS样式的黄色圆圈的div,我想用JAVASCRIPT来收集音频文件的频率数据。

使用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参数连接起来。

任何帮助都将是非常感激的! 我已经尝试了好几天,但没有任何进展。你可能会从我的代码中看出,我是一个完全的初学者。

所有最好的。

翡翠

javascript html css web-audio-api visualizer
1个回答
1
投票

只要做频率的平均值就可以了。这里是工作的例子。

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>

你只需要调整滑块就可以了 但最好使用一些低通量的均衡器 这样你就可以得到更接近的结果了

© www.soinside.com 2019 - 2024. All rights reserved.