Google Maps Api: невозможно щелкнуть интерактивный полигон за слоем данных

Привет, я использую Google Maps API (JavaScript) для создания интерактивной карты мира. Все шло очень хорошо, пока я не столкнулся с этой проблемой. Я использую многоугольники, чтобы показать очертания страны. Эти многоугольники вызывают модальное отображение информации о стране при нажатии. Это работало, пока я не начал использовать «Уровень данных: данные о землетрясении». Вместо использования данных о землетрясениях я использую информацию о продажах компании, в которой работаю. Таким образом, если большая часть наших клиентов находится в Нидерландах, уровень данных, назначенный Нидерландам, будет очень большим. Проблема в том, что из-за слоев данных страны больше не кликабельны. Я не могу нажать "сквозь" слой данных. Есть ли возможность, что я могу инициировать событие за уровнем данных?

Этот код отображает слои данных:

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 не сработает, потому что «Маркеры всегда отображаются перед строками линий и полигонами».

Есть ли способ щелкнуть полигон за слоем данных?

EDIT Я попытался присвоить полигону более высокий 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)
}

EDIT Очевидно, проблема была не в уровне данных, а в значке. Вот почему это не сработало, когда я сделал это:

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

    });

person atthijs98    schedule 10.05.2018    source источник
comment
Вы пробовали zIndex? Установка его на 1 на многоугольнике помещает его перед слоем данных.   -  person MrUpsidown    schedule 10.05.2018
comment
1) у вас опечатка должно быть clickable а не clickAble и 2) что сейчас не работает?   -  person MrUpsidown    schedule 10.05.2018
comment
Смотрите мой обновленный ответ с полным рабочим примером.   -  person MrUpsidown    schedule 10.05.2018


Ответы (2)


У вас в основном есть 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>

person MrUpsidown    schedule 10.05.2018
comment
Вы действительно? Код, на который вы ссылаетесь, не содержит ничего из того, что я предложил в своем ответе: нет z-индекса и нет кликабельного свойства. Обновите ваш вопрос с помощью кода, который вы использовали (не просто делитесь ссылкой). - person MrUpsidown; 10.05.2018

Я обнаружил, что после установки z-порядка API карт ненадежно отправляет клики на объект многоугольника в верхнем слое, когда много полигонов.

У меня был один слой данных регионов, где каждый объект является границей участка. Когда вы нажимаете на одну функцию, поверх нее загружается другой слой данных. Верхний слой состоит из полигонов внутри региона с более высоким z-порядком, представляющих границы титула дома в этом регионе.

После того, как дома загружены, щелчок по дому должен отправлять щелчок на полигон дома, а не на регион. Но это иногда не удавалось - особенно если домов много.

Чтобы решить эту проблему, после нажатия на функцию региона я сделал эту функцию неактивной. Затем клики всегда распространяются на правильный элемент дома. Вы по-прежнему можете нажимать на другие объекты нижнего слоя, но не на выбранный. Это решение должно работать, если ваши данные и презентация следуют аналогичному шаблону.

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

person intotecho    schedule 27.06.2019