Кластеризация маркеров Google maps

Тема в разделе "JavaScript", создана пользователем 13zone, 15 фев 2018.

Модераторы: ZiX
  1. 13zone

    13zone

    Регистр.:
    22 ноя 2008
    Сообщения:
    205
    Симпатии:
    45
    Из базы данных через хмл собираю массив маркеров, затем вывожу на карте. Никак не могу сделать кластеризацию (обьединение) ближайших маркеров в одну группу. Подскажите где туплю?
    библиотека подключена, пробую сделать как указано в гугле - не работает...

    <script>
    var markers = [];

    var icons = {
    batarei: {
    icon: 'batarei.png'
    },
    makulatura: {
    icon: 'makulatura.png'
    },
    odejda: {
    icon: 'odejda.png'
    },
    metallolom: {
    icon: 'metallolom.png'
    },
    info: {
    icon: 'info-i_maps.png'
    }
    };
    var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    var map;
    var geocoder;
    var infoWindow;
    function initialize() {
    map = new google.maps.Map(document.getElementById("map"), {
    center: new google.maps.LatLng(49.988546, 36.233000),
    zoom: 11,
    gridSize: 50,
    mapTypeControl: true,
    disableDefaultUI: true,
    zoomControl: true,
    imagePath: 'images/',
    });

    infoWindow = new google.maps.InfoWindow;
    // читаю хмл файлик
    downloadUrl('/dbtoxml.php', function(data) {
    var xml = data.responseXML;
    var markers = xml.documentElement.getElementsByTagName('marker');
    Array.prototype.forEach.call(markers, function(markerElem) {
    var id = markerElem.getAttribute('id');
    var markers = markerElem.getAttribute('markers');
    var name = markerElem.getAttribute('name');
    var address = markerElem.getAttribute('address');
    var type = markerElem.getAttribute('type');
    var photo = markerElem.getAttribute('photo');
    var point = new google.maps.LatLng(
    parseFloat(markerElem.getAttribute('lat')),
    parseFloat(markerElem.getAttribute('lng')));
    // формирование информационного бокса для маркеров
    var infowincontent = document.createElement('div');
    var strong = document.createElement('strong');
    strong.textContent = ("Что принимают: "+name)
    infowincontent.appendChild(strong);
    // infowincontent.appendChild(document.createElement('br'));
    var text = document.createElement('text');
    text.textContent = ("Адрес: "+address)
    infowincontent.appendChild(text);
    infowincontent.appendChild(document.createElement('br'));
    text.textContent = ("Описание обьекта: "+type)
    infowincontent.appendChild(text);
    infowincontent.appendChild(document.createElement('br'));
    // добавляю фото в инфоблок маркера
    var img = document.createElement('img');
    img.src = (""+photo+"");
    infowincontent.appendChild(img);

    // кластеризация (обьединение) маркеров на карте
    var markerCluster = new MarkerClusterer(_this.map, markers,
    {
    maxZoom: 10,
    gridSize: 60,
    styles: null
    });

    var marker = new google.maps.Marker({
    map: map,
    position: point,
    // label: icon.label,
    title: name,
    icon: icons[markers].icon,
    // анимация, маркеры падают на карту
    // animation: google.maps.Animation.DROP,
    });

    // наложение слоя автомобильного трафика
    var trafficLayer = new google.maps.TrafficLayer();
    trafficLayer.setMap(map);

    marker.addListener('click', function() {
    infoWindow.setContent(infowincontent);
    infoWindow.open(map, marker);
    map.setZoom(15); // Устанавливаем ZOOM 16
    map.setCenter(marker.getPosition()); // Центруем карту по маркеру, на который кликнули
    // маркер подпрыгивает при нажатии, только не останавливается
    if (icons[markers].getAnimation() !== null) {
    icons[markers].setAnimation(null);
    } else {
    icons[markers].setAnimation(google.maps.Animation.BOUNCE);
    }
    });
    google.maps.event.addListener(infoWindow, 'closeclick', function(event) {
    map.setZoom(12);
    });
    });
    });
    }
    function newLocation(newLat,newLng)
    {
    map.setCenter({
    lat : newLat,
    lng : newLng
    });
    }

    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);
    }
    google.maps.event.addDomListener(window, 'load', initialize);

    function doNothing() {}
    </script>
     
  2. 13zone

    13zone

    Регистр.:
    22 ноя 2008
    Сообщения:
    205
    Симпатии:
    45
     
  3. chicha

    chicha Создатель

    Регистр.:
    21 май 2012
    Сообщения:
    23
    Симпатии:
    6
    Посмотрел заготовку, лично у меня не отобраютса маркери така как они неправильно парсятса.
    [​IMG]
    Как видно в дебагере. В обекте респонса responseXML = null, а сами маркери приходять responce і responseText.
    Вариант 1: Спарсать маркери з текста
    Вариант 2: Поексперементировать с content-type на сервере
    Вариант 3: Согласно документации https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML
    можна оверайднуть mimeType для принудительной парсинга XML:

    Код:
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/server', true);
    
    // If specified, responseType must be empty string or "document"
    xhr.responseType = 'document';
    
    // overrideMimeType() can be used to force the response to be parsed as XML
    xhr.overrideMimeType('text/xml');
    
    xhr.onload = function () {
      if (xhr.readyState === xhr.DONE) {
        if (xhr.status === 200) {
          console.log(xhr.response);
          console.log(xhr.responseXML);
        }
      }
    };
    
    xhr.send(null);

    И наконец работающий ппример на jsfiddle http://jsfiddle.net/2qdvjc4j/74/

    PS: На даний момент проблема в парсинге
     
  4. 13zone

    13zone

    Регистр.:
    22 ноя 2008
    Сообщения:
    205
    Симпатии:
    45
    спасибо, гляну на еще один работающий пример.. (с парсингом все в порядке, просто сейчас на тестовом сайте залита малость багованная версия файлика ) звиняйте (утром перезалью на нормальную версию)
     
  5. chicha

    chicha Создатель

    Регистр.:
    21 май 2012
    Сообщения:
    23
    Симпатии:
    6
    Тогда понятно.
    Солгласно документаци
    https://developers.google.com/maps/documentation/javascript/marker-clustering
    Коструктор MarkerClusterer в качестве пареметра markers дожень принимать масив с инстансов типа google.maps.Marker
    1 Ви должни спарсать маркери
    2 Далее создать масив из инстрастов протипа google.maps.Marker
    код с гуглопримера:

    Код:
    var markers = locations.map(function(location, i) {
              return new google.maps.Marker({
                position: location,
                label: labels[i % labels.length]
              });
            });
    3. И только после етого сделать new MarkerClustere

    У вас же markers которие в scope Array.prototype.forEach.call(markers, function(markerElem) {
    ...

    ето var markers = markerElem.getAttribute("markers");
    а не @param {Array.<google.maps.Marker>=}

    код функции класетеразора
    https://github.com/googlemaps/js-marker-clusterer/blob/gh-pages/src/markerclusterer.js
     
    13zone нравится это.
  6. 13zone

    13zone

    Регистр.:
    22 ноя 2008
    Сообщения:
    205
    Симпатии:
    45
    идем далее, переколбасил малость код...
    создаю массив из базы данных

    Код:
    $locat = array();
    while ($row = @mysql_fetch_assoc($result)){
        $locat []= 'lat: ' . $row['lat'] .  ', lng: ' . $row['lng'];
    }
    $point = json_encode($locat);
    смотрю дамп массива, все вроде в порядке..
    пытаюсь втулить массив в скрипт

    Код:
    function initMap() {
    
            var map = new google.maps.Map(document.getElementById('map'), {
                zoom: 3,
                center: {lat: -28.024, lng: 140.887}
            });
            var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            var markers = locations.map(function(location, i) {
                return new google.maps.Marker({
                    position: location,
                    label: labels[i % labels.length]
                });
            });
            var markerCluster = new MarkerClusterer(map, markers,
                {imagePath: 'images/m'});
        }
    
    var locations = '<?=$point; ?>';   // Здесь координаты маркеров
    чего-то не работает ))) где опять накосячил?
     
  7. 13zone

    13zone

    Регистр.:
    22 ноя 2008
    Сообщения:
    205
    Симпатии:
    45
    все... справилсИ.. спасибо всем кто не прошел мимо )

    Код:
            var markers = <?=$point; ?>.map(function(location, i) {
                return new google.maps.Marker({
                    position: location,
                    label: labels[i % labels.length]
                });
            });
    в таком виде кластеризация маркеров из массива работает

    + массив собран как нужно

    Код:
    while ($row = @mysql_fetch_assoc($result)){
        $latt[] = array('lat' => $row['lat'], ' lng' => $row['lng']);
    }
    $point = json_encode($latt);
    $point = str_replace('"', '', $point);