Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Check if WebGL is supported 🔗

Check for WebGL browser support.

// src/main.rs 

use maplibre_gl_js::interface::MapOptions;
use web_sys::{HtmlCanvasElement, js_sys::Reflect, wasm_bindgen::JsValue};
use yew::{Html, function_component, html, use_effect, use_state};

fn is_webgl_supported() -> bool {
    let window = web_sys::window().expect("Window should be available");
    let document = window.document().expect("The document should be available");

    // Check if the class is directly missing
    if let Err(_) = Reflect::get(&window, &"WebGLRenderingContext".into()) {
        return false;
    }

    let canvas: HtmlCanvasElement = Into::<JsValue>::into(
        document
            .create_element("canvas")
            .expect("Creating an element should work"),
    )
    .into();

    // Obtain context
    let context = match (canvas.get_context("webgl2"), canvas.get_context("webgl")) {
        // If a JsException is raised, then it is supported but disabled
        (Err(_), _) => return false,
        (_, Err(_)) => return false,
        // No context available, then it is unsupported
        (Ok(None), Ok(None)) => return false,
        // Context is available
        (Ok(Some(webgl2_context)), _) => webgl2_context,
        (Ok(None), Ok(Some(webgl_context))) => webgl_context,
    };

    // Check if the context was properly initialized
    Reflect::get(&context, &"getParameter".into()).is_ok_and(|v| {
        v.js_typeof()
            .as_string()
            .expect("Result should be a string")
            == "function"
    })
}

#[function_component(App)]
fn app() -> Html {
    let webgl_supported = is_webgl_supported();
    let map_rendered = use_state(|| false);
    use_effect(move || {
        if *map_rendered {
            return;
        }
        if webgl_supported {
            MapOptions::new("map")
                .with_style("https://demotiles.maplibre.org/style.json")
                .with_center([-74.5, 40.])
                .with_zoom(2.)
                .build()
                .expect("Creating a map should work");
            map_rendered.set(true);
        }
    });
    html! { if webgl_supported { <div id="map"></div> } else { <p>{"WebGl not supported"}</p> } }
}

fn main() {
    wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
    console_error_panic_hook::set_once();
    yew::Renderer::<App>::new().render();
}
<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon"type="image/x-icon" href="data:image/x-icon;,">
    <title>Check if WebGL is supported</title>
    <link rel="scss" data-trunk href="scss/style.scss" />
    <script src="https://unpkg.com/maplibre-gl@^5.12.0/dist/maplibre-gl.js"></script>
    <link href="https://unpkg.com/maplibre-gl@^5.12.0/dist/maplibre-gl.css" rel="stylesheet" />
  </head>
  <body>loading...</body>
</html>
/* scss/style.scss */

body { margin: 0; padding: 0; }
html, body, body > div { height: 100%; }