在不刷新页面的情况下自动重新加载 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。您至少可以发送一个带有时间参数的请求,指定最后更新时间,因此只需要发送一小部分,而不是整个数据数组。
请求XML通过setTimeout
连续开始新的延迟请求
您需要一些不同的 属性 作为标记。看起来这个不同的 属性 可能是位置,因为它们是静态的。
创建一个存储标记的对象,并使用标记位置的字符串表示作为键。
要获得 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));
?>
我目前正在开展一个项目,该项目有大约 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。您至少可以发送一个带有时间参数的请求,指定最后更新时间,因此只需要发送一小部分,而不是整个数据数组。
请求XML通过
setTimeout
连续开始新的延迟请求您需要一些不同的 属性 作为标记。看起来这个不同的 属性 可能是位置,因为它们是静态的。
创建一个存储标记的对象,并使用标记位置的字符串表示作为键。
要获得 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));
?>