Don't have requestAnimationFrame looping in background for Live Mode (#1098)
This commit is contained in:
@@ -300,7 +300,6 @@ export class Replayer {
|
|||||||
|
|
||||||
const timer = new Timer([], {
|
const timer = new Timer([], {
|
||||||
speed: this.config.speed,
|
speed: this.config.speed,
|
||||||
liveMode: this.config.liveMode,
|
|
||||||
});
|
});
|
||||||
this.service = createPlayerService(
|
this.service = createPlayerService(
|
||||||
{
|
{
|
||||||
@@ -722,18 +721,16 @@ export class Replayer {
|
|||||||
this.service.send('END');
|
this.service.send('END');
|
||||||
this.emitter.emit(ReplayerEvents.Finish);
|
this.emitter.emit(ReplayerEvents.Finish);
|
||||||
};
|
};
|
||||||
|
let finish_buffer = 50; // allow for checking whether new events aren't just about to be loaded in
|
||||||
if (
|
if (
|
||||||
event.type === EventType.IncrementalSnapshot &&
|
event.type === EventType.IncrementalSnapshot &&
|
||||||
event.data.source === IncrementalSource.MouseMove &&
|
event.data.source === IncrementalSource.MouseMove &&
|
||||||
event.data.positions.length
|
event.data.positions.length
|
||||||
) {
|
) {
|
||||||
// defer finish event if the last event is a mouse move
|
// extend finish event if the last event is a mouse move so that the timer isn't stopped by the service before checking the last event
|
||||||
setTimeout(() => {
|
finish_buffer += Math.max(0, -event.data.positions[0].timeOffset);
|
||||||
finish();
|
|
||||||
}, Math.max(0, -event.data.positions[0].timeOffset + 50)); // Add 50 to make sure the timer would check the last mousemove event. Otherwise, the timer may be stopped by the service before checking the last event.
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
|
setTimeout(finish, finish_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitter.emit(ReplayerEvents.EventCast, event);
|
this.emitter.emit(ReplayerEvents.EventCast, event);
|
||||||
|
|||||||
@@ -223,7 +223,6 @@ export function createPlayerService(
|
|||||||
}),
|
}),
|
||||||
startLive: assign({
|
startLive: assign({
|
||||||
baselineTime: (ctx, event) => {
|
baselineTime: (ctx, event) => {
|
||||||
ctx.timer.toggleLiveMode(true);
|
|
||||||
ctx.timer.start();
|
ctx.timer.start();
|
||||||
if (event.type === 'TO_LIVE' && event.payload.baselineTime) {
|
if (event.type === 'TO_LIVE' && event.payload.baselineTime) {
|
||||||
return event.payload.baselineTime;
|
return event.payload.baselineTime;
|
||||||
|
|||||||
@@ -10,64 +10,71 @@ export class Timer {
|
|||||||
public speed: number;
|
public speed: number;
|
||||||
|
|
||||||
private actions: actionWithDelay[];
|
private actions: actionWithDelay[];
|
||||||
private raf: number | null = null;
|
private raf: number | true | null = null;
|
||||||
private liveMode: boolean;
|
private lastTimestamp: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
actions: actionWithDelay[] = [],
|
actions: actionWithDelay[] = [],
|
||||||
config: {
|
config: {
|
||||||
speed: number;
|
speed: number;
|
||||||
liveMode: boolean;
|
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
this.actions = actions;
|
this.actions = actions;
|
||||||
this.speed = config.speed;
|
this.speed = config.speed;
|
||||||
this.liveMode = config.liveMode;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Add an action, possibly after the timer starts.
|
* Add an action, possibly after the timer starts.
|
||||||
*/
|
*/
|
||||||
public addAction(action: actionWithDelay) {
|
public addAction(action: actionWithDelay) {
|
||||||
|
const rafWasActive = this.raf === true;
|
||||||
if (
|
if (
|
||||||
!this.actions.length ||
|
!this.actions.length ||
|
||||||
this.actions[this.actions.length - 1].delay <= action.delay
|
this.actions[this.actions.length - 1].delay <= action.delay
|
||||||
) {
|
) {
|
||||||
// 'fast track'
|
// 'fast track'
|
||||||
this.actions.push(action);
|
this.actions.push(action);
|
||||||
return;
|
} else {
|
||||||
|
// binary search - events can arrive out of order in a realtime context
|
||||||
|
const index = this.findActionIndex(action);
|
||||||
|
this.actions.splice(index, 0, action);
|
||||||
|
}
|
||||||
|
if (rafWasActive) {
|
||||||
|
this.raf = requestAnimationFrame(this.rafCheck.bind(this));
|
||||||
}
|
}
|
||||||
// binary search - events can arrive out of order in a realtime context
|
|
||||||
const index = this.findActionIndex(action);
|
|
||||||
this.actions.splice(index, 0, action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public start() {
|
||||||
this.timeOffset = 0;
|
this.timeOffset = 0;
|
||||||
let lastTimestamp = performance.now();
|
this.lastTimestamp = performance.now();
|
||||||
const check = () => {
|
this.raf = requestAnimationFrame(this.rafCheck.bind(this));
|
||||||
const time = performance.now();
|
}
|
||||||
this.timeOffset += (time - lastTimestamp) * this.speed;
|
|
||||||
lastTimestamp = time;
|
|
||||||
while (this.actions.length) {
|
|
||||||
const action = this.actions[0];
|
|
||||||
|
|
||||||
if (this.timeOffset >= action.delay) {
|
private rafCheck() {
|
||||||
this.actions.shift();
|
const time = performance.now();
|
||||||
action.doAction();
|
this.timeOffset += (time - this.lastTimestamp) * this.speed;
|
||||||
} else {
|
this.lastTimestamp = time;
|
||||||
break;
|
while (this.actions.length) {
|
||||||
}
|
const action = this.actions[0];
|
||||||
|
|
||||||
|
if (this.timeOffset >= action.delay) {
|
||||||
|
this.actions.shift();
|
||||||
|
action.doAction();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (this.actions.length > 0 || this.liveMode) {
|
}
|
||||||
this.raf = requestAnimationFrame(check);
|
if (this.actions.length > 0) {
|
||||||
}
|
this.raf = requestAnimationFrame(this.rafCheck.bind(this));
|
||||||
};
|
} else {
|
||||||
this.raf = requestAnimationFrame(check);
|
this.raf = true; // was active
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public clear() {
|
public clear() {
|
||||||
if (this.raf) {
|
if (this.raf) {
|
||||||
cancelAnimationFrame(this.raf);
|
if (this.raf !== true) {
|
||||||
|
cancelAnimationFrame(this.raf);
|
||||||
|
}
|
||||||
this.raf = null;
|
this.raf = null;
|
||||||
}
|
}
|
||||||
this.actions.length = 0;
|
this.actions.length = 0;
|
||||||
@@ -77,10 +84,6 @@ export class Timer {
|
|||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleLiveMode(mode: boolean) {
|
|
||||||
this.liveMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isActive() {
|
public isActive() {
|
||||||
return this.raf !== null;
|
return this.raf !== null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user