谷歌地图信息动态内容未在第一次标记点击时加载
我正在尝试在google地图信息块中添加动态内容:
– 出现一个第一个标记点击空信息
– 在第二次点击标记时加载正确的内容
根据这个答案,我在先前定义的infobubble对象上使用domready
事件来启动加载动态内容的函数。
…虽然答案中的JS小提琴是误导性的,因为“动态”内容实际上是在使用new InfoBubble()
调用的content
选项之前加载的
我在控制台中获得所有正确的信号,即domready
function正在完成,并且在第一个标记点击时正确找到了内容。
尝试:
-
查看了infobubble.js代码,并在第1231行的任一侧放置了console.logs:
google.maps.event.trigger(this, 'domready');
结果表明,在动态函数开始之前,domready确实被解雇了。 -
使用infobubble
disableAnimation: true
选项禁用动画 – 认为在调用domready后可能会减慢信息量负载 – 但它不起作用 -
添加了最多3秒的
setTimeout()
,但这似乎没有帮助……无论如何,这将是一个糟糕的黑客。
如何在首次点击标记时加载动态内容?
JS小提琴在这里
笔记:
– 对于js小提琴示例我正在使用$.get()
调用 – 因为在我的应用程序中我使用小胡子将模板加载到信息块中
– 正在加载的示例内容与$.get()
调用无关(是的,我可以在没有$.get()
调用的情况下实现相同)但我只是尝试使用类似的代码布局+时序到我的自己的申请
问题似乎是open_
方法(将在open
-method中调用):
InfoBubble.prototype.open_ = function(opt_map, opt_anchor) { this.updateContent_(); if (opt_map) { this.setMap(opt_map); } //............................ }
它首先调用方法updateContent_
(其中将触发domready
-event),然后设置map
。 但是,在设置map
-property之前,覆盖层不会被添加到地图中,内容是尚未附加到文档的DocumentFragment / Node,因此jQuery可能找不到它。
可能的方法:
使用信息块的content_
-property作为jQuery选择器的上下文,那么内容是否已经附加到文档也无关紧要
google.maps.event.addListener(marker, 'click', function () { google.maps.event.addListenerOnce(infoBubble,'domready',function () { var that=this; //when we load the additional content asynchronously, //make sure that it's the correct content we are loading var token=new Date().getTime()*Math.random(); that.set('token',token); $.get('https://lh4.googleusercontent.com/-_Cox6aEnSkU/UQ_B0LK4khI/AAAAAAAAAzw/4H4dsWGPgeE/s150/go-button.png', function (myImage) { if(that.get('token')===token){ $(".dialog",that.content_).html(''); } }) }); infoBubble.open(map, marker); });
感谢Dr.Molle在答案中的观察,我找到了解决方案 – 这确实与在infobubble.js代码中放置domready
事件触发器有关。
不幸的是,它当前位于updateContent_()
函数中,在调用setMap()
之前由open_()
调用 – 这意味着在将infoBubble添加到DOM之前会触发domready。
在open_()
函数中调用setMap()
之后简单地添加domready
触发器是open_()
因为setMap()
是异步的…并且setMap()
函数没有特定的回调。
但是,根据OverlayView的文档 (这个插件正在使用的内容), setMap()
函数在使用有效的map对象调用setMap()
之后调用onAdd()
函数:
onAdd():实现此方法以初始化overlay DOM元素。 在使用有效映射调用setMap()之后调用此方法一次。 此时,窗格和投影将被初始化。
更简单地说:
在onAdd()方法中,您应该创建DOM对象并将它们作为窗格的子项追加。
因此, 在将infoBubble
附加到地图窗格之后 ,我们应该在onAdd()
函数中触发domready
事件:
/** * On Adding the InfoBubble to a map * Implementing the OverlayView interface */ InfoBubble.prototype.onAdd = function() { if (!this.bubble_) { this.buildDom_(); } this.addEvents_(); var panes = this.getPanes(); if (panes) { panes.floatPane.appendChild(this.bubble_); panes.floatShadow.appendChild(this.bubbleShadow_); } google.maps.event.trigger(this, 'domready'); // infobubble has now been added to DOM so we can fire `domready` };
我已经为谷歌创建了一个pull-request来更新infobubble.js代码并解决了这个问题。
JS在这里提供更新的代码(请参阅javascript窗口中的第910行,了解新的domready
展示位置)
http://jsfiddle.net/goredwards/7r96we66/
笔记:
– 我在旧的domready
调用和正确的(更新的) domready
调用中添加了jsfiddle中的时间戳 – 你会在console.log
看到它们 – 它在我的系统上大约需要20ms(它会随系统速度而变化)
– 它显示旧的domready确实在将infoBubble
附加到窗格之前触发
– 这给出了你需要在domready
调用中放置任何函数的最小setTimeout
的想法
如果你想使用没有修复的原始代码 – 和setTimeout
hack: http : //jsfiddle.net/goredwards/xeL7dxye/
…你可以玩setTimeout
持续时间并查看最小值 – 我在快速机器上下降到大约5ms。 显然你必须在生产代码中采用相反的方式来应对最慢的机器(即你将setTimeout
持续时间放在你可以站立的最高水平 – 没有烦恼~150-250ms – 甚至覆盖你的最慢的系统)。
…或者你可以只复制和更新infobubble.js代码并完成它。