自动在Google地图信息块中重新加载数据,而无需刷新页面

时间:2015-02-18 22:28:52

标签: javascript google-maps

我目前正在开展一个项目,该项目在美国各地分散有大约20个标记。每个引脚都有一个相应的信息块(不同于infowindow,https://github.com/googlemaps/js-info-bubble),它始终显示(无需单击标记即可显示信息)。

我的问题是,项目的全部内容是获取最新数据(从每15秒发出一次XML的外部站点进入)。理想情况下,我希望信息的内容能够更新"更新"适当而无需刷新整个页面。这使您可以在地图上移动,并将其重置为默认位置,并且整体上不那么刺耳。有没有办法这样做?

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

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

2 个答案:

答案 0 :(得分:2)

  1. 通过setTimeout

  2. 请求XML不断启动新的延迟请求
  3. 您需要为标记添加一些不同的属性。因为看起来这个独特的属性可能是位置,因为它们是静态的。

  4. 创建一个存储标记的对象,并使用marker-position的字符串表示作为键。

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

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

    注意:当infoBubble已经打开时,您必须调用infoBubble的方法updateContent_(),否则下次打开infoBubble时将更新内容。您可以使用isOpen()方法检查infoBubble是否已打开。


    示例实现:

    请求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对其进行修改):

    • 包含每个标记/气泡属性的项目具有nodeName 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检索。

    • 你会看到标记/气泡有时会消失,当地图中有标记/气泡不会出现在更新的XML中时(脚本会删除它们)会发生这种情况


    代理脚本示例:

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

答案 1 :(得分:0)

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

如果没有,请将上次更新列表存储在变量中,并在通过AJAX进行更新时将时间作为参数发送给服务器,然后让服务器快速检查添加了哪些新用户,以及发送那些。然后,只需将新服务器的新数组与旧数组合并。我强烈建议不要每隔10秒拨打一个新名字。您不仅会在服务器上运行更多带宽,还必须在为列表中找到列表中的下一个用户时增加CPU使用率,然后将其发送给您。对于良好的实践,始终让客户尽可能多地完成工作,而不会有滞后。只有一台服务器,但客户端更多。转移到客户端的每个操作都将为您的服务器节省数百甚至数千个操作。

至于长轮询与setInterval,我建议在这种情况下使用setInterval。您至少可以发送带有时间参数的请求,指定上次更新时间,因此只需要发送该小部分而不是整个数据数组。

相关问题