如何使用google earth底图绘制openlayers功能

如何使用google earth底图绘制openlayers功能,openlayers,google-earth-plugin,Openlayers,Google Earth Plugin,尝试(最终)在谷歌地球插件底图上加载标记、向量和WMS。谷歌地球似乎“与他人相处不好” 如果我以“谷歌方式”实例化地图: createInstance('map',initCB,failCB) 我得到了一个谷歌地图,我可以在其中添加谷歌地名,但我不能将该实例传递给OpenLayers 使用以下命令: map = new OpenLayers.Map('ol-map'); map.addControl(new OpenLayers.Control.LayerSwitcher()); var gp

尝试(最终)在谷歌地球插件底图上加载标记、向量和WMS。谷歌地球似乎“与他人相处不好”

如果我以“谷歌方式”实例化地图: createInstance('map',initCB,failCB)

我得到了一个谷歌地图,我可以在其中添加谷歌地名,但我不能将该实例传递给OpenLayers

使用以下命令:

map = new OpenLayers.Map('ol-map');
map.addControl(new OpenLayers.Control.LayerSwitcher());

var gphy = new OpenLayers.Layer.Google(
    "Google Physical",
    {type: G_PHYSICAL_MAP}
);
var gmap = new OpenLayers.Layer.Google(
    "Google Streets", // the default
    {numZoomLevels: 20}
);
var ghyb = new OpenLayers.Layer.Google(
    "Google Hybrid",
    {type: G_HYBRID_MAP, numZoomLevels: 20}
);
var gsat = new OpenLayers.Layer.Google(
    "Google Satellite",
    {type: G_SATELLITE_MAP, numZoomLevels: 22}
);
var gearth = new OpenLayers.Layer.Google(
    "Google Earth",
    {type: G_SATELLITE_3D_MAP}
);

map.addLayers([gphy, gmap, ghyb, gsat, gearth]);

map.setCenter(new OpenLayers.LonLat(-120, 32), 5)
addMarker();
这将创建一个包含5个粘性层的基本OL贴图。当选择gearth时,除了之外,我可以在任何地图图层中看到我添加的标记。一旦我加载google earth地图,它就会“接管”整个div。所有的OL控件(如LayerSwitcher)都不见了,我还没有弄清楚如何从OL访问google earth实例

我假设标记仍然存在,但在底图后面。在底图上设置不透明度没有效果

问题:

  • 这是一个记录的限制吗?我找不到任何迹象表明这是不可能的
  • 是否有一个变通方法可以将OpenLayers地图/图层实例传递给google earth的getEarthInstance调用?反之亦然?这似乎是两全其美,让我在需要时可以访问GE API,但我可以在OL中使用所有WFS处理来完成大多数任务

  • 欢迎半生不熟的想法。

    一般来说,OpenLayers绝对不支持Google Earth 3D模式。(我是OpenLayers的开发人员,我只是通过这个问题才意识到这是可能的。)由于3D显示代码的工作方式(通过第三方插件),我无法想象默认的OpenLayers工具——用于绘图,等等——这些都会起作用:OpenLayers需要集成的部分在3D API中根本不存在

    OpenLayers——主要是一个2D绘图客户机——不太可能实现将其所有各种调用转换为Google Maps/Earth API调用的功能

    OpenLayers确实支持协议和格式:理论上,这将允许您在与第三方API(如Google Earth API)交互时在一定程度上使用OpenLayers WFS处理工具链。然而,我认为在这种情况下,您没有从中获得足够的收益来解决您的问题


    简而言之:这是行不通的,没有简单的解决方案。如果你想要3D,你可能需要自己构建更多的地图。

    我认为这个问题与Google Maps v2有关,因为我不认为v3中有一种类型:G_SATELLITE_3D_MAP

    Google地图v3的Google Earth插件通过

    作者采用的方法是监听GoogleMapsV3添加/删除事件,并添加相应的GoogleEarthAPI对象。 我相信类似的方法也可以用于OpenLayers。我是OpenLayers的新手,刚刚开始研究这个问题,但我会在这里发布更新

    我现在唯一能补充的是Google Earth插件的初始化,这在v3中是不同的:

    function GoogleEarth( olmap ) {
    this.olmap_ = olmap;
    this.layer_ = new OpenLayers.Layer.Google(
        "Google Earth",
        {type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22, visibility: false}
    );
    this.olmap_.addLayers([ this.layer_ ]);
    this.map_ = this.layer_.mapObject;
    this.mapDiv_ = this.map_.getDiv();
    
    ...
    var earthMapType = /** @type {google.maps.MapType} */({
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 19,
    name: this.earthTitle_,
    // The alt helps the findMapTypeControlDiv work.
    alt: this.earthTitle_,
    getTile:
      /**
       * @param {google.maps.Point} tileCoord the tile coordinate.
       * @param {number} zoom the zoom level.
       * @param {Node} ownerDocument n/a.
       * @return {Node} the overlay.
       */
      function(tileCoord, zoom, ownerDocument) {
        var div = ownerDocument.createElement('DIV');
        return div;
      }
    });
    
    this.map_.mapTypes.set(GoogleEarth.MAP_TYPE_ID, earthMapType);
    
    this.layer_.type = GoogleEarth.MAP_TYPE_ID;
    
    var that = this;
    google.maps.event.addListener(map, 'maptypeid_changed', function() {
      that.mapTypeChanged_();
      }); 
    }
    
    令人费解的是,我们需要为Google Earth定义一个新的地图类型,并将该类型添加到Google地图对象中。但是如果我们不创建一个类型为Google.maps.MapTypeId.SATELLITE的图层,Google地图对象就不存在了。 不是很干净,但至少它让我达到了与谷歌地图v3这篇文章的作者相同的状态。 最后,有一种方法可以通过修改函数findMapTypeControlDiv\ uz()使OpenLayers控件可见:

    [更新]

    我已经修改了函数findMapTypeControlDiv_z(),现在我寻找OpenLayers LayerSwitcher:

    GoogleEarth.prototype.findLayerSwitcherDiv_ = function() {
    //  var title = 'title="' + this.earthTitle_ + '"';
      var id = 'LayerSwitcher';
    
      var siblings = this.controlDiv_.parentNode.childNodes;
      for (var i = 0, sibling; sibling = siblings[i]; i++) {
        if (sibling.id.indexOf(id) != -1) {
          return sibling;
        }
      }
    };
    
    LayerSwitcher的z索引设置正确,div显示在顶部,直到调用google.earth.createInstance(),然后它消失。我会花更多的时间在这上面,它看起来不难解决

    [更新2]

    我已经解决了图层切换面板的问题。诀窍是将GoogleEarth插件div附加到适当的div(GMaps的原始代码将其附加到地图控件数组)。另一个问题是设置zIndex以确保LayerSwitcher位于顶部。 当GE插件运行时,我仍然有一个问题,我试图最小化LayerSwitcher,调用OpenLayers.Event.stop()使GE插件崩溃(Chrome)或LayerSwitcher消失(IE8)。 我想从Google获得原始代码,并制作一个在OpenLayers上工作的GE插件层。 有人能建议怎么做吗?谢谢

    无论如何,这里是我最新的变化:

    GoogleEarth.prototype.findLayerSwitcherDiv_ = function() {
      var id = 'LayerSwitcher';
    
      var siblings = this.mapDiv_.parentNode.childNodes;
      for (var i = 0, sibling; sibling = siblings[i]; i++) {
        if (sibling.id.indexOf(id) != -1) {
          return sibling;
        }
      }
    };
    
    GoogleEarth.prototype.addEarthControl_ = function() {
    ...
    inner.appendChild(earthDiv);
    var parentNode = this.findLayerSwitcherDiv_().parentNode;
    parentNode.appendChild( control );
    
    ...
    GoogleEarth.prototype.setZIndexes_ = function(mapTypeControlDiv) {
      var oldIndex = mapTypeControlDiv.style.zIndex;
      var siblings = this.controlDiv_.parentNode.childNodes;
      for (var i = 0, sibling; sibling = siblings[i]; i++) {
        sibling['__gme_ozi'] = sibling.style.zIndex;
        // Sets the zIndex of all controls to be behind Earth.
        sibling.style.zIndex = 0;
      }
    
      mapTypeControlDiv['__gme_ozi'] = oldIndex;
      this.controlDiv_.style.zIndex = 2000;
      mapTypeControlDiv.style.zIndex = 2001;
    };
    
    [更新3]
    我在这里建立了一个github项目:

    我不再熟悉OpenLayers中的不同层类型,但关键是Google Earth API和Google Maps API实际上是不同的。乍一看,我不明白为什么需要将它添加到Google Maps类型中(假设我认为是这样)

    正如Chris已经暗示的那样,只需将您的Earth API集成视为一个与任何现有Google层完全不同的全新事物;这些API中的语法和概念并不十分相似,至少据我所知,您无法在OpenLayers中获得现有Google Maps集成子类化的任何优势


    也就是说,我希望mapsv3/Earth集成的代码将对您有所帮助,并且类似于您将其与OpenLayers集成所需的操作。同时,我还看到一些其他人也对此进行了尝试,比如这个geoExt示例,您可能会发现它也很有用:

    谢谢您的反馈。我还和谷歌的几位工程师联系过,所以如果我学到了什么,我会随时通知你。你说得对。我与谷歌工程师的谈话对此没有帮助,但确实指出,如果您想将谷歌地球插件实现到定制的web应用程序中,GE插件API(Earth_loader_Plugin.js)的本地副本必须是lo
    GoogleEarth.prototype.findLayerSwitcherDiv_ = function() {
      var id = 'LayerSwitcher';
    
      var siblings = this.mapDiv_.parentNode.childNodes;
      for (var i = 0, sibling; sibling = siblings[i]; i++) {
        if (sibling.id.indexOf(id) != -1) {
          return sibling;
        }
      }
    };
    
    GoogleEarth.prototype.addEarthControl_ = function() {
    ...
    inner.appendChild(earthDiv);
    var parentNode = this.findLayerSwitcherDiv_().parentNode;
    parentNode.appendChild( control );
    
    ...
    GoogleEarth.prototype.setZIndexes_ = function(mapTypeControlDiv) {
      var oldIndex = mapTypeControlDiv.style.zIndex;
      var siblings = this.controlDiv_.parentNode.childNodes;
      for (var i = 0, sibling; sibling = siblings[i]; i++) {
        sibling['__gme_ozi'] = sibling.style.zIndex;
        // Sets the zIndex of all controls to be behind Earth.
        sibling.style.zIndex = 0;
      }
    
      mapTypeControlDiv['__gme_ozi'] = oldIndex;
      this.controlDiv_.style.zIndex = 2000;
      mapTypeControlDiv.style.zIndex = 2001;
    };