尝试使用OpenLayers来(最终)加载标记,向量& WMS位于谷歌地球插件基础地图之上。 Google地球似乎并没有“与他人合作”。
如果我以'google方式'实例化地图: google.earth.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个googly图层的基本OL地图。当选择了gearth时,我可以看到任何地图图层除了时添加的标记。只要我加载谷歌地球地图,它就会“接管”整个div。所有的OL控件(如LayerSwitcher)都已消失,我无法弄清楚如何从OL访问Google地球实例。
我假设标记仍然存在,但在底图后面。在底图上设置不透明度无效。
问题:
欢迎半生不熟的想法。
答案 0 :(得分:1)
一般来说,OpenLayers绝对不支持Google Earth 3D模式。 (我是OpenLayers的开发人员,我只是通过这个问题才意识到这是可能的。)由于3D显示代码的工作方式(通过第三方插件),我可以无论如何,默认的OpenLayers工具 - 用于绘图等 - 都可以起作用:OpenLayers需要与之集成的部分根本不存在于3D API中。
OpenLayers--主要是2D绘图客户端 - 不太可能实现将所有各种调用转换为Google Maps / Earth API调用的内容。
OpenLayers确实支持协议和格式:理论上,这将允许您在与第三方API(如Google Earth API)交互时在某种程度上使用OpenLayers WFS处理工具链。但是,我希望在这种情况下,你没有足够的收益来解决你的问题。
简而言之:这不起作用,并没有简单的解决方案。如果你想要3D,你可能需要自己构建更多。
答案 1 :(得分:1)
我认为这个问题与Google Maps v2有关,因为我认为v3中没有类型:G_SATELLITE_3D_MAP。
谷歌地图插件for Google Maps v3通过script from the google-maps-utility-library-v3 (googleearth.js)
支持(测试版)作者@jlivni采取的方法是收听Google Maps v3添加/删除事件并添加相应的Google Earth Api对象。 我相信OpenLayers可以采用类似的方法。我是OpenLayers的新手,刚开始研究这个,但我会在这里发布更新。
我现在唯一可以添加的是关于Google地球插件的初始化,这在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地球定义新的地图类型,并将此类型添加到Google地图对象中。但是,如果我们不创建具有类型的图层,那么Google Map对象就不存在了,我最初将其设置为google.maps.MapTypeId.SATELLITE。 不是很干净,但至少它让我与谷歌地图v3这篇文章的作者处于同一状态。 最后,可能有一种方法可以通过修改函数findMapTypeControlDiv _()来使OpenLayers控件可见:
var mapTypeControlDiv = this.findMapTypeControlDiv_();
if (mapTypeControlDiv) {
this.setZIndexes_(mapTypeControlDiv);
this.addShim_(mapTypeControlDiv);
}
[更新]
我修改了函数findMapTypeControlDiv_(),现在我寻找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]
我已经解决了LayerSwitcher面板问题。诀窍是将Google Earth Plugin div附加到正确的div(GMaps的原始代码将其附加到Map Controls数组)。另一个问题是设置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项目:https://github.com/ZiglioNZ/GoogleEarth-for-OpenLayers
[更新4] 有关演示,请转到http://ziglionz.github.com/GoogleEarth-for-OpenLayers/ol.html
答案 2 :(得分:0)
我不再熟悉OpenLayers中的不同图层类型了,但关键是Google Earth API和Google Maps API真的是不同的野兽。乍一看,我不明白为什么你需要将它添加到谷歌地图类型(假设这是我认为的)。
正如克里斯暗示的那样,只需将您的Earth API集成视为与任何现有Google图层完全相同的全新内容;这些API中的语法和概念与你在OpenLayers中对现有的Google Maps集成进行子类化的任何优势都不是很相似,至少就我所知。
那就是说我希望Maps V3 / Earth集成的代码有用,类似于将它与OpenLayers集成所需的操作。与此同时,我看到其他一些人也给了这个镜头,比如这个geoExt示例,您可能会发现它很有用:http://dev.geoext.org/sandbox/cmoullet/ux/GoogleEarthPanel/examples/GoogleEarthPanelExample.html