Annotations and Reverse Geocoding

This sample demonstrates three MapKit JS features:

  1. Placing named annotations (with custom glyphs)
  2. Using mapkit.Map-specific events, in this case: single-tap
  3. Looking up a place from a coordinate (reverse geocoding)
Try clicking (or tapping) on the map to place an annotation.

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">

<style>
#map-container {
    height: 600px;
}
</style>

<script src="https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.core.js"
    crossorigin async
    data-callback="initMapKit"
    data-libraries="map,annotations,services"
    data-token="IMPORTANT: ADD YOUR TOKEN HERE">
</script>

<script type="module">
// Wait for MapKit JS to be ready to use.
const setupMapKitJs = async() => {
    // If MapKit JS is not yet loaded...
    if (!window.mapkit || window.mapkit.loadedLibraries.length === 0) {
        // ...await <script>'s data-callback (window.initMapKit).
        await new Promise(resolve => { window.initMapKit = resolve });
        // Clean up.
        delete window.initMapKit;
    }
};

const main = async() => {
    await setupMapKitJs();

    // Create the Map and Geocoder.
    const map = new mapkit.Map("map-container");
    const geocoder = new mapkit.Geocoder({ language: "en-US" });

    // Create the "Event" annotation, setting properties in the constructor.
    const event = new mapkit.Coordinate(37.7831, -122.4041);
    const eventAnnotation = new mapkit.MarkerAnnotation(event, {
        color: "#4eabe9",
        title: "Event",
        glyphText: "\u{1F37F}" // Popcorn Emoji
    });

    // Create the "Work" annotation, setting properties after construction.
    const work = new mapkit.Coordinate(37.3349, -122.0090);
    const workAnnotation = new mapkit.MarkerAnnotation(work);
    workAnnotation.color = "#969696";
    workAnnotation.title = "Work";
    workAnnotation.subtitle = "Apple Park";
    workAnnotation.selected = "true";
    workAnnotation.glyphText = "\u{F8FF}"; // Apple Symbol

    // Add and show both annotations on the map.
    map.showItems([eventAnnotation, workAnnotation]);

    // This contains the user-set single-tap annotation.
    let clickAnnotation = null;

    // Add or move an annotation when a user single-taps an empty space.
    map.addEventListener("single-tap", event => {
        if (clickAnnotation) {
            map.removeAnnotation(clickAnnotation);
        }

        // Get the clicked coordinate and add an annotation there.
        const point = event.pointOnPage;
        const coordinate = map.convertPointOnPageToCoordinate(point);

        clickAnnotation = new mapkit.MarkerAnnotation(coordinate, {
            title: "Loading...",
            color: "#c969e0"
        });

        map.addAnnotation(clickAnnotation);

        // Look up the address with the Geocoder's Reverse Lookup Function.
        geocoder.reverseLookup(coordinate, (error, data) => {
            const first = (!error && data.results) ? data.results[0] : null;
            clickAnnotation.title = (first && first.name) || "";
        });
    });

};

main();

</script>

</head>

<body>
    <div id="map-container"></div>
</body>
</html>