Маркетинг 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 буде утримувати кожен маркер. Коли кожен результат геокодування повертається, порівняйте latlng цього запиту з усіма маркерами, які вже були намічені. Можна порівняти позиції, використовуючи метод рівних об’єкта 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> 

EDIT: Відповідь на коментар

Крім того, ви можете натиснути на збігаючі маркери, застосувавши невелике (випадкове число, наприклад, між .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

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