Маркеры Google по тому же адресу не показывают все маркеры


16

Я работал над этой картой - http://www.mediwales.com/mapping/test/

Это хорошо строит компании и хорошо их группирует, но возникла проблема с компаниями в одном здании с одним и тем же адресом. Это показывает только одну компанию, а не все из них.

Как я могу заставить его отображать все компании по одному адресу?

Маркеры геокодируются по названию / номеру здания, улице, городу, почтовому индексу. Я предполагаю, что маркеры присутствуют, так как здание, в котором есть 3 компании, показывает 3 в кластере. Тем не менее, когда вы нажимаете на нее вниз, это показывает только одну компанию.

ОБНОВИТЬ:

Мне удалось заставить их смещаться, но он смещает все маркеры, когда я хочу, чтобы они смещались, только если есть несколько одинаковых маркеров. (Благодаря ответу Кейси).

   <script type="text/javascript">
    //<![CDATA[

    var customIcons = {
      restaurant: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      bar: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(53.4788, -3.9551),
        zoom: 6,
        mapTypeId: 'roadmap'
      });
var infowindow = new google.maps.InfoWindow();
var min = .999999;
var max = 1.000001;

      // Change this depending on the name of your PHP file
      downloadUrl("<?php bloginfo('stylesheet_directory'); ?>/phpsqlajax_genxml.php ", function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");



          var offsetLat = markers[i].getAttribute("lat") * (Math.random() * (max - min) + min);
          var offsetLng = markers[i].getAttribute("lng") * (Math.random() * (max - min) + min);



          var point = new google.maps.LatLng(offsetLat, offsetLng);
          var html = "<b>" + name + "</b> <br/>" + address;
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          google.maps.event.addListener(marker, 'click', (function(marker, i) {
                        return function() {
                            infowindow.setContent(markers[i].getAttribute("name"));
                            infowindow.open(map, marker);
                        }
                    })(marker, i));
          cluster.push(marker);
        }
        var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infoWindow, html) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject('Microsoft.XMLHTTP') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open('GET', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>

   <script type="text/javascript">
    //<![CDATA[

    var customIcons = {
      restaurant: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_blue.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      },
      bar: {
        icon: 'http://labs.google.com/ridefinder/images/mm_20_red.png',
        shadow: 'http://labs.google.com/ridefinder/images/mm_20_shadow.png'
      }
    };

    function load() {
      var cluster = [];
      var map = new google.maps.Map(document.getElementById("map"), {
        center: new google.maps.LatLng(53.4788, -3.9551),
        zoom: 6,
        mapTypeId: 'roadmap'
      });
var infowindow = new google.maps.InfoWindow();

      // Change this depending on the name of your PHP file
      downloadUrl("<?php bloginfo('stylesheet_directory'); ?>/phpsqlajax_genxml.php ", function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
          var name = markers[i].getAttribute("name");
          var address = markers[i].getAttribute("address");
          var type = markers[i].getAttribute("type");
          var point = new google.maps.LatLng(
              parseFloat(markers[i].getAttribute("lat")),
              parseFloat(markers[i].getAttribute("lng")));
          var html = "<b>" + name + "</b> <br/>" + address;
          var icon = customIcons[type] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icon.icon,
            shadow: icon.shadow
          });
          google.maps.event.addListener(marker, 'click', (function(marker, i) {
                        return function() {
                            infowindow.setContent(markers[i].getAttribute("name"));
                            infowindow.open(map, marker);
                        }
                    })(marker, i));
          cluster.push(marker);
        }
        var mc = new MarkerClusterer(map,cluster);
      });
    }

    function bindInfoWindow(marker, map, infoWindow, html) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    function downloadUrl(url, callback) {
      var request = window.ActiveXObject ?
          new ActiveXObject('Microsoft.XMLHTTP') :
          new XMLHttpRequest;

      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          request.onreadystatechange = doNothing;
          callback(request, request.status);
        }
      };

      request.open('GET', url, true);
      request.send(null);
    }

    function doNothing() {}

    //]]>
  </script>

Ответы:


15

Кластерер отображается правильно. Все маркеры строятся. Проблема в том, что вы можете нажать только на самый верхний маркер, создавая впечатление, что есть только один маркер.

Чтобы увидеть содержимое совпадающих маркеров, вам нужно будет передать содержимое информационного окна нижележащих маркеров в самый верхний маркер.

Для этого, во-первых, следите за каждым маркером. Вы используете MarkerClusterer, поэтому экземпляр markerClusterer будет содержать каждый маркер. Когда возвращается каждый результат геокодирования, сравните ширину этого запроса со всеми уже нанесенными маркерами. Вы можете сравнить позиции, используя метод equals объекта latlng .

Если новый маркер совпадает с позицией существующего маркера, возьмите содержимое информационного окна от первого маркера и добавьте его к содержимому информационного окна нового маркера. Таким образом, когда вы нажимаете на самый верхний маркер (вторая компания), он будет показывать информацию от обеих компаний. Если существует более двух компаний, вам нужно получить содержимое информационного окна для всех соответствующих маркеров. Этот метод также позволит кластеру маркеров по-прежнему отображать правильное количество маркеров.

Вот рабочий пример и код JavaScript. Первый и второй адреса совпадают. Когда вы нажмете на маркер для 2, он покажет «2 и 1».

<script type="text/javascript"> 
var map;

//marker clusterer
var mc;
var mcOptions = {gridSize: 20, maxZoom: 17};

//global infowindow
var infowindow = new google.maps.InfoWindow();

//geocoder
var geocoder = new google.maps.Geocoder(); 

var address = new Array("1000 Market St, Philadelphia, PA","1000 Market St, Philadelphia, PA","1002 Market St, Philadelphia, PA","1004 Market St, Philadelphia, PA");
var content = new Array("1","2","3","4");

function createMarker(latlng,text) {

    var marker = new google.maps.Marker({
        position: latlng
    });

    ///get array of markers currently in cluster
    var allMarkers = mc.getMarkers();

    //check to see if any of the existing markers match the latlng of the new marker
    if (allMarkers.length != 0) {
        for (i=0; i < allMarkers.length; i++) {
            var currentMarker = allMarkers[i];
            var pos = currentMarker.getPosition();

            if (latlng.equals(pos)) {
                text = text + " & " + content[i];
            }

        }
    }

    google.maps.event.addListener(marker, 'click', function() {
        infowindow.close();
        infowindow.setContent(text);
        infowindow.open(map,marker);
    });

    return marker;
}

function geocodeAddress(address,i) {

    geocoder.geocode( {'address': address}, function(results, status) {

        if (status == google.maps.GeocoderStatus.OK) {

            var marker = createMarker(results[0].geometry.location,content[i]);
            mc.addMarker(marker);

        } else { 
            alert("Geocode was not successful for the following reason: " + status); 
        } 
    });
}

function initialize(){

    var options = { 
        zoom: 13, 
        center: new google.maps.LatLng(39.96225,-75.13222), 
        mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 

    map = new google.maps.Map(document.getElementById('map'), options); 

    //marker cluster
    mc = new MarkerClusterer(map, [], mcOptions);

    for (i=0; i<address.length; i++) { 
        geocodeAddress(address[i],i);
    }

}       
</script> 

РЕДАКТИРОВАТЬ: Ответ на комментарий

В качестве альтернативы, вы можете подтолкнуть совпадающие маркеры, применив небольшой (случайное число, например, между .999999 и 1.000001) множитель к позиции каждого совпадающего маркера. Вот пример. При этом используются те же данные, что и в первом примере, за исключением того, что маркеры 1 и 2 размещаются друг над другом и совместно используют информационное окно, маркер 2 смещен от маркера 1. Обратите внимание, что результаты геокодирования будут чуть менее точно. Соответствующий код ниже:

//min and max limits for multiplier, for random numbers
//keep the range pretty small, so markers are kept close by
var min = .999999;
var max = 1.000001;

    function createMarker(latlng,text) {

        ///get array of markers currently in cluster
        var allMarkers = mc.getMarkers();

        //final position for marker, could be updated if another marker already exists in same position
        var finalLatLng = latlng;

        //check to see if any of the existing markers match the latlng of the new marker
        if (allMarkers.length != 0) {
            for (i=0; i < allMarkers.length; i++) {
                var existingMarker = allMarkers[i];
                var pos = existingMarker.getPosition();

                //if a marker already exists in the same position as this marker
                if (latlng.equals(pos)) {

                    //update the position of the coincident marker by applying a small multipler to its coordinates
                    var newLat = latlng.lat() * (Math.random() * (max - min) + min);
                    var newLng = latlng.lng() * (Math.random() * (max - min) + min);

                    finalLatLng = new google.maps.LatLng(newLat,newLng);

                }                   
            }
        }

        var marker = new google.maps.Marker({
            position: finalLatLng
        });     

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.close();
            infowindow.setContent(text);
            infowindow.open(map,marker);
        });

        return marker;
    }

Спасибо за ответ. Просто возвращаюсь к этому проекту! Правильно, можно ли будет немного сместить маркеры? В противном случае тип вовлеченных компаний будет спорить, кто возглавляет информационное окно (мелкий, я знаю!).
Роб

Хорошая работа @Casey. Это выглядит великолепно!
RyanKDalton-OffTheGridMaps

@Casey Спасибо за ответ, как я могу включить это в мой код? Я борюсь с переработкой кода, как это! Вот мой источник - view-source: mediwales.com/mapping/members
Роб

@Rob Используйте мой пример страницы в качестве руководства. Одно большое различие между нашим кодом состоит в том, что я вытащил свой код создания маркера из моего адресного кода геокода и поместил его в свою собственную функцию, называемую createMarker. Вы должны будете сделать это также, чтобы заставить метод подталкивания работать.
Кейси

@Casey У меня было несколько попыток, и я не могу заставить его работать ... Я не хочу, чтобы это звучало так, будто я просто заставляю тебя делать это, но я пытался в течение последнего дня.
Роб

3

У меня была та же проблема с несколькими маркерами на одном и том же широте / длине для приложения на территории продаж. Это был распространенный сценарий в моем приложении с несколькими клиентами по одному и тому же адресу, например, клиенты в одном здании небоскреба и, следовательно, с одним физическим адресом улицы.

Я нашел альтернативный ответ с, возможно, лучшим пользовательским интерфейсом (UX) для перекрывающихся маркеров. Спасибо Джорджу МакКеррону за создание библиотеки OverlappingMarkerSpiderfier . Эта библиотека JavaScript для Google Maps v3 переопределяет поведение по умолчанию для перекрывающихся маркеров. Библиотека позволяет настроить радиус смещения для перекрытия (по умолчанию 20 пикселей).

Примеры скриншотов с http://jawj.github.io/OverlappingMarkerSpiderfier/demo.html :

Скриншот перекрывающихся маркеров перед кликом Снимок экрана: щелчок по любому из перекрывающихся маркеров Снимок экрана нажатия на маркер в "паутине" паутины перекрывающихся маркеров


0

Я предлагаю изменить вышеуказанную функцию следующим образом, потому что полученные результаты кажутся мне лучше.

function adjustMarkerPlace(latlng) {
  ///get array of markers currently in cluster 
  //final position for marker, could be updated if another marker already exists in same position
  var finalLatLng = latlng;

  //check to see if any of the existing markers match the latlng of the new marker
  if (markers.length !== 0) {
      for (let i=0; i < markers.length; i++) {
          var existingMarker = markers[i];
          var pos = existingMarker.getPosition();

          //check if a marker already exists in the same position as this marker
          if (latlng.equals(pos)) {

              //update the position of the coincident marker by applying a small multipler to its coordinates
              var newLat = latlng.lat() + (Math.random() / 10000);
              var newLng = latlng.lng() + (Math.random() / 10000);

              finalLatLng = new google.maps.LatLng(newLat,newLng);

          }
      }
  }

  return finalLatLng;

}

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.