From e193cbe026ddc5bd7498c65b728c805162e2903e Mon Sep 17 00:00:00 2001 From: Simon Oberhammer Date: Mon, 9 Sep 2024 10:06:33 +0200 Subject: [PATCH] throttle updates of seekbar label --- src/ts/components/seekbar.ts | 53 ++++++++++++++++++++---------------- src/ts/throttle.ts | 17 ++++++++++++ 2 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 src/ts/throttle.ts diff --git a/src/ts/components/seekbar.ts b/src/ts/components/seekbar.ts index 5d6e7183c..2c97cd29a 100644 --- a/src/ts/components/seekbar.ts +++ b/src/ts/components/seekbar.ts @@ -16,6 +16,7 @@ import { i18n } from '../localization/i18n'; import { BrowserUtils } from '../browserutils'; import { TimelineMarkersHandler } from './timelinemarkershandler'; import { getMinBufferLevel } from './seekbarbufferlevel'; +import {throttle} from '../throttle'; /** * Configuration interface for the {@link SeekBar} component. @@ -999,6 +1000,33 @@ export class SeekBar extends Component { this.seekBarEvents.onSeek.dispatch(this); } + protected updateLabelPosition = throttle((seekPositionPercentage: number) => { + const labelDomElement = this.label.getDomElement(); + labelDomElement.css({ + 'left': seekPositionPercentage + '%', + 'transform': null, + }); + if (this.config.preventSeekPreviewOverflow) { + const overflowMargin = 5; + const uiBounding = this.uimanager.getUI().getDomElement().get(0).getBoundingClientRect(); + const labelBounding = labelDomElement.get(0).getBoundingClientRect(); + const labelRight = (labelBounding.right - labelBounding.width / 2 ); + const labelLeft = (labelBounding.left - labelBounding.width / 2); + let preventOverflowOffset = 0; + if (labelRight + overflowMargin > uiBounding.right) { + preventOverflowOffset = labelRight - uiBounding.right + overflowMargin; + } else if (labelLeft - overflowMargin < uiBounding.left) { + preventOverflowOffset = labelLeft - uiBounding.left - overflowMargin; + } + if (preventOverflowOffset) { + labelDomElement.css({ + transform: `translateX(${-preventOverflowOffset}px)`, + }); + labelDomElement.get(0).style.setProperty(`--${this.prefixCss('seekbar-label-overflow-offset')}`, String(preventOverflowOffset)); + } + } + }, 50) + protected onSeekPreviewEvent(percentage: number, scrubbing: boolean) { let snappedMarker = this.timelineMarkersHandler && this.timelineMarkersHandler.getMarkerAtPosition(percentage); @@ -1022,30 +1050,7 @@ export class SeekBar extends Component { } if (this.label) { - const labelDomElement = this.label.getDomElement(); - labelDomElement.css({ - 'left': seekPositionPercentage + '%', - 'transform': null, - }); - if (this.config.preventSeekPreviewOverflow) { - const overflowMargin = 5; - const uiBounding = this.uimanager.getUI().getDomElement().get(0).getBoundingClientRect(); - const labelBounding = labelDomElement.get(0).getBoundingClientRect(); - const labelRight = (labelBounding.right - labelBounding.width / 2 ); - const labelLeft = (labelBounding.left - labelBounding.width / 2); - let preventOverflowOffset = 0; - if (labelRight + overflowMargin > uiBounding.right) { - preventOverflowOffset = labelRight - uiBounding.right + overflowMargin; - } else if (labelLeft - overflowMargin < uiBounding.left) { - preventOverflowOffset = labelLeft - uiBounding.left - overflowMargin; - } - if (preventOverflowOffset) { - labelDomElement.css({ - transform: `translateX(${-preventOverflowOffset}px)`, - }); - labelDomElement.get(0).style.setProperty(`--${this.prefixCss('seekbar-label-overflow-offset')}`, String(preventOverflowOffset)); - } - } + this.updateLabelPosition(seekPositionPercentage); } this.seekBarEvents.onSeekPreview.dispatch(this, { diff --git a/src/ts/throttle.ts b/src/ts/throttle.ts new file mode 100644 index 000000000..9c80702d1 --- /dev/null +++ b/src/ts/throttle.ts @@ -0,0 +1,17 @@ +/** + * Returns a new function which will invocate the original no faster + * then every rateMs milliseconds. + */ +export function throttle(fn: Function, rateMs: number) { + let timerFlag : null | ReturnType = null; + + return (...args: unknown[]) => { + if (timerFlag === null) { + fn(...args); + timerFlag = setTimeout(() => { + timerFlag = null; + }, rateMs); + } + }; +} +