Skip to main content

Display Cursor Street Name

|

This example demonstrates how to display the name of the street at the cursor position when users tap on the map.

Live Demo

Overview

This example shows how to:

  • Enable cursor rendering on the map
  • Register touch callbacks to detect tap positions
  • Set cursor position based on screen coordinates
  • Retrieve street information at the cursor location
  • Display street names in a UI overlay

Code Implementation

Imports

First, import the required modules from the SDK:

import {
GemKit,
GemMap,
Coordinates,
PositionService
} from '@magiclane/maps-sdk';

Setup State Variables

Initialize global variables for map and UI elements:

let map: GemMap | null = null;
let currentStreetName = "";

// UI Elements
let streetNameDiv: HTMLDivElement;

Initialize Map with Cursor

Setup the map centered on Milan, Italy with cursor enabled:

index.ts
async function onMapCreated(gemMap: GemMap) {
map = gemMap;

// Center on Milan, Italy
map.centerOnCoordinates(new Coordinates({
latitude: 45.472358,
longitude: 9.184945
}), { zoomLevel: 80 });

// Enable cursor rendering
map.preferences.enableCursor = true;
map.preferences.enableCursorRender = true;

// Register touch callback to set cursor and display street name
map.registerTouchCallback(async (point: any) => {
await map!.setCursorScreenPosition(point);
const streets = map!.cursorSelectionStreets();
currentStreetName = (streets && streets.length > 0)
? (streets[0].name || "Unnamed street")
: "Unnamed street";
updateStreetNameUI(currentStreetName);
});
}

Initialize GemKit and Map View

Setup the map container and initialize the SDK:

index.ts
window.addEventListener('DOMContentLoaded', async () => {
const gemKit = await GemKit.initialize(projectApiToken);
await PositionService.instance;

const container = document.getElementById('map-container');
if (!container) throw new Error('Map container not found');

const viewId = 2;
const wrapper = gemKit.createView(viewId, onMapCreated);
if (wrapper) container.appendChild(wrapper);

// Create the street name display (hidden by default)
updateStreetNameUI("");
});

Display Street Name UI

Create and update the street name overlay:

index.ts
function updateStreetNameUI(name: string) {
if (!streetNameDiv) {
streetNameDiv = document.createElement('div');
streetNameDiv.style.cssText = `
position: fixed; bottom: 25px; left: 50%; transform: translateX(-50%);
background: #fff; color: #222; border-radius: 8px; padding: 8px 16px;
font-size: 1.1em; box-shadow: 0 2px 10px rgba(0,0,0,0.15); z-index: 2000;
min-width: 120px; text-align: center;
`;
document.body.appendChild(streetNameDiv);
}
streetNameDiv.textContent = name;
streetNameDiv.style.display = name ? 'block' : 'none';
}

Utility Functions

Display temporary status messages:

index.ts
function showMessage(message: string, duration = 3000) {
let msgDiv = document.getElementById('status-msg');
if (!msgDiv) {
msgDiv = document.createElement('div');
msgDiv.id = 'status-msg';
msgDiv.style.cssText = `
position: fixed; top: 20px; left: 50%; transform: translateX(-50%);
background: #333; color: #fff; padding: 12px 20px; border-radius: 8px;
z-index: 2000; font-size: 1em;
`;
document.body.appendChild(msgDiv);
}
msgDiv.textContent = message;
setTimeout(() => {
msgDiv.textContent = '';
}, duration);
}

Key Features

Enable Cursor

Configure map preferences to enable cursor functionality:

map.preferences.enableCursor = true;
map.preferences.enableCursorRender = true;

Properties:

  • enableCursor - Enable cursor detection and selection
  • enableCursorRender - Render cursor visually on map

Touch Callback Registration

Register a callback to handle tap events:

map.registerTouchCallback(async (point: any) => {
// Handle touch event
});

Callback Parameter:

  • point - Screen coordinates {x, y} where user tapped

Set Cursor Position

Update cursor to tapped screen position:

await map.setCursorScreenPosition(point);

This method:

  • Sets the cursor to the specified screen coordinates
  • Triggers internal selection logic
  • Enables retrieval of street information

Retrieve Street Information

Get streets at cursor position:

const streets = map.cursorSelectionStreets();

Return Value:

  • Array of street objects at cursor location
  • Each street has a name property
  • Empty array if no streets found

Handle Unnamed Streets

Provide fallback for streets without names:

currentStreetName = (streets && streets.length > 0) 
? (streets[0].name || "Unnamed street")
: "Unnamed street";

This ensures the UI always displays meaningful text.

Dynamic UI Display

Show/hide street name based on availability:

streetNameDiv.style.display = name ? 'block' : 'none';

The overlay only appears when a street name is available.

Bottom-Centered Overlay

Position the street name at the bottom center:

position: fixed; 
bottom: 25px;
left: 50%;
transform: translateX(-50%);

This creates a clear, non-intrusive display area.

Implementation Details

  • Lazy Initialization: Street name div created on first use
  • Async Operations: setCursorScreenPosition is awaited before retrieving streets
  • Null Checking: Verify streets array exists and has elements
  • Fallback Text: Display "Unnamed street" for unnamed or missing streets
  • Visual Design: White background with shadow for readability
  • Z-index: 2000 ensures overlay appears above map
  • Centering: Transform translate for perfect horizontal centering

Use Cases

  • Navigation Apps: Show current street name during navigation
  • Real Estate Apps: Display property street information
  • Delivery Apps: Confirm delivery address street
  • City Exploration: Learn street names while browsing the map
  • Address Selection: Help users confirm selected location
  • Educational Apps: Teach geography and street layouts
  • Tourist Apps: Identify street names in foreign cities

Advanced Features

Multiple Streets

Handle intersections with multiple streets:

if (streets && streets.length > 1) {
const streetNames = streets.map(s => s.name).join(" / ");
updateStreetNameUI(streetNames);
}

Street Details

Access additional street properties:

streets.forEach(street => {
console.log('Street:', street.name);
console.log('Type:', street.type);
// Additional properties may be available
});

Custom Styling

Customize the overlay appearance:

streetNameDiv.style.cssText = `
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
font-weight: bold;
border: 2px solid #fff;
`;

Next Steps