Controla los eventos del mouse

Selecciona la plataforma: iOS JavaScript

Descripción general

Haz que una capa de componentes responda a los eventos mousemove y click, y úsalos para mostrar información sobre el límite en el que se hizo clic. Esta información incluye el ID, el nombre visible y el tipo de componente. En el siguiente mapa de ejemplo, se muestran los límites del área administrativa de nivel 2 y se incluye un código de control de eventos que diseña polígonos según la interacción del usuario (mousemove cambia el grosor del borde, click sombrea el color de fondo y hace que se muestre una ventana de información).

Cómo habilitar los eventos de la capa de componentes

Sigue estos pasos para habilitar los eventos en una capa de componentes:

  1. Registra una capa de componentes para las notificaciones de eventos llamando a la función addListener() en la capa de componentes para cada evento que desees registrar. En este ejemplo, también se agrega un objeto de escucha al mapa.

    TypeScript

    // Add the feature layer.
    //@ts-ignore
    featureLayer = map.getFeatureLayer('ADMINISTRATIVE_AREA_LEVEL_2');
    
    // Add the event listeners for the feature layer.
    featureLayer.addListener('click', handleClick);
    featureLayer.addListener('mousemove', handleMouseMove);
    
    // Map event listener.
    map.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;
      }
    });

    JavaScript

    // Add the feature layer.
    //@ts-ignore
    featureLayer = map.getFeatureLayer("ADMINISTRATIVE_AREA_LEVEL_2");
    // Add the event listeners for the feature layer.
    featureLayer.addListener("click", handleClick);
    featureLayer.addListener("mousemove", handleMouseMove);
    // Map event listener.
    map.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;
      }
    });

  2. Agrega código de controlador de eventos para aplicar diseño al polígono seleccionado según el tipo de interacción.

    TypeScript

    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;
    }

    JavaScript

    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;
    }
    

  3. Usa una función de diseño de componentes para aplicar diseños. La función que se muestra aquí aplica diseño de forma condicional según el tipo de interacción. Aquí se definen tres diseños: uno para que el borde se muestre en negrita cuando se escribe en mousemove, uno para cambiar el fondo y mostrar una ventana de información en click, y uno predeterminado.

    TypeScript

    // 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;
    }

    JavaScript

    // 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;
    }
    

Ejemplo de código completo

TypeScript

let map: google.maps.Map;
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') as google.maps.MapsLibrary;

  map = new Map(document.getElementById('map') as HTMLElement, {
    center: {lat: 39.23, lng: -105.73},
    zoom: 8,
    // In the cloud console, configure your Map ID with a style that enables the
    // 'Administrative Area Level 2' Data Driven Styling type.
    mapId: 'a3efe1c035bad51b', // Substitute your own map ID.
    mapTypeControl: false,
  });

  // Add the feature layer.
  //@ts-ignore
  featureLayer = map.getFeatureLayer('ADMINISTRATIVE_AREA_LEVEL_2');

  // Add the event listeners for the feature layer.
  featureLayer.addListener('click', handleClick);
  featureLayer.addListener('mousemove', handleMouseMove);

  // Map event listener.
  map.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;
    }
  });

  // 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 infowindow.
  const place = await feature.fetchPlace();
  let content =
      '<span style="font-size:small">Display name: ' + place.displayName +
      '<br/> Place ID: ' + feature.placeId +
      '<br/> Feature type: ' + feature.featureType + '</span>';

  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,
    shouldFocus: false,
  });
}

initMap();

JavaScript

let map;
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");

  map = new Map(document.getElementById("map"), {
    center: { lat: 39.23, lng: -105.73 },
    zoom: 8,
    // In the cloud console, configure your Map ID with a style that enables the
    // 'Administrative Area Level 2' Data Driven Styling type.
    mapId: "a3efe1c035bad51b", // Substitute your own map ID.
    mapTypeControl: false,
  });
  // Add the feature layer.
  //@ts-ignore
  featureLayer = map.getFeatureLayer("ADMINISTRATIVE_AREA_LEVEL_2");
  // Add the event listeners for the feature layer.
  featureLayer.addListener("click", handleClick);
  featureLayer.addListener("mousemove", handleMouseMove);
  // Map event listener.
  map.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;
    }
  });
  // 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 infowindow.
  const place = await feature.fetchPlace();
  let content =
    '<span style="font-size:small">Display name: ' +
    place.displayName +
    "<br/> Place ID: " +
    feature.placeId +
    "<br/> Feature type: " +
    feature.featureType +
    "</span>";

  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,
    shouldFocus: false,
  });
}

initMap();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Handle Region Boundary Click Event</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>

Prueba la muestra

Más información sobre los eventos