很新的反应,试着理解它的基本原理。我想在画布播放时将视频内容渲染到画布上。我的解决方案会导致溢出。如何管理这样的递归调用?
import React, {Component} from 'react';
class VideoPlayer extends React.Component {
componentDidMount() {
this.context = this.refs.canvas.getContext('2d');
}
play() {
if (this.refs.video.paused) {
this.refs.video.play();
this.updateCanvas();
} else {
this.refs.video.pause();
}
}
updateCanvas() {
if (this.refs.video.paused || this.refs.video.ended) {
return;
}
let fps = 30;
this.context.drawImage(this.refs.video, 0, 0, 400, 220);
setTimeout(requestAnimationFrame(this.updateCanvas()), 1000 / fps);
}
render() {
return (
<div>
<video width="400" ref="video" id="v">
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"/>
</video>
<canvas ref="canvas" width="400" height="220"></canvas>
<br/>
<button type="button" onClick={this.play.bind(this)}>Play</button>
</div>
);
}
}
export default VideoPlayer;发布于 2018-01-05 23:34:49
如果您想定期打电话,最好使用setInterval和clearInterval,而不是setTimeout。递归总是有点棘手,处理延迟会使整个方法更加棘手。
因此,当play被按下(视频还没有播放)时,这个想法变成了编程一个setInterval,它会将当前的视频帧复制到画布中,并以n fps的速度完成。返回的interval处理程序将保存到组件的状态。
当play再次按下(视频正在运行)时,将通过调用保存在状态中的clearInterval值来清除interval函数。
此外,为了处理允许视频运行的情况,如果当我们按play (而且视频尚未运行)时,interval处理程序被设置在状态中,那么我们只需使用状态中的interval处理程序调用clearInterval (如果不这样做,每次视频运行到其末端=内存泄漏时,都会有未清除的间隔堆积)。
为了获得当前视频帧的副本,我们还实现了一个非常基本的grabFrame方法,并确保它绑定到组件的上下文中。
最后,我们获取副本(即FPS)的速率作为支柱传递给组件。
class VideoPlayer extends React.Component {
constructor(props) {
super(props);
this.state = {
interval: undefined,
ctx: undefined
};
this.grabFrame = this.grabFrame.bind(this);
}
componentDidMount() {
this.setState({
ctx: this.canvas.getContext("2d")
});
}
grabFrame() {
return this.state.ctx.drawImage(this.video, 0, 0, 400, 220);
}
play() {
if (this.video.paused) {
if (this.state.interval) {
clearInterval(this.state.interval);
}
this.video.play();
this.setState({
interval: setInterval(this.grabFrame, 1000 / this.props.fps)
});
} else {
clearInterval(this.state.interval);
this.setState({
interval: undefined
});
this.video.pause();
}
}
render() {
return (
<div>
<video width="400" ref={video => (this.video = video)} id="v">
<source
src="https://www.w3schools.com/html/mov_bbb.mp4"
type="video/mp4"
/>
</video>
<canvas
ref={canvas => (this.canvas = canvas)}
width="400"
height="220"
/>
<br />
<button type="button" onClick={this.play.bind(this)}>
Play
</button>
</div>
);
}
}有关工作示例,请参见这个CodeSandbox。
https://stackoverflow.com/questions/48120376
复制相似问题