Google 地图 Api: 无法点击数据层后面的可点击多边形

Google Maps Api: cannot click on clickable polygon behind datalayer

您好,我正在使用 google 地图 api(JavaScript) 构建交互式世界地图。在我 运行 解决这个问题之前,一切都很顺利。我正在使用多边形来显示一个国家的轮廓。单击这些多边形会触发一个模式,显示有关国家/地区的信息。这一直有效,直到我开始使用 "Data Layer: Earthquake data"。我没有使用地震数据,而是使用了我工作的公司的销售信息。因此,如果我们的大部分客户来自荷兰,那么分配给荷兰的数据层将非常大。问题是由于数据层,国家不再可点击。我无法单击 "through" 数据层。有没有可能我可以触发数据层后面的事件?

此代码显示数据层:

map.data.loadGeoJson('./data/test.json');

map.data.setStyle(function(feature) {
  var percentage = parseFloat(feature.getProperty('percentage'));
  return ({
    icon: {
      path: google.maps.SymbolPath.CIRCLE,
      scale: percentage,
      fillColor: '#00ff00',
      fillOpacity: 0.35,
      strokeWeight: 0
    }
  })

});

map.data.addListener('mouseover', function(event) {
  map.data.overrideStyle(event.feature, {
    title: 'Hello, World!'
  });
});

map.data.addListener('mouseout', function(event) {
  map.data.revertStyle();
});

function eqfeed_callback(data) {
  map.data.addGeoJson(data);
}

此代码显示多边形:

function drawMap(data) {

  var rows = data['rows'];
  for (var i in rows) {
    if (rows[i][0] != 'Antarctica') {


      var newCoordinates = [];
      var geometries = rows[i][1]['geometries'];

      if (geometries) {
        for (var j in geometries) {
          newCoordinates.push(constructNewCoordinates(geometries[j]));
        }
      } else {
        newCoordinates = constructNewCoordinates(rows[i][1]['geometry']);
      }
      var country = new google.maps.Polygon({
        paths: newCoordinates,
        strokeColor: 'transparent',
        strokeOpacity: 1,
        strokeWeight: 0.3,
        fillColor: '#cd0000',
        fillOpacity: 0,
        name: rows[i][0]

      });
      google.maps.event.addListener(country, 'mouseover', function() {
        this.setOptions({
          fillOpacity: 0.3
        });
      });
      google.maps.event.addListener(country, 'mouseout', function() {
        this.setOptions({
          fillOpacity: 0
        });
      });
      google.maps.event.addListener(country, 'click', function() {
        var countryName = this.name;
        var code = convert(countryName); // Calls a function that converts the name of the country to its official ISO 3166-1 alpha-2 code.
        var modal = document.querySelector('.modal');
        var instance = M.Modal.init(modal);
        instance.open();

      });


      country.setMap(map);
    }
  }

如果在文档中读到更改 zIndex 将不起作用,因为 "Markers are always displayed in front of line-strings and polygons."

有没有办法点击数据层后面的多边形?

编辑 我试图给多边形一个更高的 zIndex,我让数据层不可点击

map.data.loadGeoJson('./data/test.json');

map.data.setStyle(function(feature) {
  var percentage = parseFloat(feature.getProperty('percentage'));

  return ({
    icon: {
      path: google.maps.SymbolPath.CIRCLE,
      scale: percentage,
      fillColor: '#00ff00',
      fillOpacity: 0.35,
      strokeWeight: 0,
      clickAble: false,
      zIndex: 50


    }
  })

});

function eqfeed_callback(data) {
  map.data.addGeoJson(data);
}


function drawMap(data) {

  var rows = data['rows'];
  for (var i in rows) {
    if (rows[i][0] != 'Antarctica') {


      var newCoordinates = [];
      var geometries = rows[i][1]['geometries'];

      if (geometries) {
        for (var j in geometries) {
          newCoordinates.push(constructNewCoordinates(geometries[j]));
        }
      } else {
        newCoordinates = constructNewCoordinates(rows[i][1]['geometry']);
      }
      var country = new google.maps.Polygon({
        paths: newCoordinates,
        strokeColor: 'transparent',
        strokeOpacity: 1,
        strokeWeight: 0.3,
        fillColor: '#cd0000',
        fillOpacity: 0,
        name: rows[i][0],
        zIndex: 100

      });
      google.maps.event.addListener(country, 'mouseover', function() {
        this.setOptions({
          fillOpacity: 0.3
        });
      });
      google.maps.event.addListener(country, 'mouseout', function() {
        this.setOptions({
          fillOpacity: 0
        });
      });
      google.maps.event.addListener(country, 'click', function() {
        var countryName = this.name;
        var code = convert(countryName); // Calls a function that converts the name of the country to its official ISO 3166-1 alpha-2 code.
        var modal = document.querySelector('.modal');
        var instance = M.Modal.init(modal);
        instance.open();

      });


      country.setMap(map);
    }
  }
  //console.log(map);
  //test(map)
}

编辑 显然数据层不是问题,但图标是。这就是为什么我这样做时它不起作用的原因:

     map.data.setStyle(function(feature) {
        var percentage = parseFloat(feature.getProperty('percentage'));

        return ({
            icon: {
                path: google.maps.SymbolPath.CIRCLE,
                scale: percentage,
                fillColor: '#00ff00',
                fillOpacity: 0.35,
                strokeWeight: 0,
                clickable: false
            }

        })

    });

正确的做法是这样的:

    map.data.setStyle(function(feature) {
        var percentage = parseFloat(feature.getProperty('percentage'));

        return ({
            icon: {
                path: google.maps.SymbolPath.CIRCLE,
                scale: percentage,
                fillColor: '#00ff00',
                fillOpacity: 0.35,
                strokeWeight: 0
            },
            clickable: false
        })

    });

这里基本上有 2 个选项:

  1. 将多边形的 zIndex 设置为比数据层更高的数字。您的多边形将是可点击的,但显然会出现在数据层上方,这可能不是您想要的。

  2. 将数据层的clickable属性设置为false,这样就可以点击下面的元素了。这将有效如果您不需要对数据层上的点击做出反应...

选项 2 示例代码:

map.data.setStyle({
    clickable: false
});

编辑:下面的完整工作示例,使用选项 2。如您所见,多边形位于数据层下方,但您仍然可以单击它。

function initMap() {

  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: {
      lat: -28,
      lng: 137
    }
  });

  var polygon = new google.maps.Polygon({
    strokeOpacity: 0,
    strokeWeight: 0,
    fillColor: '#00FF00',
    fillOpacity: .6,
    paths: [
      new google.maps.LatLng(-26, 139),
      new google.maps.LatLng(-23, 130),
      new google.maps.LatLng(-35, 130),
      new google.maps.LatLng(-26, 139)
    ],
    map: map
  });

  polygon.addListener('click', function() {

    console.log('clicked on polygon');
  });

  // Load GeoJSON
  map.data.loadGeoJson('https://storage.googleapis.com/mapsdevsite/json/google.json');

 // Set style
  map.data.setStyle({
    fillColor: '#fff',
    fillOpacity: 1,
    clickable: false
  });
}
#map {
  height: 200px;
}
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
<div id="map"></div>

我发现,在设置 z-order 之后,当有很多多边形时,地图 api 不会可靠地将点击发送到顶层的多边形要素。

我有一个区域数据层,其中每个要素都是一个选区边界。当您单击一个要素时,它会在顶部加载另一个数据层。顶层由区域内具有更高 z-order 的多边形组成,代表该区域内的房屋产权边界。

加载房屋后,点击房屋应将点击发送到房屋多边形,而不是区域。但这有时会失败 - 特别是如果有很多房子。

为了解决这个问题,在点击一个区域特征后,我将该特征设置为不可点击。然后点击总是传播到正确的房屋特征。您仍然可以单击下层的其他功能,只是不能单击所选的功能。如果您的数据和演示遵循类似的模式,则此解决方案应该有效。

/* private utility is only called by this.hideOnlyMatchingFeaturesFromLayer() */
  _overrideStyleOnFeature(feature, layer, key, value,  overrideStyle, defaultStyle) {
    if (feature.getProperty(key) === value) {
      if (this.map) {
        layer.overrideStyle(feature, overrideStyle);
      }
    } else {
      if (this.map) {
        layer.overrideStyle(feature, defaultStyle);
      }
    }
  }

  /* Apply an overrideStyle style to features in a data layer that match key==value
   * All non-matching features will have the default style applied.
   * Otherwise all features except the matching feature is hidden!
   * Examples:
   *    overrideStyle = { clickable: false,strokeWeight: 3}
   *    defaultStyle = { clickable: true,strokeWeight: 1}
   */

  overrideStyleOnMatchingFeaturesInLayer(layer, key, value, overrideStyle, defaultStyle) {
    layer.forEach((feature) => {
      if (Array.isArray(feature)) {
        feature.forEach((f) => {
          _overrideStyleOnFeature(f, layer, key, value, overrideStyle, defaultStyle);
        });
      } else {
        _overrideStyleOnFeature(feature, layer, key, value, overrideStyle, defaultStyle);
      }
    });
  }

  /* example usage */
  overrideStyleOnMatchingFeaturesInLayer(
    theRegionsDataLayer,
    'PROP_NAME',
    propValue,
    { clickable: false, strokeWeight: 3},
    { clickable: true, strokeWeight: 1}
);