KmlLayer Migration Paths

Introduction

The purpose of this guide is to cover the most common uses of the KmlLayer and provide corresponding migration paths to alternative implementations. This information is intended for developers who need to transition from using KmlLayer due to its scheduled deprecation. The last version which supports KmlLayer is 3.65, to be decommissioned in May 2027.

Your migration path depends on how you are using the KmlLayer:

KML file to style boundary/border/area of interest information

For developers using KmlLayer to display or style administrative boundaries—such as highlighting a specific country, state, or locality—Google Maps Platform recommends migrating to Data-driven styling (DDS) for boundaries.

Migration Recommendation: Data-driven Styling for Boundaries

Data-driven styling for boundaries provides direct access to Google's administrative boundary polygons, allowing you to apply custom styles (fill and stroke) to these regions without needing to host or manage external KML files.

Available FeatureType

Administrative areas are categorized by function and arranged by levels. The following feature types are supported for styling:

  • COUNTRY: The national political entity.
  • ADMINISTRATIVE_AREA_LEVEL_1: A first-order civil entity below the country level (e.g., states in the US).
  • ADMINISTRATIVE_AREA_LEVEL_2: A second-order civil entity below the country level (e.g., counties in the US).
  • LOCALITY: An incorporated city or town.
  • POSTAL_CODE: Postal codes as used for mail.
  • SCHOOL_DISTRICT: Unified, elementary, or secondary school districts.

See boundary coverage for regions where these feature types are available.

How to Highlight an Area

To style a specific region, you must target it by its Place ID.

  • Setup: You must use a Map ID configured for JavaScript Vector map type and enable the Feature layer available in the Google Cloud Console.
  • Implementation: use the Style a boundary polygon sample code.

Restricting Panning to an Area

To prevent users from navigating outside the bounding box of your highlighted area, you can use the restriction option within the MapOptions.

The restriction object defines a latLngBounds that limits the map's viewable area. See the documentation for more details on how the restriction works.

// Restrict panning to a specific bounding box
restriction: {
  latLngBounds: {
    north: 47.8,
    south: 45.8,
    east: 10.5,
    west: 5.9,
  },
  strictBounds: true,
},

Summary Migration Implementation

Here is a complete example of how to use Data-driven styling for boundaries and a region restriction to focus the map around a specific area.

const myTargetRegion = "ChIJYW1Zb-9kjEcRFXvLDxG1Vlw"; // Place ID for Switzerland

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 46.8, lng: 8.2 },
    zoom: 9,
    mapId: "YOUR_MAP_ID", // Required for DDS
    // Restrict panning to a specific bounding box
    restriction: {
    // Bounding box for Switzerland
      latLngBounds: {
        north: 47.8,
        south: 45.8,
        east: 10.5,
        west: 5.9,
      },
      strictBounds: true,
    },
  });

  // Access the Country layer and style a specific region by Place ID
  const countryLayer = map.getFeatureLayer("COUNTRY");
  countryLayer.style = (options) => {
    if (options.feature.placeId === myTargetRegion) {
      return {
        fillColor: "#FF0000",
        fillOpacity: 0.5,
        strokeColor: "#FF0000",
        strokeWeight: 2,
      };
    } else {
    // Style everything else whited out, to make the area of interest pop out more.
      return {
        fillColor: '#ffffff',
        fillOpacity: 0.8,
      };
    }
  };
}

KML file with vector data (Points/Polylines/Boundaries/Polygons)

Migration Recommendation: Data-driven Styling for Datasets

Google recommends the below path for displaying publicly available geographic data while gaining more control over styling and performance.

Data-driven styling for datasets lets you upload your own geospatial data (KML, GeoJSON, or CSV), apply custom styling based on data attributes, and display features on vector maps.

1. Setup and Upload

Unlike KmlLayer, which fetches a URL at runtime, DDS requires you to host the data as a dataset in the Google Cloud Console.

  • Create a Map ID: Use a Map ID configured for the Vector map type.
  • Upload the Dataset: Upload your KML file to the Google Cloud Console to generate a unique Dataset ID. Read the full documentation on how to manage Maps Datasets for more details.
  • Display the Dataset: Once you have created a Dataset ID, you need to associate the Dataset with a Maps Style and a Map ID. You will then use the Dataset ID to actually display the data on the map. Read the full documentation on how to Add a dataset to a map for all the details.
  • Note the KML requirements for Datasets, if you decide to import your data from the KML format.

2. Setting the Viewport to the Data

KmlLayer automatically pans and zooms to the data location by default. With DDS for datasets, this behavior is not automatic and must be implemented manually.

  • Hardcoded Restrictions: If the data area is static, use the restriction option in MapOptions to lock the viewport to specific bounds.
  • Dynamic Zooming: To dynamically set the viewport, you can use map.fitBounds() with the bounding box of your dataset.

3. Styling from Feature Attributes

KML files often contain style information (like colors) that DDS does not automatically apply. You must create a client-side style function that reads attributes from the dataset features to apply colors and opacity. Consult the developer documentation on how to style your data for the full details.

Example: Styling Function using Attributes

The following example demonstrates how to create a style function that reads background_color and opacity attributes directly from the uploaded dataset:

/**
 * Migration example: Styling features from dataset attributes.
 */
function styleDDSLayer(map, datasetId) {
  const datasetLayer = map.getDatasetFeatureLayer(datasetId);

  // Set the style function
  datasetLayer.style = (params) => {
    // Access attributes defined in your KML/Dataset
    const featureAttributes = params.feature.datasetAttributes;

    // Read style values from attributes, with fallback defaults
    const fillColor = featureAttributes['background_color'] || '#4285F4';
    const fillOpacity = parseFloat(featureAttributes['opacity']) || 0.5;
    const strokeColor = featureAttributes['border_color'] || '#34A853';

    return {
      fillColor: fillColor,
      fillOpacity: fillOpacity,
      strokeColor: strokeColor,
      strokeWeight: 2,
    };
  };
}

For further details on implementing interactions and styling, refer to the Data-driven styling for datasets overview and Datasets API for dynamic data.

Migration Recommendation: Client-Side Rendering with GeoJSON

For developers migrating from KmlLayer to client-side rendering with GeoJSON, Google Maps Platform recommends a migration path that involves converting your data format and using the Data layer to render and style features directly in the browser.

Client-side rendering using the Data layer provides a highly flexible way to display geographic data. Unlike KmlLayer, which is rendered on Google's servers, the Data layer lets you interact with features as standard JavaScript objects. Note, however, that for large datasets you might prefer server-side processing and rendering of your data, such as with Data-driven Styling for Datasets.

1. Convert KML to GeoJSON

The first step is to convert your KML files into GeoJSON. This can be done using several popular open-source tools:

  • ogr2ogr: Part of the GDAL suite, this powerful command-line utility can convert between many vector formats.
ogr2ogr -f GeoJSON output.json input.kml
  • togeojson: A tiny, well-tested tool designed specifically for converting KML and GPX to GeoJSON.
togeojson input.kml > output.json

2. Setting the Viewport to the Data

While KmlLayer automatically pans and zooms to the data location, the Data layer does not. To set the viewport to fit your GeoJSON data, you must manually calculate the bounding box and call map.fitBounds().

3. Styling from Feature Attributes

In the Data layer, you can define a style function that reads attributes (properties) directly from each GeoJSON feature to determine its appearance.

Example: Styling Function and Viewport Adjustment

The following example demonstrates how to load GeoJSON data, calculate its bounds to set the viewport, and style features based on their attributes:

/**
 * Migration example: Loading GeoJSON, fitting viewport, and styling from attributes.
 */
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: -28, lng: 137 },
  });

  // Load the GeoJSON data
  map.data.loadGeoJson('path/to/your/data.json', null, (features) => {
    // Adjust viewport to show all loaded features
    const bounds = new google.maps.LatLngBounds();
    features.forEach((feature) => {
      feature.getGeometry().forEachLatLng((latlng) => {
        bounds.extend(latlng);
      });
    });
    map.fitBounds(bounds);
  });

  // Set the style function to read from GeoJSON properties
  map.data.setStyle((feature) => {
    // Access attributes defined in your GeoJSON properties
    const fillColor = feature.getProperty('background_color') || '#4285F4';
    const opacity = parseFloat(feature.getProperty('opacity')) || 0.5;
    const strokeColor = feature.getProperty('border_color') || '#34A853';

    return {
      fillColor: fillColor,
      fillOpacity: opacity,
      strokeColor: strokeColor,
      strokeWeight: 2,
      visible: true
    };
  });
}

For more information on using the Data layer, see the Importing GeoJSON into Maps documentation.

Migration Path: Client-Side Rendering with 3rd party libraries

For developers seeking other alternatives to the KmlLayer, there are several community-maintained libraries that render KML data on the Google Maps Platform JavaScript API.

1. deck.gl

deck.gl is a high-performance WebGL-powered visualization framework. It can be used as a near drop-in replacement for KML rendering through its GoogleMapsOverlay and GeoJsonLayer.

  • Canvas Requirement: To use deck.gl effectively, you must convert your map to use the Vector map type (which renders to a canvas element) with its WebGL rendering capabilities.
  • KML Support: Geometry parsing is handled by @loaders.gl/kml, which converts KML into GeoJSON. Note that some KML features like complex styles, icons, and NetworkLinks may require additional manual implementation.
  • Documentation: deck.gl Documentation | loaders.gl KML Loader.
  • Examples:
    • The deckgl-kml-updated sample on the Google Maps GitHub repository demonstrates how to use deck.gl to render KML data that is updated in real-time.
    • The deckgl-kml sample demonstrates how to use deck.gl to render KML data.

2. geoxml3

geoxml3 is a KML processor specifically designed for the Google Maps JavaScript API v3. It parses KML locally in the browser and renders the data as standard Google Maps API objects like Markers, Polylines, and Polygons.

  • Standard Map Support: Unlike WebGL-based solutions, geoxml3 works on standard Google Maps JS API v3 maps without requiring a specific rendering mode.
  • Caveats:
    • Limited KMZ Support: The library does not fully support KMZ files natively; unzipping KMZ archives typically requires integration with additional 3rd party scripts like ZipFile.complete.js.
    • Unsupported Elements: Features such as 3D geometries, complex labels, and certain newer KML elements are not supported.
  • Documentation: geoxml3 GitHub Repository.

KML file with interactive elements

Migration Recommendation: Data-driven Styling for Datasets

For developers migrating from KmlLayer to Data-driven styling (DDS) for datasets, this guide explains how to transition from automatic KML interactions to custom, high-performance interactions like mouse clicks and hover.

Initial Setup

Before implementing interactions, ensure you have followed the setup steps from the KML Migration: Vector Data guide:

  • Map ID: Configure a Map ID for the Vector map type.
  • Upload: Upload your KML data to the Google Cloud Console to obtain a Dataset ID.
  • Layer Access: Use map.getDatasetFeatureLayer(datasetId) to access the interactive layer.

1. Handling Interaction Events

In KmlLayer, feature clicks are handled automatically by the API to pop up an info window. With DDS for datasets, you must manually register listeners for mouse events on the dataset layer.

  • click: Triggered when a user clicks on a feature.
  • mousemove: Triggered when the cursor moves over a feature, useful for hover effects.

2. Dynamic Styling (Hover Effect)

Because DDS styles are applied globally to the layer, you should maintain a state variable to track which feature is being interacted with and re-apply the style.

let currentFeatureId = null;

function initInteraction(map, datasetId) {
  const datasetLayer = map.getDatasetFeatureLayer(datasetId);

  // Apply the style function
  datasetLayer.style = (params) => {
    const isHovered = params.feature.datasetAttributes['id'] === currentFeatureId;
    return {
      strokeColor: 'green',
      strokeWeight: isHovered ? 4.0 : 2.0, // Bold border on hover
      fillColor: 'green',
      fillOpacity: isHovered ? 0.5 : 0.3,
    };
  };

  // Add interaction listeners
  datasetLayer.addListener('mousemove', (event) => {
    if (event.features.length > 0) {
      currentFeatureId = event.features[0].datasetAttributes['id'];
      datasetLayer.style = datasetLayer.style; // Re-apply style to reflect changes
    }
  });

  // Clear hover state when the mouse leaves the features
  map.addListener('mousemove', () => {
    if (currentFeatureId !== null) {
      currentFeatureId = null;
      datasetLayer.style = datasetLayer.style;
    }
  });
}

3. Displaying HTML from the description Attribute

In KML, the <description> tag often contains HTML for the default info window. When this data is imported as a dataset, the description becomes a feature attribute. To render it, pass the string directly to a standard google.maps.InfoWindow.

const infoWindow = new google.maps.InfoWindow();

datasetLayer.addListener('click', (event) => {
  if (event.features.length > 0) {
    const feature = event.features[0];
    // Access the HTML description attribute
    const htmlContent = feature.datasetAttributes['description'];

    infoWindow.setContent(htmlContent);
    infoWindow.setPosition(event.latLng);
    infoWindow.open(map);
  }
});

4. Custom InfoWindow with ExtendedData

If your KML uses <ExtendedData> to store custom name/value pairs, these are mapped to datasetAttributes. You can iterate through these attributes to build a custom HTML display.

function createCustomContent(feature) {
  const attributes = feature.datasetAttributes;
  const container = document.createElement("div");
  container.style.padding = "10px";
  container.innerHTML = "<h3>Feature Details</h3><dl></dl>";

  const dl = container.querySelector("dl");

  // Iterate through all data attributes imported from KML ExtendedData
  for (const key in attributes) {
    const dt = document.createElement("dt");
    dt.style.fontWeight = "bold";
    dt.textContent = key;

    const dd = document.createElement("dd");
    dd.textContent = attributes[key];

    dl.appendChild(dt);
    dl.appendChild(dd);
  }
  return container;
}

datasetLayer.addListener('click', (event) => {
  if (event.features.length > 0) {
    const content = createCustomContent(event.features[0]);
    infoWindow.setContent(content);
    infoWindow.setPosition(event.latLng);
    infoWindow.open(map);
  }
});

For more advanced visualization techniques, see the developer documentation on how to style data features.

Migration Recommendation: Client-Side Rendering with GeoJSON

For developers migrating from KmlLayer to client-side rendering with GeoJSON and the Data layer, this guide explains how to transition from automatic KML interactions to custom, event-driven interactions and dynamic styling.

Initial Setup

Before implementing interactions, you must convert your KML data to GeoJSON and load it into the Data layer. Refer to the Migration Recommendation: Client-Side Rendering with GeoJSON guide for details on using tools like ogr2ogr or togeojson and initializing the map with map.data.loadGeoJson().

1. Automatic versus Manual Interactions

A key difference between these layers is how they handle user input:

  • KmlLayer: Automatically handles feature clicks and displays an InfoWindow containing the KML and data.
  • Data Layer: Does not display InfoWindow objects automatically. You must manually add event listeners to capture user interactions and write code to display data.

2. Handling Interaction Events

To make GeoJSON features interactive, use the addListener() method on the map.data object. Common events include:

  • click: Used to trigger info windows or selection logic.
  • mouseover / mouseout: Used for hover effects and highlighting.

3. Displaying HTML Descriptions in an InfoWindow

When KML is converted to GeoJSON, the <description> tag (which often contains HTML) is typically mapped to a property named description. You can use feature.getProperty('description') to retrieve this string and render it inside a standard google.maps.InfoWindow.

const infoWindow = new google.maps.InfoWindow();

// Handle clicks to show the HTML description
map.data.addListener('click', (event) => {
  // Access the 'description' property from the GeoJSON feature
  const htmlContent = event.feature.getProperty('description');

  if (htmlContent) {
    infoWindow.setContent(htmlContent);
    infoWindow.setPosition(event.latLng);
    infoWindow.open(map);
  }
});

4. Custom InfoWindows and ExtendedData

If your original KML utilized <ExtendedData>, these name-value pairs are converted into GeoJSON properties. Because the Data layer doesn't have a default UI for these, you must implement a custom InfoWindow to iterate through and display them.

You can access these attributes using event.feature.getProperty('attribute_name') and construct a custom HTML string or DOM element to pass to the infoWindow.setContent() method.

5. Dynamic Styling (Hover Effects)

The Data layer lets you update feature styles programmatically in response to events. Use overrideStyle() to temporarily change a feature's appearance (e.g., on hover) and revertStyle() to return to the global style.

// Set a base style for all features
map.data.setStyle({
  fillColor: 'blue',
  strokeWeight: 1
});

// Highlight feature on mouseover
map.data.addListener('mouseover', (event) => {
  map.data.revertStyle(); // Clear previous highlights
  map.data.overrideStyle(event.feature, {strokeWeight: 8});
});

// Revert style on mouseout
map.data.addListener('mouseout', (event) => {
  map.data.revertStyle();
});

For more detailed implementation details, see the documentation on Data Layer: Event Handling and Data Layer: Dynamic Styling.

Migration Path: Client-Side Rendering with 3rd party libraries

For developers migrating from KmlLayer to third-party solutions, this guide focuses on handling interactive data such as mouse clicks and dynamic events using deck.gl and geoxml3.

Initial Setup

Before implementing interactions, ensure you have followed the setup steps from the Migration Path: Client-Side Rendering with 3rd party libraries guide. This includes:

  • deck.gl: Converting your map to use the Vector map type (canvas requirement).
  • geoxml3: Serving the library scripts from your own host and managing Cross-Origin Resource Sharing (CORS).

1. Interactive Data with deck.gl

deck.gl supports KML as a direct input format and automatically handles feature interactions like clicks based on the data provided in the KML file.

  • KMLLoader Handling: Using the @loaders.gl/kml module, geometry and properties are parsed into a format that deck.gl uses to trigger interaction events natively.
  • Feature Clicks: When a feature is clicked, deck.gl can capture the event and display associated metadata (like <name> or <description>).
  • Example: The deckgl-kml-updated sample demonstrates real-time KML rendering where hovering over earthquake markers displays detailed event information.

2. Interactive Data with geoxml3

geoxml3 parses the KML locally in the browser, extracts style information, and generates standard Google Maps API objects that retain their interactivity.

  • Native Style Extraction: The library grabs <Style> and <StyleMap> elements from the KML to apply them to the generated Markers, Polylines, and Polygons.
  • Click Handlers: By default, geoxml3 provides click handlers for these objects. You can also define custom callback functions (createMarker, createOverlay) during parser instantiation to implement your own selection logic or sidebar updates.
  • Example: This example demonstrates how to use geoxml3 to render KML, with customization like circle markers with interaction, such as clicking on the markers to display earthquake information.
  • Usage Pattern:
var myParser = new geoXML3.parser({
  map: map,
  processStyles: true, // Automatically handle KML styles
  afterParse: function(doc) {
    // Code to run after the KML is fully parsed
  }
});
myParser.parse('interactive_data.kml');

KML file with imagery

For developers using KmlLayer to display imagery—such as maps with satellite-derived data, weather patterns, or historical blueprints—this guide outlines the migration paths to GroundOverlays or 3rd party parsers.

Migration Recommendation: Maps JavaScript API GroundOverlay

The recommended path for migrating imagery is to use the google.maps.GroundOverlay class. This lets you place an image on the map at specific geographic coordinates directly in your code.

1. Implementation

Instead of relying on a KML file to define the bounds, you specify the image URL and a LatLngBounds object representing the rectangle on the map.

  • Documentation: Ground Overlays Guide.
  • Image Preparation: If your image is georeferenced but not in the correct projection (EPSG:4326), you can use the open-source tool gdalwarp to warp the image for use with the Maps JS API.
gdalwarp -t_srs EPSG:4326 image.jp2 image.jpg

Migration Path: Using 3rd Party Libraries

If your workflow requires you to keep your data in KML format, third-party libraries like geoxml3 or deck.gl can be used to render imagery overlays.

Disclaimer: These third-party solutions are not supported by Google. However, they have been tested and should work for most use cases.

1. geoxml3

geoxml3 is a good option for parsing simple GroundOverlay elements locally in the browser and converting them into Google Maps API objects.

Example Usage:

const geoXmlParser = new geoXML3.parser({
    map: map,
    afterParse: function(doc) {
        console.log("Parsing complete. Number of documents: " + doc.length);
        const bounds = doc[0].gbounds;
        if (bounds && !bounds.isEmpty()) {
           map.fitBounds(bounds);
        }
    },
    createOverlay: function(groundOverlayData) {
        // Extract bounds and URL from parsed KML data
        const imageUrl = groundOverlayData.icon.href;
        const imageBounds = {
            north: parseFloat(groundOverlayData.latLonBox.north),
            south: parseFloat(groundOverlayData.latLonBox.south),
            east: parseFloat(groundOverlayData.latLonBox.east),
            west: parseFloat(groundOverlayData.latLonBox.west)
        };

        // Create the Google Maps GroundOverlay
        const nativeOverlay = new google.maps.GroundOverlay(imageUrl, imageBounds);
        nativeOverlay.setMap(map);
    }
});
geoXmlParser.parse('your_file.kml');

2. deck.gl

While deck.gl's standard GeoJsonLayer handles vector data, it can also support GroundOverlays through a manual implementation using the BitmapLayer.

This approach involves leveraging KMLLoader to parse the file and then explicitly defining a BitmapLayer with the image URL and coordinates extracted from the KML data.

Advanced Case: Tile Pyramids using gdal2tiles

For complex KML files containing imagery tile pyramids, migration is more difficult and requires extracting the imagery data.

  • Tool: gdal2tiles can extract data from a KMZ pyramid and produce standard Maps JavaScript API code to display the tiles. Note that the end result may require manual modification to be incorporated into an existing map.
gdal2tiles -z 10- -n -u https://yourhost.com/tiles/ -w google input.kmz

Handling KML files with network links requires a shift from the automatic, cloud-side fetching of KmlLayer to more explicit data management strategies.

Supported Solution: Data-driven Styling (DDS) for Datasets

Because Google Maps Platform datasets don't natively parse <NetworkLink> elements, you must choose a migration strategy based on your data structure:

  • Strategy A: Distinct Datasets (Best for User-Controlled Layers) Upload each KML file that was previously a network link as its own individual dataset in the Google Cloud Console. You can then use JavaScript to dynamically load and display these layers when needed by calling map.getDatasetFeatureLayer(datasetId) and adjusting its visibility or style.
  • Strategy B: Flattened KML File (Best for High-Performance Display) Combine all features from your various network-linked files into a single, comprehensive KML file before uploading it as a dataset. You can then use dynamic styling based on feature attributes to filter and display specific data subsets on the fly.

Updating Dynamic Data: To mimic the "auto-refresh" behavior of network links, use the Datasets API to programmatically upload a new version of your dataset whenever the source data changes.

Open-Source Solutions: deck.gl and geoxml3

Neither deck.gl nor geoxml3 provide robust support for parsing and automatically fetching KML <NetworkLink> elements.

deck.gl

deck.gl utilizes the KMLLoader (built on togeojson), which explicitly does not support NetworkLinks.

  • Why it is not a good solution: The parser is designed to be a synchronous, "fuss-free" converter that avoids making its own network requests to ensure reliability and simplicity. If your application relies on KML files that point to multiple other URLs, deck.gl won't automatically resolve them.

geoxml3

While geoxml3 was developed to parse KML for the Maps JS API, its support for network links is experimental and unmaintained.

  • Why it is not a good solution: The functionality exists only in a specific "network_link" branch that is old and not well-tested. Using this for production data migration is discouraged, as it may fail to handle complex link structures or modern security requirements like CORS.

Summary Recommendation

For a reliable migration, developers should avoid third-party parsers for files with network links and instead rebuild the data-fetching logic using the Datasets API. This ensures your data is managed securely within the Google Maps Platform infrastructure rather than relying on unmaintained client-side parsers.

Use KML to display Screen Overlays

For developers migrating from KmlLayer to modern alternatives like Data-driven styling (DDS), it is important to note that Screen Overlays are not supported in Datasets. To achieve the same effect of displaying fixed images, logos, or legends on top of the map, you must create Custom Controls using the Maps JavaScript API.

1. What to Look for in Your KML File

To build an equivalent Custom Control, examine the <ScreenOverlay> element in your KML file for the following key attributes:

  • <Icon>&lt;href>: The URL of the image you want to display.
  • <screenXY>: This defines where the overlay is positioned on the screen.
    • x=0, y=1 (fractions) corresponds to the Top Left.
    • x=1, y=1 corresponds to the Top Right.
    • x=0, y=0 corresponds to the Bottom Left.
    • x=1, y=0 corresponds to the Bottom Right.
  • <size>: Defines the width and height of the overlay.
  • <rotation>: Indicates if the image should be rotated.

2. Implementation: Creating a Custom Control

A Custom Control is essentially a standard HTML element (like a <div> or <img>) that you "push" into one of the map's predefined positions.

Mapping KML Positions to ControlPosition

The Maps JavaScript API uses the ControlPosition enum to anchor controls. Use the table below to map your KML <screenXY> to the appropriate JS API constant:

KML Position (screenXY) JS API ControlPosition
Top Left (x:0, y:1) TOP_LEFT (Legacy) or BLOCK_START_INLINE_START (Logical)
Top Right (x:1, y:1) TOP_RIGHT or BLOCK_START_INLINE_END
Bottom Left (x:0, y:0) BOTTOM_LEFT or BLOCK_END_INLINE_START
Bottom Right (x:1, y:0) BOTTOM_RIGHT or BLOCK_END_INLINE_END

3. Migration Example: Fixed Logo Overlay

The following example mimics a KML ScreenOverlay logo positioned in the Top Right of the map.

CSS Styling

Use CSS to define the size and appearance of your "overlay".

#logo-control {
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.8);
  margin: 10px;
  border-radius: 2px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.3);
}

#logo-control img {
  width: 150px; /* Equivalent to KML <size> */
  display: block;
}

JavaScript Implementation

Add the element to the map.controls array.

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 12,
    center: { lat: 41.85, lng: -87.65 },
  });

  // 1. Create the container for the overlay
  const logoControlDiv = document.createElement("div");
  logoControlDiv.id = "logo-control";

  // 2. Create the image (KML <Icon>)
  const logoImage = document.createElement("img");
  logoImage.src = "https://example.com/logo.png";
  logoImage.alt = "Company Logo";

  logoControlDiv.appendChild(logoImage);

  // 3. Position the control (KML <screenXY>)
  // In this case, we use TOP_RIGHT
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(logoControlDiv);
}

More Information