【问题标题】:google maps infobubble dynamic content not loading on first marker click谷歌地图信息气泡动态内容未在第一次标记点击时加载
【发布时间】:2016-01-16 00:41:39
【问题描述】:

我正在尝试在谷歌地图中添加动态内容infobubble:
- 一个第一个标记单击一个空的信息气泡出现
- 在 SECOND 点击标记时会加载正确的内容

根据this answer,我正在使用先前定义的 infobubble 对象上的domready 事件来启动加载动态内容的函数。
...尽管该答案中的 JS 小提琴具有误导性,因为“动态”内容实际上是在 domready 之前使用 content 调用的 content 选项加载的

我在控制台中收到了所有正确的信号,表明 domready 功能正在完成,并且在第一次标记点击时正确找到了内容。

试过了:

  • 查看the infobubble.js code并将console.logs放在第1231行的任一侧:
    google.maps.event.trigger(this, 'domready');
    结果表明 domready 确实在动态函数开始之前被触发。

  • 使用 infobubble disableAnimation: true 选项禁用动画 - 认为在调用 domready 后可能会减慢 infobubble 加载速度 - 但它不起作用

  • 添加了最多 3 秒的 setTimeout(),但这似乎无济于事……无论如何,这将是一个糟糕的 hack。

如何在第一次点击标记时加载动态内容?

JS Fiddle here

注意事项:
- 对于 js fiddle 示例,我使用 $.get() 调用 - 因为在我的应用程序中,我使用 mustache 将模板加载到 infobubble
- 正在加载的示例内容与$.get() 调用无关(是的,我可以在没有$.get() 调用的情况下实现相同的效果),但我只是想对我自己的应用程序使用类似的代码布局+时间

【问题讨论】:

    标签: jquery google-maps infowindow domready infobubble


    【解决方案1】:

    问题似乎是信息泡泡的open_-方法(将在open-方法中调用):

    InfoBubble.prototype.open_ = function(opt_map, opt_anchor) {
      this.updateContent_();
    
      if (opt_map) {
        this.setMap(opt_map);
      }
      //............................
    }
    

    它首先调用方法updateContent_(将触发domready事件)然后设置map。但是在设置map-property 之前,叠加层不会添加到地图中,内容是尚未附加到文档的DocumentFragment/Node,因此jQuery 可能找不到它。

    可能的解决方案:

    使用 infobubble 的 content_-property 作为 jQuery-selector 的上下文,那么内容是否已经附加到文档应该无关紧要

    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('<img id="theImg" src="https://goo.gl/phmzis" />');
          }     
            })
    
      });
      infoBubble.open(map, marker);
    });
    

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

    【讨论】:

    • 感谢您提供信息和解决方案 - 在 setMap() 上很好地发现了 domready 电话之后的问题 - 解决方案有效......虽然它看起来有点骇人听闻......你认为有什么方法可以在 setMap() 之后将 domready 调用放在函数上?
    • 你可以下载js文件,修改它并使用修改后的副本。
    • 是的,谢谢-已经这样做了-对您认为domready调用它的最佳位置将在open方法内更感兴趣。我在redraw_() 调用之后直接在open 方法中思考...?
    • 我不确定是否有“最好的地方”。首先,我试图观察 infoBubble 的 map_changed-event ,但这也不能正常工作。也许最好的解决方案是实现一种自定义方法,在现有内容中插入内容。
    • 实际上,如果您需要在 infobubble 内容上使用 jQuery(例如,如果您要添加轮播或活动按钮等),则此解决方案不起作用,因为 content_ 实际上不在domready 触发时的 dom。 (这也意味着它没有大小 - 因为信息窗口是根据内容调整大小的,大概在 setMap() 中)正如您正确指出的那样,这是因为 domreadysetMap() 之前触发 - 请参阅下面的解决方案。
    【解决方案2】:

    感谢in the answer by Dr.Molle 的观察,我找到了解决方案——这确实与infobubble.js 代码中domready 事件触发器的放置有关。

    不幸的是,它当前位于 updateContent_() 函数中,该函数在调用 setMap() 之前由 open_() 调用 - 这意味着在将 infoBubble 添加到 DOM 之前会触发 domready

    不可能在open_() 函数中的setMap() 调用之后简单地添加domready 触发器,因为setMap() 是异步的......并且setMap() 函数没有特定的回调。

    然而,根据documentation for OverlayView(这是该插件使用的),setMap() 函数在使用有效地图对象调用setMap() 之后调用onAdd() 函数:

    onAdd():实现这个方法来初始化覆盖DOM元素。此方法在使用有效地图调用 setMap() 后调用一次。此时,窗格和投影将已初始化。

    还有更简单的:

    在 onAdd() 方法中,您应该创建 DOM 对象并将它们附加为窗格的子对象。

    因此我们应该在onAdd() 函数中触发domready 事件,infoBubble 被附加到地图窗格之后:

    /**
     * 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 供 google 更新 infobubble.js code 并解决此问题。

    JS Fiddle 更新代码(请参阅 javascript 窗口中的第 910 行以获取新的 domready 位置)
    http://jsfiddle.net/goredwards/7r96we66/

    注意事项:
    - 我在旧的domready 调用和正确的(更新的)domready 调用的 jsfiddle 中添加了时间戳 - 你会在 console.log 中看到它们 - 在我的系统上大约需要 20 毫秒(它会有所不同与系统速度)
    - 它表明旧的 domready 确实在 infoBubble 被附加到窗格之前触发
    - 这给出了您需要在 domready 调用中放置任何函数的最低 setTimeout 的概念

    如果您想使用没有修复的原始代码 - 以及 setTimeout hack:http://jsfiddle.net/goredwards/xeL7dxye/
    ...您可以使用setTimeout 持续时间,看看最小值是多少——我在一台快速机器上下降到大约 5 毫秒。显然,您必须在生产代码中采用 other 方式,以应对最慢的机器(即您将setTimeout 持续时间设置为您可以忍受的最高水平 - 没有烦恼~150-250ms - 甚至涵盖最慢的系统)。
    ...或者您可以复制并更新 infobubble.js 代码并完成它。

    【讨论】:

    猜你喜欢
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 2011-09-01
    相关资源
    最近更新 更多