在不刷新页面的情况下自动重新加载 Google 地图信息气泡中的数据

Automatically reload data in Google Maps infobubble without page refresh

我目前正在开展一个项目,该项目有大约 20 个标记分布在美国各地。每个图钉都有一个相应的信息气泡(与信息窗口不同,https://github.com/googlemaps/js-info-bubble)始终显示(无需单击标记即可显示信息气泡)。

我的问题是,该项目的全部重点是获取最新数据(来自每 15 秒 XML 吐出的外部站点)。理想情况下,我想要的是将信息气泡的内容适当地 "update",而不必刷新整个页面。这使您可以在重置为默认位置的情况下在地图上移动,并且整体上不那么刺耳。有什么办法吗?

更新:我找到了这个解决方案:(Google Map v3 auto refresh Markers only) 但有几个问题:

1).他是如何不断让标记刷新的?他们只在 10 秒后更新一次。
2.) 我可以将类似的逻辑应用到 infobubble 刷新吗?请记住,我的标记是静态的,只有信息气泡的内容需要更新。

我肯定会考虑缓存。特别是如果你的集合有更多的用户,每 10 秒发出一个 AJAX 请求很容易使你的服务器过载。但是,如果您想保持简单,请每隔几分钟发出一次更新请求。缓存用户,将它们生成到 javascript 代码中,比如 users = new Array(user1, user2, ...)。如果页面不是那么重要,您实际上不必继续更新页面,因为大多数用户无论如何都会在一两分钟内离开。如果您有一个每隔几秒更改一次的长列表,那么您就有足够的时间不必使用 AJAX 进行更新,而只需依赖服务器生成的用户列表。

如果不是,请将上次更新列表的时间存储在变量中,并在通过 AJAX 更新时将时间作为参数发送到服务器,然后让服务器快速检查什么添加了新用户,只发送那些。然后,只需将新服务器的新阵列与旧阵列合并即可。不过,我强烈建议不要每 10 秒就给一个新名字打电话。您不仅会 运行 在您的服务器上增加更多带宽,还会增加 CPU 使用率,因为它必须为您找到列表中的下一个用户,然后将那个用户发送给您。为了获得良好的实践,请始终让客户尽可能多地完成工作,不要有延迟。只有一台服务器,但有更多的客户端。您转移到客户端的每个操作都会为您的服务器节省数百(如果不是数千)操作。

至于长轮询与 setInterval,在那种情况下我会推荐 setInterval。您至少可以发送一个带有时间参数的请求,指定最后更新时间,因此只需要发送一小部分,而不是整个数据数组。

  1. 请求XML通过setTimeout连续开始新的延迟请求

  2. 您需要一些不同的 属性 作为标记。看起来这个不同的 属性 可能是位置,因为它们是静态的。

创建一个存储标记的对象,并使用标记位置的字符串表示作为键。

要获得 XML,您当然可以使用 AJAX(当 XML 来自不同的域时,他们必须发送适当的 Access-Control-Allow-Origin-header 或您必须在自己的服务器上使用服务器端代理脚本来转发 XML).

要更新内容,请使用 infoBubble 的 setContent() 方法(使用所需内容作为第一个函数参数)。

注意:当一个信息气泡已经打开时,必须调用该信息气泡的方法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 参数)。目前还不清楚 xml 的样子,该函数需要以下内容(您可能必须根据给定的 XML 修改它):

  • 包含每个 marker/bubble 属性的项目具有节点名称 event
  • 纬度存储在项目属性中lat
  • 经度存储在项目属性中lng
  • title/caption/whateve 事件存储在 items 属性中 name
  • 内容将是项目的textContent 例如

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

  • 检索
  • 你会看到 markers/bubbles 有时会消失,当地图中有 markers/bubbles 而不会出现在更新的 [=90= 中时,就会发生这种情况](脚本将删除它们)


代理脚本示例:

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