diff --git a/dist/index.html b/dist/index.html index 1dc994f7..f3a51451 100644 --- a/dist/index.html +++ b/dist/index.html @@ -47,6 +47,7 @@

Maps JSAPI Samples

  • advanced-markers-simple
  • advanced-markers-zoom
  • boundaries-choropleth
  • +
  • boundaries-click
  • boundaries-simple
  • boundaries-text-search
  • deckgl-heatmap
  • diff --git a/dist/samples/boundaries-click/app/.eslintsrc.json b/dist/samples/boundaries-click/app/.eslintsrc.json new file mode 100644 index 00000000..4c44dab0 --- /dev/null +++ b/dist/samples/boundaries-click/app/.eslintsrc.json @@ -0,0 +1,13 @@ +{ + "extends": [ + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "rules": { + "@typescript-eslint/ban-ts-comment": 0, + "@typescript-eslint/no-this-alias": 1, + "@typescript-eslint/no-empty-function": 1, + "@typescript-eslint/explicit-module-boundary-types": 1, + "@typescript-eslint/no-unused-vars": 1 + } +} diff --git a/dist/samples/boundaries-click/app/README.md b/dist/samples/boundaries-click/app/README.md new file mode 100644 index 00000000..813f357a --- /dev/null +++ b/dist/samples/boundaries-click/app/README.md @@ -0,0 +1,40 @@ +# Google Maps JavaScript Sample + +This sample is generated from @googlemaps/js-samples located at +https://github.com/googlemaps-samples/js-api-samples. + +## Setup + +### Before starting run: + +`npm i` + +### Run an example on a local web server + +`cd samples/boundaries-click` +`npm start` + +### Build an individual example + +`cd samples/boundaries-click` +`npm run build` + +From 'samples': + +`npm run build --workspace=boundaries-click/` + +### Build all of the examples. + +From 'samples': + +`npm run build-all` + +### Run lint to check for problems + +`cd samples/boundaries-click` +`npx eslint index.ts` + +## Feedback + +For feedback related to this sample, please open a new issue on +[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues). diff --git a/dist/samples/boundaries-click/app/index.html b/dist/samples/boundaries-click/app/index.html new file mode 100644 index 00000000..2da437a2 --- /dev/null +++ b/dist/samples/boundaries-click/app/index.html @@ -0,0 +1,22 @@ + + + + + + Handle Region Boundary Click Event + + + + + + + + + + + diff --git a/dist/samples/boundaries-click/app/index.ts b/dist/samples/boundaries-click/app/index.ts new file mode 100644 index 00000000..d239b133 --- /dev/null +++ b/dist/samples/boundaries-click/app/index.ts @@ -0,0 +1,153 @@ +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +// [START maps_boundaries_click_event] +let innerMap; +let featureLayer; +let infoWindow; +let lastInteractedFeatureIds = []; +let lastClickedFeatureIds = []; + +// [START maps_boundaries_click_event_handler] +function handleClick(/* MouseEvent */ e) { + lastClickedFeatureIds = e.features.map((f) => f.placeId); + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + createInfoWindow(e); +} + +function handleMouseMove(/* MouseEvent */ e) { + lastInteractedFeatureIds = e.features.map((f) => f.placeId); + featureLayer.style = applyStyle; +} +// [END maps_boundaries_click_event_handler] + +async function initMap() { + // Request needed libraries. + const { Map, InfoWindow } = (await google.maps.importLibrary( + 'maps' + )) as google.maps.MapsLibrary; + + // Get the gmp-map element. + const mapElement = document.querySelector( + 'gmp-map' + ) as google.maps.MapElement; + + // Get the inner map. + innerMap = mapElement.innerMap; + + // Set map options. + innerMap.setOptions({ + mapTypeControl: false, + }); + + //[START maps_boundaries_click_event_add_layer] + // Add the feature layer. + featureLayer = innerMap.getFeatureLayer( + google.maps.FeatureType.ADMINISTRATIVE_AREA_LEVEL_2 + ); + + // Add the event listeners for the feature layer. + featureLayer.addListener('click', handleClick); + featureLayer.addListener('mousemove', handleMouseMove); + + // Map event listener. + innerMap.addListener('mousemove', () => { + // If the map gets a mousemove, that means there are no feature layers + // with listeners registered under the mouse, so we clear the last + // interacted feature ids. + if (lastInteractedFeatureIds?.length) { + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + } + }); + //[END maps_boundaries_click_event_add_layer] + + // Create the infowindow. + infoWindow = new InfoWindow({}); + // Apply style on load, to enable clicking. + featureLayer.style = applyStyle; +} + +// Helper function for the infowindow. +async function createInfoWindow(event) { + let feature = event.features[0]; + if (!feature.placeId) return; + + // Update the info window. + // Get the place instance from the selected feature. + const place = await feature.fetchPlace(); + + // Create a new div to hold the text content. + let content = document.createElement('div'); + + // Get the text values. + let nameText = document.createElement('span'); + nameText.textContent = `Display name: ${place.displayName}`; + let placeIdText = document.createElement('span'); + placeIdText.textContent = `Place ID: ${feature.placeId}`; + let featureTypeText = document.createElement('span'); + featureTypeText.textContent = `Feature type: ${feature.featureType}`; + + // Append the text to the div. + content.appendChild(nameText); + content.appendChild(document.createElement('br')); + content.appendChild(placeIdText); + content.appendChild(document.createElement('br')); + content.appendChild(featureTypeText); + + updateInfoWindow(content, event.latLng); +} + +// [START maps_boundaries_click_event_style] +// Define styles. +// Stroke and fill with minimum opacity value. +const styleDefault = { + strokeColor: '#810FCB', + strokeOpacity: 1.0, + strokeWeight: 2.0, + fillColor: 'white', + fillOpacity: 0.1, // Polygons must be visible to receive events. +}; +// Style for the clicked polygon. +const styleClicked = { + ...styleDefault, + fillColor: '#810FCB', + fillOpacity: 0.5, +}; +// Style for polygon on mouse move. +const styleMouseMove = { + ...styleDefault, + strokeWeight: 4.0, +}; + +// Apply styles using a feature style function. +function applyStyle(/* FeatureStyleFunctionOptions */ params) { + const placeId = params.feature.placeId; + //@ts-ignore + if (lastClickedFeatureIds.includes(placeId)) { + return styleClicked; + } + //@ts-ignore + if (lastInteractedFeatureIds.includes(placeId)) { + return styleMouseMove; + } + return styleDefault; +} +// [END maps_boundaries_click_event_style] + +// Helper function to create an info window. +function updateInfoWindow(content, center) { + infoWindow.setContent(content); + infoWindow.setPosition(center); + infoWindow.open({ + map: innerMap, + shouldFocus: false, + }); +} + +initMap(); +// [END maps_boundaries_click_event] diff --git a/dist/samples/boundaries-click/app/package.json b/dist/samples/boundaries-click/app/package.json new file mode 100644 index 00000000..ffa9be78 --- /dev/null +++ b/dist/samples/boundaries-click/app/package.json @@ -0,0 +1,14 @@ +{ + "name": "@js-api-samples/boundaries-click", + "version": "1.0.0", + "scripts": { + "build": "tsc && bash ../jsfiddle.sh boundaries-click && bash ../app.sh boundaries-click && bash ../docs.sh boundaries-click && npm run build:vite --workspace=. && bash ../dist.sh boundaries-click", + "test": "tsc && npm run build:vite --workspace=.", + "start": "tsc && vite build --base './' && vite", + "build:vite": "vite build --base './'", + "preview": "vite preview" + }, + "dependencies": { + + } +} diff --git a/dist/samples/boundaries-click/app/style.css b/dist/samples/boundaries-click/app/style.css new file mode 100644 index 00000000..3371171f --- /dev/null +++ b/dist/samples/boundaries-click/app/style.css @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* [START maps_boundaries_click_event] */ +/* + * Always set the map height explicitly to define the size of the div element + * that contains the map. + */ +gmp-map { + height: 100%; +} + +/* + * Optional: Makes the sample page fill the window. + */ +html, +body { + height: 100%; + margin: 0; + padding: 0; +} + +/* [END maps_boundaries_click_event] */ diff --git a/dist/samples/boundaries-click/app/tsconfig.json b/dist/samples/boundaries-click/app/tsconfig.json new file mode 100644 index 00000000..366aabb0 --- /dev/null +++ b/dist/samples/boundaries-click/app/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "esnext", + "strict": true, + "noImplicitAny": false, + "lib": [ + "es2015", + "esnext", + "es6", + "dom", + "dom.iterable" + ], + "moduleResolution": "Node", + "jsx": "preserve" + } +} diff --git a/dist/samples/boundaries-click/dist/assets/index-C1Myve7P.js b/dist/samples/boundaries-click/dist/assets/index-C1Myve7P.js new file mode 100644 index 00000000..9cbbd8fe --- /dev/null +++ b/dist/samples/boundaries-click/dist/assets/index-C1Myve7P.js @@ -0,0 +1,5 @@ +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))r(t);new MutationObserver(t=>{for(const n of t)if(n.type==="childList")for(const a of n.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&r(a)}).observe(document,{childList:!0,subtree:!0});function c(t){const n={};return t.integrity&&(n.integrity=t.integrity),t.referrerPolicy&&(n.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?n.credentials="include":t.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function r(t){if(t.ep)return;t.ep=!0;const n=c(t);fetch(t.href,n)}})();/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */let i,l,d,s=[],f=[];function m(o){f=o.features.map(e=>e.placeId),s=[],l.style=p,g(o)}function y(o){s=o.features.map(e=>e.placeId),l.style=p}async function h(){const{Map:o,InfoWindow:e}=await google.maps.importLibrary("maps");i=document.querySelector("gmp-map").innerMap,i.setOptions({mapTypeControl:!1}),l=i.getFeatureLayer(google.maps.FeatureType.ADMINISTRATIVE_AREA_LEVEL_2),l.addListener("click",m),l.addListener("mousemove",y),i.addListener("mousemove",()=>{s?.length&&(s=[],l.style=p)}),d=new e({}),l.style=p}async function g(o){let e=o.features[0];if(!e.placeId)return;const c=await e.fetchPlace();let r=document.createElement("div"),t=document.createElement("span");t.textContent=`Display name: ${c.displayName}`;let n=document.createElement("span");n.textContent=`Place ID: ${e.placeId}`;let a=document.createElement("span");a.textContent=`Feature type: ${e.featureType}`,r.appendChild(t),r.appendChild(document.createElement("br")),r.appendChild(n),r.appendChild(document.createElement("br")),r.appendChild(a),L(r,o.latLng)}const u={strokeColor:"#810FCB",strokeOpacity:1,strokeWeight:2,fillColor:"white",fillOpacity:.1},C={...u,fillColor:"#810FCB",fillOpacity:.5},I={...u,strokeWeight:4};function p(o){const e=o.feature.placeId;return f.includes(e)?C:s.includes(e)?I:u}function L(o,e){d.setContent(o),d.setPosition(e),d.open({map:i,shouldFocus:!1})}h(); diff --git a/dist/samples/boundaries-click/dist/assets/index-i_98oPIq.css b/dist/samples/boundaries-click/dist/assets/index-i_98oPIq.css new file mode 100644 index 00000000..c48393ed --- /dev/null +++ b/dist/samples/boundaries-click/dist/assets/index-i_98oPIq.css @@ -0,0 +1,5 @@ +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */gmp-map{height:100%}html,body{height:100%;margin:0;padding:0} diff --git a/dist/samples/boundaries-click/dist/index.html b/dist/samples/boundaries-click/dist/index.html new file mode 100644 index 00000000..2bcf2dc3 --- /dev/null +++ b/dist/samples/boundaries-click/dist/index.html @@ -0,0 +1,22 @@ + + + + + + Handle Region Boundary Click Event + + + + + + + + + + + diff --git a/dist/samples/boundaries-click/docs/index.html b/dist/samples/boundaries-click/docs/index.html new file mode 100644 index 00000000..2da437a2 --- /dev/null +++ b/dist/samples/boundaries-click/docs/index.html @@ -0,0 +1,22 @@ + + + + + + Handle Region Boundary Click Event + + + + + + + + + + + diff --git a/dist/samples/boundaries-click/docs/index.js b/dist/samples/boundaries-click/docs/index.js new file mode 100644 index 00000000..e228ca63 --- /dev/null +++ b/dist/samples/boundaries-click/docs/index.js @@ -0,0 +1,128 @@ +"use strict"; +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +// [START maps_boundaries_click_event] +let innerMap; +let featureLayer; +let infoWindow; +let lastInteractedFeatureIds = []; +let lastClickedFeatureIds = []; +// [START maps_boundaries_click_event_handler] +function handleClick(/* MouseEvent */ e) { + lastClickedFeatureIds = e.features.map((f) => f.placeId); + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + createInfoWindow(e); +} +function handleMouseMove(/* MouseEvent */ e) { + lastInteractedFeatureIds = e.features.map((f) => f.placeId); + featureLayer.style = applyStyle; +} +// [END maps_boundaries_click_event_handler] +async function initMap() { + // Request needed libraries. + const { Map, InfoWindow } = (await google.maps.importLibrary('maps')); + // Get the gmp-map element. + const mapElement = document.querySelector('gmp-map'); + // Get the inner map. + innerMap = mapElement.innerMap; + // Set map options. + innerMap.setOptions({ + mapTypeControl: false, + }); + //[START maps_boundaries_click_event_add_layer] + // Add the feature layer. + featureLayer = innerMap.getFeatureLayer(google.maps.FeatureType.ADMINISTRATIVE_AREA_LEVEL_2); + // Add the event listeners for the feature layer. + featureLayer.addListener('click', handleClick); + featureLayer.addListener('mousemove', handleMouseMove); + // Map event listener. + innerMap.addListener('mousemove', () => { + // If the map gets a mousemove, that means there are no feature layers + // with listeners registered under the mouse, so we clear the last + // interacted feature ids. + if (lastInteractedFeatureIds?.length) { + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + } + }); + //[END maps_boundaries_click_event_add_layer] + // Create the infowindow. + infoWindow = new InfoWindow({}); + // Apply style on load, to enable clicking. + featureLayer.style = applyStyle; +} +// Helper function for the infowindow. +async function createInfoWindow(event) { + let feature = event.features[0]; + if (!feature.placeId) + return; + // Update the info window. + // Get the place instance from the selected feature. + const place = await feature.fetchPlace(); + // Create a new div to hold the text content. + let content = document.createElement('div'); + // Get the text values. + let nameText = document.createElement('span'); + nameText.textContent = `Display name: ${place.displayName}`; + let placeIdText = document.createElement('span'); + placeIdText.textContent = `Place ID: ${feature.placeId}`; + let featureTypeText = document.createElement('span'); + featureTypeText.textContent = `Feature type: ${feature.featureType}`; + // Append the text to the div. + content.appendChild(nameText); + content.appendChild(document.createElement('br')); + content.appendChild(placeIdText); + content.appendChild(document.createElement('br')); + content.appendChild(featureTypeText); + updateInfoWindow(content, event.latLng); +} +// [START maps_boundaries_click_event_style] +// Define styles. +// Stroke and fill with minimum opacity value. +const styleDefault = { + strokeColor: '#810FCB', + strokeOpacity: 1.0, + strokeWeight: 2.0, + fillColor: 'white', + fillOpacity: 0.1, // Polygons must be visible to receive events. +}; +// Style for the clicked polygon. +const styleClicked = { + ...styleDefault, + fillColor: '#810FCB', + fillOpacity: 0.5, +}; +// Style for polygon on mouse move. +const styleMouseMove = { + ...styleDefault, + strokeWeight: 4.0, +}; +// Apply styles using a feature style function. +function applyStyle(/* FeatureStyleFunctionOptions */ params) { + const placeId = params.feature.placeId; + //@ts-ignore + if (lastClickedFeatureIds.includes(placeId)) { + return styleClicked; + } + //@ts-ignore + if (lastInteractedFeatureIds.includes(placeId)) { + return styleMouseMove; + } + return styleDefault; +} +// [END maps_boundaries_click_event_style] +// Helper function to create an info window. +function updateInfoWindow(content, center) { + infoWindow.setContent(content); + infoWindow.setPosition(center); + infoWindow.open({ + map: innerMap, + shouldFocus: false, + }); +} +initMap(); +// [END maps_boundaries_click_event] diff --git a/dist/samples/boundaries-click/docs/index.ts b/dist/samples/boundaries-click/docs/index.ts new file mode 100644 index 00000000..d239b133 --- /dev/null +++ b/dist/samples/boundaries-click/docs/index.ts @@ -0,0 +1,153 @@ +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +// [START maps_boundaries_click_event] +let innerMap; +let featureLayer; +let infoWindow; +let lastInteractedFeatureIds = []; +let lastClickedFeatureIds = []; + +// [START maps_boundaries_click_event_handler] +function handleClick(/* MouseEvent */ e) { + lastClickedFeatureIds = e.features.map((f) => f.placeId); + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + createInfoWindow(e); +} + +function handleMouseMove(/* MouseEvent */ e) { + lastInteractedFeatureIds = e.features.map((f) => f.placeId); + featureLayer.style = applyStyle; +} +// [END maps_boundaries_click_event_handler] + +async function initMap() { + // Request needed libraries. + const { Map, InfoWindow } = (await google.maps.importLibrary( + 'maps' + )) as google.maps.MapsLibrary; + + // Get the gmp-map element. + const mapElement = document.querySelector( + 'gmp-map' + ) as google.maps.MapElement; + + // Get the inner map. + innerMap = mapElement.innerMap; + + // Set map options. + innerMap.setOptions({ + mapTypeControl: false, + }); + + //[START maps_boundaries_click_event_add_layer] + // Add the feature layer. + featureLayer = innerMap.getFeatureLayer( + google.maps.FeatureType.ADMINISTRATIVE_AREA_LEVEL_2 + ); + + // Add the event listeners for the feature layer. + featureLayer.addListener('click', handleClick); + featureLayer.addListener('mousemove', handleMouseMove); + + // Map event listener. + innerMap.addListener('mousemove', () => { + // If the map gets a mousemove, that means there are no feature layers + // with listeners registered under the mouse, so we clear the last + // interacted feature ids. + if (lastInteractedFeatureIds?.length) { + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + } + }); + //[END maps_boundaries_click_event_add_layer] + + // Create the infowindow. + infoWindow = new InfoWindow({}); + // Apply style on load, to enable clicking. + featureLayer.style = applyStyle; +} + +// Helper function for the infowindow. +async function createInfoWindow(event) { + let feature = event.features[0]; + if (!feature.placeId) return; + + // Update the info window. + // Get the place instance from the selected feature. + const place = await feature.fetchPlace(); + + // Create a new div to hold the text content. + let content = document.createElement('div'); + + // Get the text values. + let nameText = document.createElement('span'); + nameText.textContent = `Display name: ${place.displayName}`; + let placeIdText = document.createElement('span'); + placeIdText.textContent = `Place ID: ${feature.placeId}`; + let featureTypeText = document.createElement('span'); + featureTypeText.textContent = `Feature type: ${feature.featureType}`; + + // Append the text to the div. + content.appendChild(nameText); + content.appendChild(document.createElement('br')); + content.appendChild(placeIdText); + content.appendChild(document.createElement('br')); + content.appendChild(featureTypeText); + + updateInfoWindow(content, event.latLng); +} + +// [START maps_boundaries_click_event_style] +// Define styles. +// Stroke and fill with minimum opacity value. +const styleDefault = { + strokeColor: '#810FCB', + strokeOpacity: 1.0, + strokeWeight: 2.0, + fillColor: 'white', + fillOpacity: 0.1, // Polygons must be visible to receive events. +}; +// Style for the clicked polygon. +const styleClicked = { + ...styleDefault, + fillColor: '#810FCB', + fillOpacity: 0.5, +}; +// Style for polygon on mouse move. +const styleMouseMove = { + ...styleDefault, + strokeWeight: 4.0, +}; + +// Apply styles using a feature style function. +function applyStyle(/* FeatureStyleFunctionOptions */ params) { + const placeId = params.feature.placeId; + //@ts-ignore + if (lastClickedFeatureIds.includes(placeId)) { + return styleClicked; + } + //@ts-ignore + if (lastInteractedFeatureIds.includes(placeId)) { + return styleMouseMove; + } + return styleDefault; +} +// [END maps_boundaries_click_event_style] + +// Helper function to create an info window. +function updateInfoWindow(content, center) { + infoWindow.setContent(content); + infoWindow.setPosition(center); + infoWindow.open({ + map: innerMap, + shouldFocus: false, + }); +} + +initMap(); +// [END maps_boundaries_click_event] diff --git a/dist/samples/boundaries-click/docs/style.css b/dist/samples/boundaries-click/docs/style.css new file mode 100644 index 00000000..3371171f --- /dev/null +++ b/dist/samples/boundaries-click/docs/style.css @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* [START maps_boundaries_click_event] */ +/* + * Always set the map height explicitly to define the size of the div element + * that contains the map. + */ +gmp-map { + height: 100%; +} + +/* + * Optional: Makes the sample page fill the window. + */ +html, +body { + height: 100%; + margin: 0; + padding: 0; +} + +/* [END maps_boundaries_click_event] */ diff --git a/dist/samples/boundaries-click/jsfiddle/demo.css b/dist/samples/boundaries-click/jsfiddle/demo.css new file mode 100644 index 00000000..72d40c20 --- /dev/null +++ b/dist/samples/boundaries-click/jsfiddle/demo.css @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Always set the map height explicitly to define the size of the div element + * that contains the map. + */ +gmp-map { + height: 100%; +} + +/* + * Optional: Makes the sample page fill the window. + */ +html, +body { + height: 100%; + margin: 0; + padding: 0; +} + + diff --git a/dist/samples/boundaries-click/jsfiddle/demo.details b/dist/samples/boundaries-click/jsfiddle/demo.details new file mode 100644 index 00000000..0a032c2f --- /dev/null +++ b/dist/samples/boundaries-click/jsfiddle/demo.details @@ -0,0 +1,7 @@ +name: boundaries-click +authors: + - Geo Developer IX Documentation Team +tags: + - google maps +load_type: h +description: Sample code supporting Google Maps Platform JavaScript API documentation. diff --git a/dist/samples/boundaries-click/jsfiddle/demo.html b/dist/samples/boundaries-click/jsfiddle/demo.html new file mode 100644 index 00000000..d24671b6 --- /dev/null +++ b/dist/samples/boundaries-click/jsfiddle/demo.html @@ -0,0 +1,22 @@ + + + + + + Handle Region Boundary Click Event + + + + + + + + + + + diff --git a/dist/samples/boundaries-click/jsfiddle/demo.js b/dist/samples/boundaries-click/jsfiddle/demo.js new file mode 100644 index 00000000..c33c4a9b --- /dev/null +++ b/dist/samples/boundaries-click/jsfiddle/demo.js @@ -0,0 +1,128 @@ +"use strict"; +/** + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +let innerMap; +let featureLayer; +let infoWindow; +let lastInteractedFeatureIds = []; +let lastClickedFeatureIds = []; + +function handleClick(/* MouseEvent */ e) { + lastClickedFeatureIds = e.features.map((f) => f.placeId); + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + createInfoWindow(e); +} +function handleMouseMove(/* MouseEvent */ e) { + lastInteractedFeatureIds = e.features.map((f) => f.placeId); + featureLayer.style = applyStyle; +} + +async function initMap() { + // Request needed libraries. + const { Map, InfoWindow } = (await google.maps.importLibrary('maps')); + // Get the gmp-map element. + const mapElement = document.querySelector('gmp-map'); + // Get the inner map. + innerMap = mapElement.innerMap; + // Set map options. + innerMap.setOptions({ + mapTypeControl: false, + }); + //[START maps_boundaries_click_event_add_layer] + // Add the feature layer. + featureLayer = innerMap.getFeatureLayer(google.maps.FeatureType.ADMINISTRATIVE_AREA_LEVEL_2); + // Add the event listeners for the feature layer. + featureLayer.addListener('click', handleClick); + featureLayer.addListener('mousemove', handleMouseMove); + // Map event listener. + innerMap.addListener('mousemove', () => { + // If the map gets a mousemove, that means there are no feature layers + // with listeners registered under the mouse, so we clear the last + // interacted feature ids. + if (lastInteractedFeatureIds?.length) { + lastInteractedFeatureIds = []; + featureLayer.style = applyStyle; + } + }); + //[END maps_boundaries_click_event_add_layer] + // Create the infowindow. + infoWindow = new InfoWindow({}); + // Apply style on load, to enable clicking. + featureLayer.style = applyStyle; +} +// Helper function for the infowindow. +async function createInfoWindow(event) { + let feature = event.features[0]; + if (!feature.placeId) + return; + // Update the info window. + // Get the place instance from the selected feature. + const place = await feature.fetchPlace(); + // Create a new div to hold the text content. + let content = document.createElement('div'); + // Get the text values. + let nameText = document.createElement('span'); + nameText.textContent = `Display name: ${place.displayName}`; + let placeIdText = document.createElement('span'); + placeIdText.textContent = `Place ID: ${feature.placeId}`; + let featureTypeText = document.createElement('span'); + featureTypeText.textContent = `Feature type: ${feature.featureType}`; + // Append the text to the div. + content.appendChild(nameText); + content.appendChild(document.createElement('br')); + content.appendChild(placeIdText); + content.appendChild(document.createElement('br')); + content.appendChild(featureTypeText); + updateInfoWindow(content, event.latLng); +} + +// Define styles. +// Stroke and fill with minimum opacity value. +const styleDefault = { + strokeColor: '#810FCB', + strokeOpacity: 1.0, + strokeWeight: 2.0, + fillColor: 'white', + fillOpacity: 0.1, // Polygons must be visible to receive events. +}; +// Style for the clicked polygon. +const styleClicked = { + ...styleDefault, + fillColor: '#810FCB', + fillOpacity: 0.5, +}; +// Style for polygon on mouse move. +const styleMouseMove = { + ...styleDefault, + strokeWeight: 4.0, +}; +// Apply styles using a feature style function. +function applyStyle(/* FeatureStyleFunctionOptions */ params) { + const placeId = params.feature.placeId; + //@ts-ignore + if (lastClickedFeatureIds.includes(placeId)) { + return styleClicked; + } + //@ts-ignore + if (lastInteractedFeatureIds.includes(placeId)) { + return styleMouseMove; + } + return styleDefault; +} + +// Helper function to create an info window. +function updateInfoWindow(content, center) { + infoWindow.setContent(content); + infoWindow.setPosition(center); + infoWindow.open({ + map: innerMap, + shouldFocus: false, + }); +} +initMap(); + diff --git a/index.html b/index.html index 1dc994f7..f3a51451 100644 --- a/index.html +++ b/index.html @@ -47,6 +47,7 @@

    Maps JSAPI Samples

  • advanced-markers-simple
  • advanced-markers-zoom
  • boundaries-choropleth
  • +
  • boundaries-click
  • boundaries-simple
  • boundaries-text-search
  • deckgl-heatmap
  • diff --git a/package-lock.json b/package-lock.json index 1d1380e1..6d41fe14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1439,6 +1439,10 @@ "resolved": "samples/boundaries-choropleth", "link": true }, + "node_modules/@js-api-samples/boundaries-click": { + "resolved": "samples/boundaries-click", + "link": true + }, "node_modules/@js-api-samples/boundaries-simple": { "resolved": "samples/boundaries-simple", "link": true @@ -8821,6 +8825,10 @@ "name": "@js-api-samples/boundaries-choropleth", "version": "1.0.0" }, + "samples/boundaries-click": { + "name": "@js-api-samples/boundaries-click", + "version": "1.0.0" + }, "samples/boundaries-simple": { "name": "@js-api-samples/boundaries-simple", "version": "1.0.0"