我正在分析一个类组件中的某些音频,然后对另一组件中的音频进行波形可视化处理。我正在努力用钩子将它们重构为功能组件。 StackBlitz URL
问题:
this.tick
中重写bind
AudioAnalyser
方法canvas
标签写入AudioVisualiser
中的ref
元素。class AudioAnalyser extends Component {
constructor(props) {
super(props);
this.state = { audioData: new Uint8Array(0) };
this.tick = this.tick.bind(this);
}
componentDidMount() {
this.audioContext = new window.AudioContext();
this.analyser = this.audioContext.createAnalyser();
this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
this.source = this.audioContext.createMediaStreamSource(this.props.audio);
this.source.connect(this.analyser);
this.rafId = requestAnimationFrame(this.tick);
}
tick() {
this.analyser.getByteTimeDomainData(this.dataArray);
this.setState({ audioData: this.dataArray });
this.rafId = requestAnimationFrame(this.tick);
}
componentWillUnmount() {
cancelAnimationFrame(this.rafId);
this.analyser.disconnect();
this.source.disconnect();
}
render() {
return <AudioVisualiser audioData={this.state.audioData} />;
}
}
export default AudioAnalyser;
class AudioVisualiser extends Component {
constructor(props) {
super(props);
this.canvas = React.createRef();
}
componentDidUpdate() {
this.draw();
}
draw() {
const { audioData } = this.props;
const canvas = this.canvas.current;
const height = canvas.height;
const width = canvas.width;
const context = canvas.getContext('2d');
let x = 0;
const sliceWidth = (width * 1.0) / audioData.length;
context.lineWidth = 2;
context.strokeStyle = '#000000';
context.clearRect(0, 0, width, height);
context.beginPath();
context.moveTo(0, height / 2);
for (const item of audioData) {
const y = (item / 255.0) * height;
context.lineTo(x, y);
x += sliceWidth;
}
context.lineTo(x, height / 2);
context.stroke();
}
render() {
return <canvas width="300" height="300" ref={this.canvas} />;
}
}
export default AudioVisualiser;
答案 0 :(得分:0)
未经测试,但应该朝这个方向
import React, { useEffect, useState } from 'react';
function useAudio(audio) {
const [analyser, setAnalyser] = useState();
const [audioContext, setAudioContext] = useState();
const [audioData, setAudioData] = useState();
const [dataArray, setDataArray] = useState();
const [rafId, setRafId] = useState();
const [source, setSource] = useState();
useEffect(() => {
const tick = () => {
analyser.getByteTimeDomainData(this.dataArray);
setAudioData(dataArray);
setRafId(requestAnimationFrame(tick));
};
setAudioContext(new window.AudioContext());
setAnalyser(audioContext.createAnalyser());
setDataArray(new Uint8Array(analyser.frequencyBinCount));
setSource(audioContext.createMediaStreamSource(audio), () => {
source.connect(analyser);
});
setRafId(requestAnimationFrame(tick));
return () => {
cancelAnimationFrame(rafId);
analyser.disconnect();
source.disconnect();
};
}, []);
return [audioData, setAudioData];
}
function AudioAnalyser({ audio }) {
const [audioData] = useAudio(audio);
return <AudioVisualiser audioData={audioData} />;
}
export default AudioAnalyser;
第二班
import React, { useEffect, useRef } from 'react';
function Canvas({ audioData }) {
const canvasRef = useRef();
const didMountRef = useRef(false);
useEffect(() => {
const draw = () => {
const canvas = canvasRef.current;
const height = canvas.height;
const width = canvas.width;
const context = canvas.getContext('2d');
const sliceWidth = (width * 1.0) / audioData.length;
context.lineWidth = 2;
context.strokeStyle = '#000000';
context.clearRect(0, 0, width, height);
context.beginPath();
context.moveTo(0, height / 2);
let x = 0;
for (const item of audioData) {
const y = (item / 255.0) * height;
context.lineTo(x, y);
x += sliceWidth;
}
context.lineTo(x, height / 2);
context.stroke();
};
if (didMountRef.current) {
draw();
} else didMountRef.current = true;
}, []);
return <canvas width="300" height="300" ref={canvasRef} />;
}
export { Canvas as default };
让我知道这是否对您有帮助,或者您需要一些代码片段的说明。