Skip to content

Commit

Permalink
Silence webgl context event when map is removed
Browse files Browse the repository at this point in the history
  • Loading branch information
sebstryczek committed Dec 17, 2024
1 parent c9886b9 commit 10f87f0
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 23 deletions.
42 changes: 37 additions & 5 deletions src/Map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
combineTransformRequest,
computeLabelsLocalizationMetrics,
displayNoWebGlWarning,
displayWebGLContextLostWarning,
replaceLanguage,
} from "./tools";
import { getBrowserLanguage, Language, type LanguageInfo } from "./language";
Expand Down Expand Up @@ -186,6 +185,7 @@ export type MapOptions = Omit<MapOptionsML, "style" | "maplibreLogo"> & {
*/
// biome-ignore lint/suspicious/noShadowRestrictedNames: we want to keep consitency with MapLibre
export class Map extends maplibregl.Map {
private options: MapOptions;
private isTerrainEnabled = false;
private terrainExaggeration = 1;
private primaryLanguage: LanguageInfo;
Expand Down Expand Up @@ -250,6 +250,9 @@ export class Map extends maplibregl.Map {
// biome-ignore lint/performance/noDelete: <explanation>
delete superOptions.style;
super(superOptions);

this.options = options;

this.setStyle(style);

if (requiresUrlMonitoring) {
Expand Down Expand Up @@ -642,14 +645,43 @@ export class Map extends maplibregl.Map {

// Display a message if WebGL context is lost
this.once("load", () => {
this.getCanvas().addEventListener("webglcontextlost", (e) => {
console.warn(e);
displayWebGLContextLostWarning(options.container);
this.fire("webglContextLost", { error: e });
this.getCanvas().addEventListener("webglcontextlost", (event) => {
if (this._removed === true) {
/**
* https://github.com/maplibre/maplibre-gl-js/blob/main/src/ui/map.ts#L3334
*/
console.warn("[webglcontextlost]", "WebGL context lost after map removal. This is harmless.");
return
}

console.warn("[webglcontextlost]", "Unexpected loss of WebGL context!");

this.fire("webglContextLost", event);
});
});
}

/**
* Recreates the map instance with the same options.
* Useful for WebGL context loss.
*/
public recreate() {
const cameraOptions: maplibregl.CameraOptions = {
center: this.getCenter(),
zoom: this.getZoom(),
bearing: this.getBearing(),
pitch: this.getPitch(),
};

this.remove();

Object.assign(this, new Map({ ...this.options }));

this.once("load", () => {
this.jumpTo(cameraOptions);
});
}

/**
* Set the duration (millisec) of the terrain animation for growing or flattening.
* Must be positive. (Built-in default: `1000` milliseconds)
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ export {
getLanguageInfoFromKey,
} from "@maptiler/client";

export { getWebGLSupportError } from "./tools";
export { getWebGLSupportError, displayWebGLContextLostWarning } from "./tools";
export { config, SdkConfig } from "./config";
export * from "./language";
export { type Unit } from "./unit";
Expand Down
21 changes: 4 additions & 17 deletions src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,28 +204,15 @@ export function displayNoWebGlWarning(container: HTMLElement | string) {
}

/**
* Display an error message in the Map div if WebGL2 is not supported
* Display a warning message in the Map div if the WebGL context was lost
*/
export function displayWebGLContextLostWarning(container: HTMLElement | string) {
export function displayWebGLContextLostWarning(map: MapSDK) {
const webglError = "The WebGL context was lost.";

let actualContainer: HTMLElement | null = null;

if (typeof container === "string") {
actualContainer = document.getElementById(container);
} else if (container instanceof HTMLElement) {
actualContainer = container;
}

if (!actualContainer) {
throw new Error("The Map container must be provided.");
}

const container: HTMLElement = map.getContainer();
const errorMessageDiv = document.createElement("div");
errorMessageDiv.innerHTML = webglError;
errorMessageDiv.classList.add("webgl-warning-div");
actualContainer.appendChild(errorMessageDiv);
// throw new Error(webglError);
container.appendChild(errorMessageDiv);
}

/**
Expand Down

0 comments on commit 10f87f0

Please sign in to comment.