UNPKG

rx-player

Version:
126 lines (112 loc) 3.63 kB
/** * Copyright 2015 CANAL+ Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import log from "../log"; import globalScope from "../utils/global_scope"; import type { IReadOnlySharedReference } from "../utils/reference"; import SharedReference from "../utils/reference"; import type { CancellationSignal } from "../utils/task_canceller"; export interface IResolution { width: number; height: number; } interface IResizeObserverConstructor { // eslint-disable-next-line @typescript-eslint/prefer-function-type new (callback: IResizeObserverCallback): IResizeObserver; } interface IResizeObserver { observe(target: Element): void; unobserve(target: Element): void; disconnect(): void; } type IResizeObserverCallback = ( entries: IResizeObserverEntry[], observer: IResizeObserver, ) => void; interface IResizeObserverEntry { readonly target: Element; readonly contentRect: IDOMRectReadOnly; } interface IDOMRectReadOnly { readonly x: number; readonly y: number; readonly width: number; readonly height: number; readonly top: number; readonly right: number; readonly bottom: number; readonly left: number; } const _ResizeObserver: IResizeObserverConstructor | undefined = globalScope.ResizeObserver; /** * Emit the current height and width of the given `element` each time it * changes. * * On some browsers, we might not be able to rely on a native API to know when * it changes, the `interval` argument allow us to provide us an inverval in * milliseconds at which we should query that element's size. * @param {HTMLElement} element * @param {number} interval * @returns {Object} */ export default function onHeightWidthChange( element: HTMLElement, interval: number, cancellationSignal: CancellationSignal, ): IReadOnlySharedReference<IResolution> { const { height: initHeight, width: initWidth } = element.getBoundingClientRect(); const ref = new SharedReference<IResolution>( { height: initHeight, width: initWidth, }, cancellationSignal, ); let lastHeight: number = initHeight; let lastWidth: number = initWidth; if (_ResizeObserver !== undefined) { const resizeObserver = new _ResizeObserver((entries) => { if (entries.length === 0) { log.error("utils", "Resized but no observed element."); return; } const entry = entries[0]; const { height, width } = entry.contentRect; if (height !== lastHeight || width !== lastWidth) { lastHeight = height; lastWidth = width; ref.setValue({ height, width }); } }); resizeObserver.observe(element); cancellationSignal.register(() => { resizeObserver.disconnect(); }); } else { const intervalId = setInterval(() => { const { height, width } = element.getBoundingClientRect(); if (height !== lastHeight || width !== lastWidth) { lastHeight = height; lastWidth = width; ref.setValue({ height, width }); } }, interval); cancellationSignal.register(() => { clearInterval(intervalId); }); } return ref; }