@luma.gl/core
Version:
The luma.gl core Device API
90 lines • 3.44 kB
JavaScript
// luma.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
/**
* Internal DOM observer orchestration for HTML canvas surfaces.
*
* CanvasSurface owns the tracked state and device callback dispatch. This helper only manages
* browser observers, timers, and polling loops, then reports events through callbacks.
*/
export class CanvasObserver {
props;
_resizeObserver;
_intersectionObserver;
_observeDevicePixelRatioTimeout = null;
_observeDevicePixelRatioMediaQuery = null;
_handleDevicePixelRatioChange = () => this._refreshDevicePixelRatio();
_trackPositionInterval = null;
_started = false;
get started() {
return this._started;
}
constructor(props) {
this.props = props;
}
start() {
if (this._started || !this.props.canvas) {
return;
}
this._started = true;
this._intersectionObserver ||= new IntersectionObserver(entries => this.props.onIntersection(entries));
this._resizeObserver ||= new ResizeObserver(entries => this.props.onResize(entries));
this._intersectionObserver.observe(this.props.canvas);
try {
this._resizeObserver.observe(this.props.canvas, { box: 'device-pixel-content-box' });
}
catch {
this._resizeObserver.observe(this.props.canvas, { box: 'content-box' });
}
this._observeDevicePixelRatioTimeout = setTimeout(() => this._refreshDevicePixelRatio(), 0);
if (this.props.trackPosition) {
this._trackPosition();
}
}
stop() {
if (!this._started) {
return;
}
this._started = false;
if (this._observeDevicePixelRatioTimeout) {
clearTimeout(this._observeDevicePixelRatioTimeout);
this._observeDevicePixelRatioTimeout = null;
}
if (this._observeDevicePixelRatioMediaQuery) {
this._observeDevicePixelRatioMediaQuery.removeEventListener('change', this._handleDevicePixelRatioChange);
this._observeDevicePixelRatioMediaQuery = null;
}
if (this._trackPositionInterval) {
clearInterval(this._trackPositionInterval);
this._trackPositionInterval = null;
}
this._resizeObserver?.disconnect();
this._intersectionObserver?.disconnect();
}
_refreshDevicePixelRatio() {
if (!this._started) {
return;
}
this.props.onDevicePixelRatioChange();
this._observeDevicePixelRatioMediaQuery?.removeEventListener('change', this._handleDevicePixelRatioChange);
this._observeDevicePixelRatioMediaQuery = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
this._observeDevicePixelRatioMediaQuery.addEventListener('change', this._handleDevicePixelRatioChange, { once: true });
}
_trackPosition(intervalMs = 100) {
if (this._trackPositionInterval) {
return;
}
this._trackPositionInterval = setInterval(() => {
if (!this._started) {
if (this._trackPositionInterval) {
clearInterval(this._trackPositionInterval);
this._trackPositionInterval = null;
}
}
else {
this.props.onPositionChange();
}
}, intervalMs);
}
}
//# sourceMappingURL=canvas-observer.js.map