Run the js-samples server
mainnpm start command.npm startrepository·main·Indexed 21 days ago
https://github.com/googlemaps/js-samplesA collection of code samples and a practical reference for developers implementing features of the Google Maps JavaScript API. Includes examples for initializing maps, using AdvancedMarkerElement with accessibility and altitude data, customizing marker visuals with PinElement, and implementing animations using CSS and IntersectionObserver.
npm start command.npm startThe application uses a .env file to embed the API key into the HTML document. To use your own valid API key:
.env file in the editor.npm start -- --port=8080For TypeScript development, install the official Google Maps typings as a development dependency to get autocomplete and type checking.
npm i -D @types/google.mapsRun tests to verify outputs. You can also run linting and formatting to maintain code quality. If you are using Playwright for playground testing, you can update snapshots using specific flags.
# Run tests
npm test
# Fix lint issues
npm run lint
# Format code
npm run format
# Update Playwright snapshots (only differing ones)
npm run test:playwright:playground:update-snapshots
# Update ALL Playwright snapshots
npm run test:playwright:playground:update-snapshots -- --update-snapshots
# Update snapshots for a specific sample
npm run test:playwright:playground:update-snapshots -g <sample-name>To set up the development environment for the Google Maps JavaScript API samples, install the dependencies and build the project targets to update the dist/ folder.
npm i
npm run buildTo run a Google Maps Platform JS sample using TypeScript and Vite within Google Cloud Shell, follow these steps:
npm i.npm start -- --port=8080.npm i
npm start -- --port=8080ADMINISTRATIVE_AREA_LEVEL_1) for choropleth maps, you must provide a mapId in the Map options. This mapId must be configured in the Google Cloud Console with a map style that explicitly enables the specific feature layer you intend to style.You can style feature layers by assigning a google.maps.FeatureStyleOptions object or a styling function to the layer's style property.
FeatureStyleOptions based on the feature's properties (e.g., highlighting a specific placeId).Note: To use Data-Driven Styling, your Map must be initialized with a mapId that has a style configured in the Google Cloud Console to enable the desired feature types.
// Static style
countryLayer.style = {
fillColor: 'white',
fillOpacity: 0.1,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2.0,
};
// Dynamic style based on placeId
const targetPlaceId = 'SOME_PLACE_ID';
countryLayer.style = (params) => {
if (params.feature.placeId === targetPlaceId) {
return {
fillColor: 'blue',
fillOpacity: 0.5,
strokeColor: 'blue',
strokeOpacity: 1.0,
strokeWeight: 2.0,
};
} else {
return {
fillColor: 'white',
fillOpacity: 0.1,
strokeColor: 'black',
strokeOpacity: 1.0,
strokeWeight: 1.0,
};
}
};To add custom HTML or images to a Google Map that move and scale with the map, extend the google.maps.OverlayView class. You must implement four key lifecycle methods to manage the overlay's presence and positioning:
constructor: Initialize your custom properties (e.g., image URLs, bounds).onAdd(): Called when the overlay is added to the map. Use this to create your DOM elements and append them to one of the map's panes via this.getPanes(). Common panes include overlayLayer.draw(): Called when the map's projection changes (e.g., zoom or pan). Use this.getProjection() to convert LatLng coordinates to pixel coordinates using fromLatLngToDivPixel(). This allows you to position and resize your DOM elements correctly.onRemove(): Called when the overlay is removed from the map. Use this to clean up your DOM elements to prevent memory leaks.Once the class is defined, instantiate it and call .setMap(map) to display it.
class MyCustomOverlay extends google.maps.OverlayView {
private div_: HTMLElement | null = null;
private bounds_: google.maps.LatLngBounds;
constructor(bounds: google.maps.LatLngBounds) {
super();
this.bounds_ = bounds;
}
onAdd() {
this.div_ = document.createElement("div");
const panes = this.getPanes()!;
panes.overlayLayer.appendChild(this.div_);
}
draw() {
const projection = this.getProjection()!;
const sw = projection.fromLatLngToDivPixel(this.bounds_.getSouthWest())!;
const ne = projection.fromLatLngToDivPixel(this.bounds_.getNorthEast())!;
if (this.div_) {
this.div_.style.left = sw.x + "px";
this.div_.style.top = sw.y + "px"; // Note: logic depends on coordinate system
this.div_.style.width = (ne.x - sw.x) + "px";
this.div_.style.height = (ne.y - sw.y) + "px";
}
}
onRemove() {
if (this.div_) {
this.div_.parentNode?.removeChild(this.div_);
this.div_ = null;
}
}
}
const overlay = new MyCustomOverlay(bounds);
overlay.setMap(map);When using Google Maps objects (like LatLng or LatLngLiteral) as dependencies in React hooks (e.g., useEffect), standard shallow comparison or even standard deep comparison may fail or trigger unnecessary updates.
To solve this, implement a custom equality check using google.maps.LatLng.equals(). This ensures that two different object instances representing the same coordinates are treated as equal by React's dependency tracking.
import { isLatLngLiteral } from "@googlemaps/typescript-guards";
import { createCustomEqual } from "fast-equals";
const deepCompareEqualsForMaps = createCustomEqual(
(deepEqual) => (a: any, b: any) => {
if (
isLatLngLiteral(a) ||
a instanceof google.maps.LatLng ||
isLatLngLiteral(b) ||
b instanceof google.maps.LatLng
) {
return new google.maps.LatLng(a).equals(new google.maps.LatLng(b));
}
return deepEqual(a, b);
}
);When subclassing google.maps.OverlayView, you must implement these methods to manage the overlay's lifecycle:
onAdd(): Triggered when the overlay is added to the map. Use this.getPanes() to access map panes (like overlayLayer) and append your custom HTML elements.draw(): Triggered when the map is redrawn or the projection changes. Use this.getProjection() to convert LatLng coordinates to pixel coordinates via fromLatLngToDivPixel() to position and size your elements.onRemove(): Triggered when setMap(null) is called. Use this to remove your custom elements from the DOM to prevent memory leaks.To make Deck.gl layers interactive (e.g., pickable: true) while they are overlaid on a Google Map, you must intercept Google Maps mouse events and convert them into Deck.gl events.
deck.getViewports()[0].project([lng, lat]) to convert the Google Maps latLng into the pixel coordinates expected by Deck.gl.click $\rightarrow$ click (Note: You may need to manually trigger pickObject for click events if not using pointer events).dblclick $\rightarrow$ click with tapCount: 2.mousemove $\rightarrow$ pointermove.mouseout $\rightarrow$ pointerleave.this.requestRedraw() after handling events to ensure the Deck.gl layer updates its visual state (like highlights).handleMouseEvent(deck: any, type: string, event: google.maps.MapMouseEvent) {
const point = deck.getViewports()[0].project([
event.latLng!.lng(),
event.latLng!.lat()
]);
const deckEvent = {
type,
offsetCenter: { x: point[0], y: point[1] },
srcEvent: event,
};
// Map types and call deck._onEvent or deck._onPointerMove
// ...
this.requestRedraw();
}