UNPKG

@devexperts/dxcharts-lite

Version:
117 lines (116 loc) 4.63 kB
/* * Copyright (C) 2019 - 2026 Devexperts Solutions IE Limited * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /* * Copyright (C) 2019 - 2024 Devexperts Solutions IE Limited * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import { Subject } from 'rxjs'; import { EVENT_DRAW, EVENT_RESIZED } from '../events/events'; import { uuid } from '../utils/uuid.utils'; import { animationFrameThrottledPrior } from '../utils/performance/request-animation-frame-throttle.utils'; /** * Tracks chart element size and emits events whenever it changes. */ export class ChartResizeHandler { constructor(frameElement, resizerElement, bus, canvasModels, config) { this.frameElement = frameElement; this.resizerElement = resizerElement; this.bus = bus; this.canvasModels = canvasModels; this.config = config; this.previousBCR = undefined; this.animFrameId = `resize_${uuid()}`; this.canvasResized = new Subject(); this.recentlyResized = false; // Flag to track if resize happened recently this.elementResizeDetector = new ResizeObserver(() => this.handleResize()); } /** * Subscribe to resize events * Use it to update chart animations. * TODO activate / deactivate cycle */ subscribeResize() { this.elementResizeDetector.observe(this.resizerElement); } /** * Handles the resize event by throttling the animation frame and firing updates. * @private * @function * @returns {void} */ handleResize() { animationFrameThrottledPrior(this.animFrameId, () => this.fireUpdates()); } /** * Updates the canvas models and fires events if the bounding client rectangle of the resizer element has changed. * @function * @name fireUpdates * @memberof ClassName * @returns {void} */ fireUpdates() { const resizerElementBCR = this.resizerElement.getBoundingClientRect(); const newBCR = { x: resizerElementBCR.x, y: resizerElementBCR.y, width: resizerElementBCR.width, height: resizerElementBCR.height, }; if (!this.config) { this.frameElement.style.height = this.resizerElement.clientHeight + 'px'; } if (this.previousBCR === undefined || this.isBCRDimensionsDiffer(this.previousBCR, newBCR)) { this.previousBCR = newBCR; this.recentlyResized = true; // Set flag when actual resize happens this.canvasModels.forEach(model => this.previousBCR && model.updateDPR(this.previousBCR)); this.canvasResized.next(newBCR); this.bus.fire(EVENT_RESIZED, newBCR); this.bus.fire(EVENT_DRAW); } } /** * Resets the resize flag after it has been processed */ clearResizedFlag() { this.recentlyResized = false; } /** * Checks if the dimensions of two PickedDOMRect objects are different. * @param {PickedDOMRect} previousBCR - The previous bounding client rectangle. * @param {PickedDOMRect} newBCR - The new bounding client rectangle. * @returns {boolean} - Returns true if the dimensions are different, false otherwise. */ isBCRDimensionsDiffer(previousBCR, newBCR) { return previousBCR.height !== newBCR.height || previousBCR.width !== newBCR.width; } /** * Unsubscribes from the element resize detector to stop updating the chart animation. * @function * @name unsubscribeAnimationUpdate * @memberof ChartResizeHandler * @instance * @returns {void} */ unsubscribeAnimationUpdate() { if (this.resizerElement) { try { this.elementResizeDetector.unobserve(this.resizerElement); } catch (_a) { console.warn('ChartResizeHandler.ts, unsubscribeAnimationUpdate failed'); } } } // TODO a lot of unnecessary DRAW events fired before canvas has actual size /** * Checks if the canvas has been resized by comparing the previous bounding client rect with the current one. * @returns {boolean} - Returns true if the canvas has been resized, false otherwise. */ wasResized() { return this.recentlyResized; } }