add skip inactive switch and use rrweb timer to display current time

This commit is contained in:
Yanzhen Yu
2026-04-01 12:00:00 +08:00
parent c34d9523b5
commit 357d18c0dd
5 changed files with 123 additions and 15 deletions

View File

@@ -16,7 +16,7 @@
"svelte": "^2.16.0"
},
"dependencies": {
"rrweb": "^0.6.11"
"rrweb": "^0.7.0"
},
"scripts": {
"build": "rollup -c",

View File

@@ -49,8 +49,15 @@
{/if}
</button>
{#each [1, 2, 4, 8] as s}
<button class:active="s === speed" on:click="setSpeed(s)">{s}x</button>
<button
class:active="s === speed && !isSkipping"
on:click="setSpeed(s)"
disabled="{isSkipping}"
>
{s}x
</button>
{/each}
<Switch id="skip" bind:checked="skipInactive" disabled="{isSkipping}" label="skip inactive" />
</div>
</div>
{/if}
@@ -59,10 +66,15 @@
import { formatTime } from './utils.js';
export default {
components: {
Switch: './components/Switch.html',
},
data() {
return {
currentTime: 0,
isPlaying: false,
isSkipping: false,
skipInactive: true,
speed: 1,
};
},
@@ -80,29 +92,23 @@
},
methods: {
loopTimer() {
const now = performance.now();
let lastStep = now;
const self = this;
function update(step) {
let { currentTime, meta, isPlaying, speed } = self.get();
function update() {
const { meta, isPlaying, replayer } = self.get();
if (!isPlaying) {
self.timer = null;
return;
}
const stepDiff = Math.floor(step - lastStep);
lastStep = step;
currentTime += speed * stepDiff;
const currentTime =
replayer.timer.timeOffset + replayer.getTimeOffset();
self.set({
currentTime: Math.min(currentTime, meta.totalTime),
currentTime,
});
if (currentTime < meta.totalTime) {
requestAnimationFrame(update);
} else {
self.timer = null;
self.set({ isPlaying: false, currentTime: 0 });
}
}
@@ -130,9 +136,11 @@
}
},
setSpeed(speed) {
const { replayer } = this.get();
const { replayer, currentTime } = this.get();
replayer.pause();
replayer.setConfig({ speed });
this.set({ speed });
replayer.resume(currentTime);
},
handleProgressClick(event) {
const progressRect = this.refs.progress.getBoundingClientRect();
@@ -165,12 +173,27 @@
current.replayer.on('resume', () => {
this.set({ isPlaying: true });
});
current.replayer.on('finish', () => {
this.timer = null;
this.set({ isPlaying: false, currentTime: 0 });
});
current.replayer.on('skip-start', payload => {
payload.isSkipping = true;
this.set(payload);
});
current.replayer.on('skip-end', payload => {
payload.isSkipping = false;
this.set(payload);
});
}
if (changed.isPlaying) {
if (current.isPlaying && !this.timer) {
this.loopTimer();
}
}
if (changed.skipInactive) {
current.replayer.setConfig({ skipInactive: changed.skipInactive });
}
},
ondestroy() {
const { isPlaying } = this.get();
@@ -233,6 +256,9 @@
.rr-controller__btns {
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
}
.rr-controller__btns button {
@@ -256,4 +282,8 @@
color: #fff;
background: rgb(73, 80, 246);
}
.rr-controller__btns button:disabled {
cursor: not-allowed;
}
</style>

View File

@@ -46,6 +46,7 @@
const replayer = new Replayer(events, {
speed: 1,
root: this.refs.frame,
skipInactive: true,
});
replayer.on('resize', (dimension) =>
this.updateScale(replayer.wrapper, dimension)

View File

@@ -0,0 +1,77 @@
<div class="switch" class:disabled="disabled">
<input
type="checkbox"
id="{id}"
bind:checked="checked"
disabled="{disabled}"
/>
<label for="{id}"></label> <span class="label">{label}</span>
</div>
<style>
.switch {
height: 1em;
display: flex;
align-items: center;
}
.switch.disabled {
opacity: 0.5;
}
.label {
margin: 0 8px;
height: 1em;
}
.switch input[type='checkbox'] {
position: absolute;
opacity: 0;
}
.switch label {
width: 2em;
height: 1em;
position: relative;
cursor: pointer;
display: block;
}
.switch.disabled label {
cursor: not-allowed;
}
.switch label:before {
content: '';
position: absolute;
width: 2em;
height: 1em;
left: 0.1em;
transition: background 0.1s ease;
background: rgba(73, 80, 246, 0.5);
border-radius: 50px;
}
.switch label:after {
content: '';
position: absolute;
width: 1em;
height: 1em;
border-radius: 50px;
left: 0;
transition: all 0.2s ease;
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.3);
background: #fcfff4;
animation: switch-off 0.2s ease-out;
z-index: 2;
}
.switch input[type='checkbox']:checked + label:before {
background: rgb(73, 80, 246);
}
.switch input[type='checkbox']:checked + label:after {
animation: switch-on 0.2s ease-out;
left: 1.1em;
}
</style>

View File

@@ -27,7 +27,7 @@ export function formatTime(ms) {
ms = ms % MINUTE;
const second = Math.round(ms / SECOND);
if (hour) {
return `${padZero(hour)}:${padZero(minute)}:${padZero(minute)}`;
return `${padZero(hour)}:${padZero(minute)}:${padZero(second)}`;
}
return `${padZero(minute)}:${padZero(second)}`;
}