我在画布上放置了一行(这是一个div)(此处不相关)。假设我有一个视频播放器,播放25 fps的视频。播放视频时,此行和画布安排应用作辅助时间线。我要使线条平滑地横切(没有任何颠簸或跳动行为)。我已经解决了,直到线与视频时间同步移动为止。但是线的过渡是跳跃的。我正在移动线架副。
我的代码:
var fps = 25;
var now;
var then = Date.now();
var interval = 1000/fps;
var delta;
var myReq;
class App extends Component {
state = {
playing: false,
xPos: 1,
line1_xStart: 700,
line1_xEnd: 700,
isMouseDown: false,
player: {},
startX:0
}
componentDidMount() {
canvas = document.getElementsByTagName("canvas")[0];
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
ctx.fillStyle = "#808891";
this.init()
}
componentWillUpdate(nextProps, nextState){
}
init = ()=> {
this.initVideoJS()
}
initVideoJS = ()=> {
let x
myPlayer = videojs('video-el');
myPlayer.on('play', ()=>{
this.draw()
}
)
myPlayer.on("timeupdate", () => {
duration = myPlayer.duration()
currentTime = myPlayer.currentTime();
x = duration
//console.log(x)
this.setState({line1_xEnd: 700 + (currentTime * document.getElementById("DemoCanvas").offsetWidth/duration)}, ()=>{
console.log(this.state.line1_xEnd)
})
})
}
draw = () => {
let totalFrames = myPlayer.duration() * 25
now = Date.now();
delta = now - then;
if(this.state.startX < 900){
if (delta > interval) {
counter = counter + 1
console.log("counter is " + counter)
// update time stuffs
// Just `then = now` is not enough.
// Lets say we set fps at 10 which means
// each frame must take 100ms
// Now frame executes in 16ms (60fps) so
// the loop iterates 7 times (16*7 = 112ms) until
// delta > interval === true
// Eventually this lowers down the FPS as
// 112*10 = 1120ms (NOT 1000ms).
// So we have to get rid of that extra 12ms
// by subtracting delta (112) % interval (100).
// Hope that makes sense.
then = now - (delta % (interval));
this.setState({ startX: this.state.startX + ((900/(totalFrames)))})
// ... Code for Drawing the Frame ...
}
}
window.requestAnimationFrame(this.draw);
}
handlePlay() {
}
render() {
return (
<div>
<video id="video-el" className="video-js" ref={node => this.video_el = node} controls preload="auto" width="640" height="264"
poster="MY_VIDEO_POSTER.jpg" data-setup="{}">
<source src="http://techslides.com/demos/sample-videos/small.mp4" type='video/mp4'/>
</video>
<div onClick={this.shiftLine.bind(this)}
onMouseDown={this.mouseDown.bind(this)}
onMouseUp={this.onMouseUp.bind(this)}
onMouseMove={this.mouseMove.bind(this)}>
<div className="App">
<canvas id="DemoCanvas" style={{width: 900, height:"60px"}}></canvas>
</div>
<div className="line"
style={{
position: 'absolute',
transform: `translate(${this.state.startX}px, 0px)`
}}
/>
</div>
</div>
);
}
}
我们要做的就是设置每秒的帧数和每帧之间的间隔。在绘图功能中,我们从当前时间中减去上一帧的执行时间,以检查自上一帧以来经过的时间是否大于我们的间隔(基于fps)。如果条件的计算结果为true,则将当前帧的时间设置为下一个绘图调用中的“最后一帧执行时间”。
以上是在每次更改帧时移动行的代码。该视频是一个5秒的视频。我尝试通过进行以下更改来使过渡变得顺畅:
draw = () => {
let totalFrames = myPlayer.duration() * 25
now = Date.now();
delta = now - then;
if(this.state.startX < 900){
if (delta > interval/2) {
counter = counter + 1
console.log("counter is " + counter)
// update time stuffs
// Just `then = now` is not enough.
// Lets say we set fps at 10 which means
// each frame must take 100ms
// Now frame executes in 16ms (60fps) so
// the loop iterates 7 times (16*7 = 112ms) until
// delta > interval === true
// Eventually this lowers down the FPS as
// 112*10 = 1120ms (NOT 1000ms).
// So we have to get rid of that extra 12ms
// by subtracting delta (112) % interval (100).
// Hope that makes sense.
then = now - (delta % (interval/2));
this.setState({ startX: this.state.startX + ((900/(totalFrames))/2)})
// ... Code for Drawing the Frame ...
}
}
window.requestAnimationFrame(this.draw);
}
我将间隔除以2,并相应地更改了setState。
那里仍然有一个混蛋。它不应该是平滑的。