好的,我知道如何使用AnalyserNode为画布设置动画。我做了一个演示,展示了我是如何实现它的。
这是我的演示-> https://codesandbox.io/s/heuristic-lovelace-bmwxo?file=/src/Visualizer.js
我想了解的是如何使其看起来与此类似 -> https://s3.us-west-1.amazonaws.com/storycreator.rendered/cka4ubx6d0dgb0114ws1rll7p?t=1590039817915
该音频频谱是在 After Effects 中使用音频频谱效果生成的。
我正在使用new Uint8Array(analyser.frequencyBinCount)音频 api 的频率反馈。AE 在幕后使用什么来创建频谱效果?在这种情况下,频谱和频率之间有区别吗?
这是 JavaScript 频率的完整代码
import React, { useEffect, useRef } from "react";
let frequencyArray = [];
let analyser;
const Visualizer = () => {
const canvasRef = useRef(null);
const requestRef = useRef(null);
const handleInit = () => {
initAudio();
requestRef.current = requestAnimationFrame(drawCanvas);
};
const initAudio = () => {
const audio = new Audio();
audio.src =
"https://s3.us-west-2.amazonaws.com/storycreator.uploads/ck9kpb5ss0xf90132mgf8z893?client_id=d8976b195733c213f3ead34a2d95d1c1";
audio.crossOrigin = "anonymous";
audio.load();
const context = new (window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
const source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequencyArray = new Uint8Array(analyser.frequencyBinCount);
audio.play();
};
// draw the whole thing
const drawCanvas = () => {
if (canvasRef.current) {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
const radius = 200;
const bars = Math.round(canvas.width);
ctx.clearRect(0, 0, canvas.width, canvas.height);
analyser.getByteFrequencyData(frequencyArray);
for (var i = 0; i < bars; i++) {
const height = frequencyArray[i] * 0.25;
drawLine(
{
i,
bars,
height,
radius
},
canvas,
ctx
);
}
requestRef.current = requestAnimationFrame(drawCanvas);
}
};
// dray lines around the circle
const drawLine = (opts, canvas, ctx) => {
const { i, radius, bars, height } = opts;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const lineWidth = 10;
// draw the bar
ctx.strokeStyle = "#ddd";
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(i, centerY);
ctx.lineTo(i, centerY + height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(i, centerY);
ctx.lineTo(i, centerY - height);
ctx.stroke();
};
return (
<>
<button onClick={handleInit}>Start Visualizer</button>
<canvas
ref={canvasRef}
style={{ background: "#f5f5f5" }}
width={window.innerWidth}
height={window.innerHeight}
/>
</>
);
};
export default Visualizer;
Run Code Online (Sandbox Code Playgroud)
我认为analyzer.getByteTimeDomainData()会更合适。
您的代码的稍微修改版本(以便我可以离线测试它,因为我不熟悉 React):
let frequencyArray = [];
let analyser;
let request;
var flag=0;
var height=0;
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
const bars = Math.round(canvas.width);
const lineWidth = 3;
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
const audio = new Audio();
audio.src =
"https://s3.us-west-2.amazonaws.com/storycreator.uploads/ck9kpb5ss0xf90132mgf8z893?client_id=d8976b195733c213f3ead34a2d95d1c1";
audio.crossOrigin = "anonymous";
audio.load();
const context = new (window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
const source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
frequencyArray = new Uint8Array(analyser.frequencyBinCount);
document.getElementById('button').addEventListener('click', function() {
context.resume().then(() => {
console.log('Playback resumed successfully');
});
});
function begin()
{
audio.play();
requestAnimationFrame(drawCanvas);
};
function end()
{
cancelAnimationFrame(request);
audio.pause();
};
audio.addEventListener("ended", close);
function close()
{
if(flag==0)
{
flag=1;
}
else
{
ctx.clearRect(0, 0, canvas.width, canvas.height);
flag=0;
}
}
const drawCanvas = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
analyser.getByteTimeDomainData(frequencyArray);
for (var i = 0; i < bars; i+=3) {
height = frequencyArray[i];
if(height<100)
{
height*=0.05;
}
else
{
if(height<200 && height>100)
{
height=(height-100)+(100*0.05)
}
else
{
height=(height-200)*0.2+(100*1.05);
}
}
drawLine(
{
i,
bars,
height
},
canvas,
ctx
);
}
if(flag==0)
{
request = requestAnimationFrame(drawCanvas);
}
else
{
flag=2;
close();
}
};
const drawLine = (opts, canvas, ctx) => {
const { i, bars, height } = opts;
// draw the bar
ctx.strokeStyle = "#212121";
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(i, centerY);
ctx.lineTo(i, centerY + height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(i, centerY);
ctx.lineTo(i, centerY - height);
ctx.stroke();
};Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>
<head>
<body>
<button id="button" onClick=begin()>Start</button>
<button onClick=end()>End</button>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML canvas tag.</canvas>
<script src = "wave.js">
</script>
</body>
</html>Run Code Online (Sandbox Code Playgroud)
间歇性地出现一些看起来很糟糕的尖锐尖峰。也许其他人可以解决这个问题。