2015-02-18 3 views
-1

В настоящее время я работаю над проектом, который содержит около 20 маркеров, разбросанных по США. Каждый штырь имеет соответствующую инфобабочку (отличную от infowindow, https://github.com/googlemaps/js-info-bubble), которая всегда отображается (нет необходимости нажимать маркер, чтобы получить информационную подсказку).Автоматическая перезагрузка данных в Google Maps инфооббюро без обновления страницы

Моя проблема заключается в том, что вся цель проекта - получать самые последние данные (поступающие с внешнего сайта, который выплескивает XML каждые 15 секунд). В идеале я хочу, чтобы содержимое информационных бюллетеней «обновлялось» соответствующим образом, не обновляя всю страницу. Это позволяет перемещаться по карте с ее сбросом до положения по умолчанию и в целом меньше. Есть ли способ сделать это?

Обновление: Я нашел это решение: (Google Map v3 auto refresh Markers only), но есть несколько вопросов:

1). Как он постоянно обновляет маркеры? Они обновляются только один раз через 10 секунд.
2.) Могу ли я применить аналогичную логику только для обновления информации? Помните, мои маркеры являются статическими, это единственное содержимое инфообъектива, которое необходимо обновить.

+1

Пожалуйста, пост примера для XML –

+0

XML-настоящее время я использую привязано к спортивным событиям, так что данные не будут автоматически исх пока игра не начнется. – John

+0

Ищите «тикер: null, // setTimeout reference» и 'setTimeout' в ответе, который вы связали.и для 'delay: 10000, // (миллисекунды) интервал между последовательными get' – DanFromGermany

ответ

2
  1. чтобы просить XML продолжительную начать новый отложенный запрос через setTimeout

  2. Вам потребуется некоторое отчетливое свойство для маркеров. Как кажется, это отдельное свойство может быть позицией, потому что они являются статическими.

Создайте объект, в котором вы храните маркеры, и используйте строковое представление положения маркера в качестве ключей.

Для получения XML вы можете, конечно, использовать AJAX (когда XML приходит из другого домена, он должен либо отправить соответствующий Access-Control-Allow-Origin -header, либо использовать собственный прокси-скрипт на своем собственном сервере, который пересылает XML) ,

Чтобы обновить контент, используйте метод setContent() infoBubble (используйте желаемый контент в качестве первого аргумента функции).

Примечание: если информационная банка уже открыта, вы должны вызвать метод infoBubble updateContent_(), иначе контент будет обновлен, когда в следующий раз откроется инфо-банк. Вы можете использовать метод isOpen(), чтобы проверить, открыт ли инфо-банк.


Образец-реализация:

Функция, которая запрашивает XML:

function downloadUrl(url,//URL of the XML-file 
         callback,//function 2 execute 
         map//the map 
        ) { 

     var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') 
             : new XMLHttpRequest; 

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

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

Функция, которая обрабатывает ответ (используемый в качестве callback -argument функции выше). Пока не ясно, как XML выглядит, функция требует следующее (вы, вероятно, необходимо изменить его на основе данного XML):

  • элементы, которые содержат свойства для каждого маркера/пузырем имеют имя узла event
  • широта хранится в атрибут элементы lat
  • долготы хранится в атрибут элементы lng
  • название/подпись/whateve события хранится в элементы атрибутов name
  • содержимое будет textContent элемента , например.

Sample-XML:

<events> 
    <event lat="41.8781136" lng="-87.629798" name="Bulls vs. Mavericks">1:0</event> 
</events> 

function xhrCallback(r, //the request 
         s, //request-status 
         u, //request-url 
         m, //map 
         c //callback 
) { 
     var events = r.responseXML.getElementsByTagName('event'); 
     if (!m.markers) { 
      //here we store the markers 
      m.markers = {}; 

     } 
     //will be used later to remove markers which will not exist in the XML 
     var keys=Object.keys(m.markers); 

     for (var i = 0; i < events.length; ++i) { 
      //the current XML-node 
      var event = events[i], 
       position = new google.maps.LatLng(event.getAttribute('lat'), 
               event.getAttribute('lng')), 
       hash = position.toString(), 
       content = '<h2>' + event.getAttribute('name') + '</h2>' + 
         event.firstChild.data; 

      //when the hash doesn't exist in m.markers 
      if (!m.markers[hash]) { 
       //create a new marker & infobubble 
       m.markers[hash] = new google.maps.Marker({ 
        map: m, 
        position: position, 
        bubble: new InfoBubble({ 
         content: content 
        }) 
       }); 

       google.maps.event.addListener(m.markers[hash], 'click', function() { 

        this.bubble.open(this.getMap(), this) 
       }); 
       google.maps.event.trigger(m.markers[hash], 'click'); 

      } else { 
      m.markers[hash].bubble.setContent(content); 
       if (m.markers[hash].bubble.isOpen()) { 
        m.markers[hash].bubble.updateContent_(); 
       } 
       //remove the current hash from the keys-array 
       (function(h){ 
       var index=keys.indexOf(h); 
        if(index>=0){ 
         keys.splice(index,1); 
        } 
       }(hash)); 
      } 
     } 

     //remove markers and bubbles which doesn't exist in the XML 
     keys.forEach(function(k){   
      m.markers[k].setMap(null); 
      m.markers[k].bubble.close(); 
      delete m.markers[k]; 
     }); 

     //new request 
     setTimeout(function() { 
      downloadUrl(u, c, m) 
     }, 
     10000//delay in milliseconds 
    ); 

    } 

Чтобы выполнить это называют 1 раз:

downloadUrl('path/to/file.xml', 
      xhrCallback,//function from above 
      map//your google.maps.Map 
      ); 

Демо: http://jsfiddle.net/doktormolle/fwk5e1nq/

  • Демо просто устанавливает содержимое в текущее время, но контент будет извлекаться через AJAX.

  • вы увидите, что маркеры/пузырьки иногда исчезают, это происходит, когда есть маркеры/пузырьки в карте, которая не будет присутствовать в обновленном формате XML (скрипт удалит их)


Пример прокси-скрипт:

<?php 
$url='http://external.service.com/path/to/the.xml'; 
header('Content-Type:text/xml'); 
die(file_get_contents($url)); 
?> 
+0

Не могли бы вы подробнее рассказать о том, что потребуется для использования прокси-сервера serveride на моем собственном сервере, который пересылает XML? Например, у меня должна быть потенциальная другая компьютерная установка, единственная цель которой - получить XML-данные с общедоступного веб-сайта (который не будет устанавливать подходящий заголовок Access-Control-Allow-Origin-header), чтобы я мог его захватить там? – John

+0

Вам нужно будет запустить скрипт serveride, это единственное требование. Этот скрипт должен 1. отправить правильный заголовок Content-Type, например. 'text/xml' 2. прочитать внешний ressource 3. распечатать содержимое внешнего ressource –

+0

Я все еще немного запутался в том, как я могу реализовать такой скрипт. Проект, над которым я сейчас работаю, находится в ASP.NET MVC. Как бы php-скрипт (я предполагаю, что php - это способ пойти) интегрироваться с остальной частью моего проекта? Как это будет работать? Или проект MVC не является хорошей идеей для чего-то подобного? Извините за мое непонимание, это все тихо для меня. Я действительно ценю твою помощь. – John

0

Я бы определенно подумал о кешировании. Особенно, если у вас есть наборы с гораздо большим количеством пользователей, запрос AJAX каждые 10 секунд может легко перегрузить ваш сервер. Однако, если вы хотите сохранить его простым, сделайте запрос каждые несколько минут, чтобы обновить. Кэш пользователей, их сгенерировали в код javascript, скажем, users = new Array (user1, user2, ...). Вам не нужно постоянно обновлять страницу, если это не так важно, поскольку большинство пользователей будут перемещаться в течение минуты или двух в любом случае. Если у вас длинный список, который меняется каждые несколько секунд, это дает вам достаточно времени, чтобы не обновлять его с помощью AJAX и просто полагаться на список пользователей, сгенерированный сервером.

Если нет, сохраните последний раз, когда вы обновили список в переменной, и отправьте время в качестве аргумента на ваш сервер при обновлении через AJAX, а затем попросите сервер быстро проверить, какие новые пользователи были добавлены, и отправить только те. Затем просто слейте новый массив новых серверов со старым массивом. Я настоятельно рекомендую не делать звонок каждые 10 секунд для нового имени. Вы не только увеличите пропускную способность вашего сервера, но и увеличите использование ЦП, когда вам придется найти следующего пользователя в списке, а затем отправить его. Для хорошей практики всегда позволяйте клиенту выполнять как можно большую часть работы, не имея отставания. Существует только один сервер, но еще много клиентов. Каждая операция, которую вы переносите на клиентов, будет экономить на вашем сервере сотни, если не тысячи, операций.

Что касается длинных опросов против setInterval, я бы порекомендовал setInterval в этом случае. Вы можете по крайней мере отправить запрос с аргументом времени, указав последнее время обновления и, следовательно, только нужно отправить эту небольшую часть, а не весь массив данных.