Skip to content

Commit 3ef7919

Browse files
authored
Add latency slider to watch demo (#728)
1 parent 75c17ca commit 3ef7919

File tree

2 files changed

+87
-7
lines changed

2 files changed

+87
-7
lines changed

js/hang-demo/src/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
2929
-->
3030
<hang-watch url="%VITE_RELAY_URL%" path="bbb" muted controls>
31-
<canvas style="width: 100%; height: auto; border-radius: 4px; margin: 0 auto;"></canvas>
31+
<div id="watch-container" style="width: 100%; height: auto; border-radius: 4px; margin: 0 auto; position: relative">
32+
<canvas style="width: 100%; height: auto;"></canvas>
33+
</div>
3234
</hang-watch>
3335

3436
<h3>Other demos:</h3>

js/hang/src/watch/element.ts

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ export class HangWatchInstance {
316316
this.#renderStatus(controls, effect);
317317
this.#renderFullscreen(controls, effect);
318318
this.#renderBuffering(effect);
319+
this.#renderLatency(effect);
319320
});
320321
}
321322

@@ -440,7 +441,78 @@ export class HangWatchInstance {
440441
DOM.render(effect, parent, button);
441442
}
442443

444+
#renderLatency(effect: Effect) {
445+
const container = DOM.create("div", {
446+
style: {
447+
display: "flex",
448+
alignItems: "center",
449+
gap: "8px",
450+
padding: "8px 12px",
451+
background: "transparent",
452+
borderRadius: "8px",
453+
margin: "8px 0",
454+
},
455+
});
456+
457+
const label = DOM.create("span", {
458+
style: {
459+
fontSize: "20px",
460+
fontWeight: "500",
461+
color: "#fff",
462+
whiteSpace: "nowrap",
463+
},
464+
textContent: "Latency:",
465+
});
466+
467+
const slider = DOM.create("input", {
468+
type: "range",
469+
style: {
470+
flex: "1",
471+
height: "6px",
472+
borderRadius: "3px",
473+
background: "transparent",
474+
cursor: "pointer",
475+
},
476+
min: "0",
477+
max: "20000",
478+
step: "100",
479+
});
480+
481+
const valueDisplay = DOM.create("span", {
482+
style: {
483+
fontSize: "20px",
484+
minWidth: "60px",
485+
textAlign: "right",
486+
color: "#fff",
487+
},
488+
});
489+
490+
effect.event(slider, "input", (e) => {
491+
const target = e.currentTarget as HTMLInputElement;
492+
const latency = parseFloat(target.value);
493+
this.parent.signals.latency.set(latency as Time.Milli);
494+
});
495+
496+
effect.effect((innerEffect) => {
497+
const latency = innerEffect.get(this.parent.signals.latency);
498+
499+
if (document.activeElement !== slider) {
500+
slider.value = latency.toString();
501+
}
502+
503+
valueDisplay.textContent = `${Math.round(latency)}ms`;
504+
});
505+
506+
DOM.render(effect, container, label);
507+
DOM.render(effect, container, slider);
508+
DOM.render(effect, container, valueDisplay);
509+
DOM.render(effect, this.parent, container);
510+
}
511+
443512
#renderBuffering(effect: Effect) {
513+
const container = this.parent.querySelector("#watch-container") as HTMLElement;
514+
if (!container) return;
515+
444516
if (!document.getElementById("buffer-spinner-animation")) {
445517
const style = document.createElement("style");
446518
style.id = "buffer-spinner-animation";
@@ -453,7 +525,7 @@ export class HangWatchInstance {
453525
document.head.appendChild(style);
454526
}
455527

456-
const container = DOM.create("div", {
528+
const overlay = DOM.create("div", {
457529
style: {
458530
position: "absolute",
459531
display: "none",
@@ -466,7 +538,7 @@ export class HangWatchInstance {
466538
zIndex: "1",
467539
backgroundColor: "rgba(0, 0, 0, 0.4)",
468540
backdropFilter: "blur(2px)",
469-
pointerEvents: "auto",
541+
pointerEvents: "none",
470542
},
471543
});
472544

@@ -481,20 +553,26 @@ export class HangWatchInstance {
481553
},
482554
});
483555

484-
container.appendChild(spinner);
556+
overlay.appendChild(spinner);
557+
container.appendChild(overlay);
485558

486559
effect.effect((effect) => {
487560
const syncStatus = effect.get(this.video.source.syncStatus);
488561
const bufferStatus = effect.get(this.video.source.bufferStatus);
489562
const shouldShow = syncStatus.state === "wait" || bufferStatus.state === "empty";
563+
490564
if (shouldShow) {
491-
container.style.display = "flex";
565+
overlay.style.display = "flex";
492566
} else {
493-
container.style.display = "none";
567+
overlay.style.display = "none";
494568
}
495569
});
496570

497-
DOM.render(effect, this.parent, container);
571+
effect.cleanup(() => {
572+
if (overlay.parentNode) {
573+
overlay.parentNode.removeChild(overlay);
574+
}
575+
});
498576
}
499577
}
500578

0 commit comments

Comments
 (0)