Skip to content
Get Features Under the Mouse Pointer

Get Features Under the Mouse Pointer in Maptoolkit Maps JS

map.queryRenderedFeatures in Maptoolkit Maps JS returns all features from any rendered layer that intersect a given point or bounding box on screen. By calling it on each mousemove event with the cursor position, you can display live feature data for whatever the user points at. Use this to build inspector panels, map debuggers, or hover tooltips that show properties from any layer without attaching separate event listeners to each one.

const API_KEY = 'YOUR_API_KEY';

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
        center: [11.39085, 47.27574],
        zoom: 14,
        attributionControl: { compact: false }
    });

    map.addControl(new maptoolkit.NavigationControl(), 'top-right');

    map.on('mousemove', (e) => {
        const features = map.queryRenderedFeatures(e.point);
        const featuresEl = document.getElementById('features');
        if (features.length === 0) {
            featuresEl.innerHTML = '<strong>Features under cursor:</strong><br>None';
            return;
        }
        const info = features.slice(0, 5).map(f =>
            `<div style="border-top:1px solid #eee;margin-top:4px;padding-top:4px;"><em>${f.layer.id}</em> (${f.layer.type})</div>`
        ).join('');
        featuresEl.innerHTML = `<strong>Features under cursor:</strong>${info}`;
    });
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Get Features Under the Mouse Pointer - Maptoolkit Maps JS</title>
    <meta property="og:description" content="Query and display map features under the mouse cursor using queryRenderedFeatures." />
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
    <style>
        html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
        #map { width: 100%; height: 100%; }
        #features {
            position: absolute;
            top: 10px;
            right: 10px;
            background: white;
            padding: 10px 14px;
            border-radius: .4rem;
            font-family: sans-serif;
            font-size: 12px;
            max-width: 240px;
            max-height: 300px;
            overflow-y: auto;
        }
    </style>
</head>
<body>
<div id="map"></div>
<div id="features"><strong>Features under cursor:</strong><br>Move the mouse over the map.</div>
<script>
    const API_KEY = 'YOUR_API_KEY';

    const map = new maptoolkit.Map({
        container: 'map',
        apiKey: API_KEY,
        style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
        center: [11.39085, 47.27574],
        zoom: 14,
        attributionControl: { compact: false }
    });

    map.addControl(new maptoolkit.NavigationControl(), 'top-right');

    map.on('mousemove', (e) => {
        const features = map.queryRenderedFeatures(e.point);
        const featuresEl = document.getElementById('features');
        if (features.length === 0) {
            featuresEl.innerHTML = '<strong>Features under cursor:</strong><br>None';
            return;
        }
        const info = features.slice(0, 5).map(f =>
            `<div style="border-top:1px solid #eee;margin-top:4px;padding-top:4px;"><em>${f.layer.id}</em> (${f.layer.type})</div>`
        ).join('');
        featuresEl.innerHTML = `<strong>Features under cursor:</strong>${info}`;
    });
</script>
</body>
</html>

Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.

Use the Maptoolkit Connector. Create an interactive map with zoom level 14, centered around [11.39085, 47.27574]. Display a panel showing map features under the mouse cursor using queryRenderedFeatures.

How it works

queryRenderedFeatures takes a pixel position, e.point, not a geographic one. It answers “what is drawn here”, so it only ever returns features currently rendered: anything filtered out, outside the viewport, or hidden behind a zoom range is not in the result even though it exists in the data.

Called with no layer filter it returns features from every layer, which on a full basemap is a long list including roads, landuse and labels. Passing { layers: ['your-layer'] } narrows it to what you care about, and is much faster.

Each returned feature carries properties, layer and source, so you can tell which layer answered as well as what the feature is.

One feature can appear more than once when its geometry is split across tile boundaries. De-duplicate on a stable id if you are counting rather than displaying.

For querying the underlying data rather than what is on screen, querySourceFeatures is the counterpart.

Next steps

Everything under the cursor is too much to show, so the next step is deciding what you care about and querying only those layers. After that, the useful move is presenting the feature rather than listing it: a popup, a panel, a highlight.

The Schema Reference is what tells you which fields are worth surfacing, and it is also how you find out that something you want to show is not in the tiles at all.