Google Maps Api: невозможно щелкнуть по кликабельному многоугольнику позади слоя данных - PullRequest
0 голосов
/ 10 мая 2018

Привет! Я использую API Google Maps (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
        })

    });

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

Я обнаружил, что после установки 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}
);
0 голосов
/ 10 мая 2018

У вас есть 2 варианта:

  1. Установите zIndex ваших полигонов на большее число, чем слой данных. Ваши полигоны будут кликабельными, но, очевидно, будут отображаться над слоем данных, что может быть не тем, что вы хотите.

  2. Установите для свойства clickable слоя данных значение false, чтобы можно было щелкать элементы ниже. Это будет работать , если вам не нужно реагировать на щелчки на слое данных ...

Пример варианта 2:

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

Редактировать: Полный рабочий пример ниже, с использованием опции 2. Как вы можете видеть, Polygon находится ниже слоя данных, но вы все равно можете щелкнуть по нему.

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>
...