【问题标题】:Region-based network links in Google Earth APIGoogle Earth API 中基于区域的网络链接
【发布时间】:2012-08-02 01:22:07
【问题描述】:

我有许多大型 KML 数据集,它们使用基于区域的网络链接层次结构提供服务;如KML reference中所述:

将 Regions 与 NetworkLinks 结合使用,您可以创建一个指针层次结构,每个指针都指向一个特定的子区域。 <viewRefreshMode>,如下面的 KML 文件所示,有一个 onRegion 选项,指定仅当 Region 处于活动状态时才加载 Region 数据。如果您为嵌套区域提供多层次的详细信息,则只有在用户的视点触发下一次加载时才会加载更大量的数据。

在 Google 地球中加载时效果很好。

我现在希望使用Google Earth plug-in 将这些加载到应用程序中。 我需要通过 Google Earth API 访问加载的内容; (即附加点击事件、更改样式)以将内容集成到应用程序中。

问题是,我没有找到对网络链接的“加载”事件的任何引用。在我看来,这样做的方式是:

  • 通过 API 加载顶级网络链接,附加一个回调函数,该函数将在加载网络链接时调用。
  • 在回调函数中,解析网络链接返回的KML。对于区域层次结构中的中间级别,此 KML 将仅包含到下一个区域级别的网络链接。通过 API 将它们加载到插件中,再次指定相同的回调函数,在加载它们时(即它们的区域变得可见时)将调用该函数。
  • 最终,返回的 KML 将包含实际的“内容”。在这个阶段,我们在执行任何所需的修改(例如附加事件侦听器、设置样式等)之后将实际内容(即地标)加载到插件中。

我认为 javascript 应该如下所示。
请注意:这只是一个粗略的草图,可能有助于理解我的问题。不 询问为什么这段代码不起作用。

//create network link
var networkLink = ge.createNetworkLink("");
networkLink.setName("Regionated hierarchy root");

// create a Link object
//the network-links contained in the kml that will be returned in this file
//are region-based; they will only be loaded when the user zooms into the relevant
//region. 
var link = ge.createLink("");
link.setHref("http://foo.com/regionatedRoot.kml");

// attach the Link to the NetworkLink
networkLink.setLink(link);

//specify the callback function to be invoked when the network link is loaded
//this is is the part that doesn't actually exist; pure fiction...
networkLink.onLoad = networkLinkLoaded;

// add the NetworkLink feature to Earth
ge.getFeatures().appendChild(networkLink);

// function which will be invoked when a network-link is loaded
// i.e. when its region becomes active
function networkLinkLoaded(kml) {

   //parse the kml returned for child network links,
   //this will create the network link KmlObject, with a 
   //region specified on it.
   for (childNetworkLink in parseNetworkLinks(kml)) {
      //and append them, again hooking up the call-back
      childNetworkLink.onLoad = networkLinkLoaded;
      ge.getFeatures().appendChild(childNetworkLink);
   }

   //if the user has zoomed in far enough, then the kml returned will
   //contain the actual content (i.e. placemarks).
   //parse the kml returned for content (in this case placemarks)
   for (placemark in parsePlacemarks(kml)) {
      //here we would attach event-listeners to the placemark
      ge.getFeatures().appendChild(placemark);
   }
}

这可能吗?
我的想法是不是走错了方向?我相信我已遵循管理大型 KML 数据集的推荐做法,但我不确定如何通过 API 使用这些做法。

附录

作为我要解决的问题类型的示例: 想象一下,您正在使用 Google 地球插件构建一个 Web 应用程序,并且您想为世界上的每组交通信号灯显示一个地标。地标应仅以适当的详细程度显示(例如,当相机位于 5 公里高度时)。当用户点击一个地标时,我们希望网络应用加载该组交通信号灯的统计信息,并将它们显示在侧边栏中。

你会如何设计这个?

【问题讨论】:

    标签: kml google-earth-plugin


    【解决方案1】:

    您无需直接访问对象数据即可提供所需的功能。您将使用基于区域的网络链接的层次结构完全像您所做的那样处理数据加载。 然后,如果您的使用场景与您在附录中设置的场景一样,那么您只需使用点击事件中的目标数据,根据需要根据地标加载统计数据。

    例如,您可以简单地在窗口对象上设置一个通用的 mousedown 事件处理程序,然后测试目标是否是地标。您可以在加载任何数据之前添加此通用侦听器,并且在您单击动态加载的地标时仍会触发它。根本不需要将单个事件侦听器附加到地标。

    例如

    window.google.earth.addEventListener(ge.getWindow(), 'mousedown', onWindowMouseDown);
    
    var onWindowMouseDown = function(event) {
      if (event.getTarget().getType() == 'KmlPlacemark') {
        // get the placemark that was clicked
        var placemark = event.getTarget();
    
        // do something with it, or one of its relative objects...
        var document = placemark.getOwnerDocument();
        var parent = placemark.getParentNode();
    
        // etc...
      }
    }
    

    【讨论】:

    • 你是对的。通过设置“全局”级别的事件处理程序,我可以过滤目标 ID 以确定如何处理事件。谢谢!
    • 不用担心,很高兴能帮上忙。
    【解决方案2】:

    不确定这是否正是您想要的,但有一个 kmltree api 可以:

    1. 根据给定的 kml 为您构建 kml 树
    2. 允许您拥有一个“kmlloaded”事件处理程序

    http://code.google.com/p/kmltree/

    function initCB(instance){
        ge = instance;
        ge.getWindow().setVisibility(true);
    
        var gex = gex = new GEarthExtensions(ge);
    
        var tree = kmltree({
            url: 'http://foo.com/regionatedRoot.kml',
            gex: gex, 
            mapElement: $('#map3d'), 
            element: $('#tree'),
        });
    
        $(tree).bind('kmlLoaded', function(event, kmlObject){ //do something here });
    
        tree.load();
    }
    

    它确实需要你引入另一个 js api,但它工作得很好,并为你提供了一些很好的内置功能。

    到目前为止,我还没有从插件中找到任何可以在加载 kml 时触发事件的东西......

    您也许可以尝试使用 fetchKml(),特别是如果您正在为那里的链接硬编码该 url?

    google.earth.fetchKml(ge, 'http://foo.com/regionatedRoot.kml', function(kmlObject){
         //do logic here
    });
    

    【讨论】:

    • 感谢马特的回答。我看过 KmlTree 项目;但我不相信它解决了这个问题。这似乎是关于将 KML 解析为树形菜单。我不相信它处理基于区域的网络链接?我在我的问题中添加了一个附录,其中包含我要解决的问题类型的示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 2018-01-11
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2017-12-02
    相关资源
    最近更新 更多