谷歌地图信息动态内容未在第一次标记点击时加载

我正在尝试在google地图信息块中添加动态内容:
– 出现一个第一个标记点​​击空信息
– 在第二次点击标记时加载正确的内容

根据这个答案,我在先前定义的infobubble对象上使用domready事件来启动加载动态内容的函数。
…虽然答案中的JS小提琴是误导性的,因为“动态”内容实际上是在使用new InfoBubble()调用的content选项之前加载的

我在控制台中获得所有正确的信号,即domreadyfunction正在完成,并且在第一个标记点​​击时正确找到了内容。

尝试:

  • 查看了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); }); 

http://jsfiddle.net/doktormolle/aLtz76ym/

感谢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代码并完成它。

Interesting Posts