我想在Google地图上添加叠加图片。该图像是我生成的SVG文件(带有SVGFig的Python)。
我使用以下代码:
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map_canvas"));
map.setCenter(new GLatLng(48.8, 2.4), 12);
// ground overlay
var boundaries = new GLatLngBounds(new GLatLng(48.283188032632829, 1.9675270369830129), new GLatLng(49.187215000000002, 2.7771877478303999));
var oldmap = new GGroundOverlay("test.svg", boundaries);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.addOverlay(oldmap);
}
令人惊讶的是,它适用于Safari 4,但它不适用于Firefox(使用Safari 3,背景不透明)。
有没有人知道我如何覆盖SVG?
PS1:我读过一些像this这样的作品或swa.ethz.ch/googlemaps的源代码,但似乎他们必须使用JavaScript代码来解析SVG并逐个添加所有元素(但我不明白所有来源......)。
PS2:SVG由不同的填充路径和圆圈组成,具有透明度。 如果没有解决方案来覆盖我的SVG,我可以使用两种替代解决方案:
但是我不喜欢第一种解决方案,因为位图的质量很差,而且是时候用抗锯齿来生成它。
对于第二种解决方案,弧,椭圆和圆必须分解为小折线。为了取得好成绩,很多都是必要的。但是我有大约3000个圆弧和圆圈来绘制,所以......
答案 0 :(得分:6)
以下是一些新闻(我希望最好将它们放在答案中,而不是编辑我的问题或创建一个新问题。如果需要,请随意移动它,或者告诉我,尽我所能纠正):
我的问题如下:
var oldmap = new GGroundOverlay("test.svg", boundaries);
map.addOverlay(oldmap);
在Safari 3,Firefox和Opera上无效(IE无法绘制SVG)。
实际上,此代码会生成以下元素的插入(<div>
)
<img src="test.svg" style=".....">
Safari 4能够将SVG文件绘制为图像,但这不是其他浏览器的方法。因此,现在的想法是为SVG创建自定义叠加层,如here所述。
这就是我要求this question的原因(对不起,但HTML / javascript不是我的最强点)。
由于Webkit存在一个小错误,用于渲染具有<object>
元素的透明背景的SVG,我需要相应地使用<object>
或<img>
浏览器(我不是像这样,但......目前,它仍然是快速而肮脏的实验)
所以我开始使用这段代码(仍在进行中):
// create the object
function myOverlay(SVGurl, bounds)
{
this.url_ = SVGurl;
this.bounds_ = bounds;
}
// prototype
myOverlay.prototype = new GOverlay();
// initialize
myOverlay.prototype.initialize = function(map)
{
// create the div
var div = document.createElement("div");
div.style.position = "absolute";
div.setAttribute('id',"SVGdiv");
div.setAttribute('width',"900px");
div.setAttribute('height',"900px");
// add it with the same z-index as the map
this.map_ = map;
this.div_ = div;
//create new svg root element and set attributes
var svgRoot;
if (BrowserDetect.browser=='Safari')
{
// Bug in webkit: with <objec> element, Safari put a white background... :-(
svgRoot = document.createElement("img");
svgRoot.setAttribute("id", "SVGelement");
svgRoot.setAttribute("type", "image/svg+xml");
svgRoot.setAttribute("style","width:900px;height:900px");
svgRoot.setAttribute("src", "test.svg");
}
else //if (BrowserDetect.browser=='Firefox')
{
svgRoot = document.createElement("object");
svgRoot.setAttribute("id", "SVGelement");
svgRoot.setAttribute("type", "image/svg+xml");
svgRoot.setAttribute("style","width:900px;height:900px;");
svgRoot.setAttribute("data", "test.svg");
}
div.appendChild(svgRoot);
map.getPane(G_MAP_MAP_PANE).appendChild(div);
//this.redraw(true);
}
...
尚未编写draw
函数。
我仍然有问题(由于我在任何地方阅读/学习的内容,我的进展缓慢,也感谢回答我问题的人)。
现在,问题如下:使用<object>
标记,地图不可拖动。在整个<object>
元素上,鼠标指针不是拖动地图的“手形图标”,而只是普通指针。
我没有找到如何纠正这个问题。我应该添加一个新的鼠标事件(我只是在点击或双击附加时看到鼠标事件,但不是用于拖动地图...)
或者是否有其他方法可以添加此图层以保留拖动能力?
感谢您的意见和回答。
PS:我也尝试逐个添加SVG的元素,但实际上......我不知道如何在DOM树中添加它们。在this example中,使用GXml.parse()
读取和解析SVG,并获取具有给定标记名称的所有元素(xml.documentElement.getElementsByTagName
)并添加到SVG节点(svgNode.appendChild(node)
)。但就我而言,我需要直接添加SVG / XML树(添加其所有元素),并且有不同的标记(<defs>
,<g>
,<circle>
,{{1}等等)。它可能更简单,但我不知道该怎么做.. :(
答案 1 :(得分:6)
我在这个问题上度过了最后一个晚上,我终于找到了解决问题的方法。
这并不困难。
正如Chris B.所说,这个想法是用GDownloadUrl加载SVG文件,用GXml.parse()解析它,并在DOM树中添加我需要的每个SVG元素
为简化起见,我认为所有SVG元素都放在一个名为“mainGroup”的大组中。我还假设某些元素可以在文件中。
所以这是基于Google Maps Custom Overlays:
的库// create the object
function overlaySVG( svgUrl, bounds)
{
this.svgUrl_ = svgUrl;
this.bounds_ = bounds;
}
// prototype
overlaySVG.prototype = new GOverlay();
// initialize
overlaySVG.prototype.initialize = function( map)
{
//create new div node
var svgDiv = document.createElement("div");
svgDiv.setAttribute( "id", "svgDivison");
//svgDiv.setAttribute( "style", "position:absolute");
svgDiv.style.position = "absolute";
svgDiv.style.top = 0;
svgDiv.style.left = 0;
svgDiv.style.height = 0;
svgDiv.style.width = 0;
map.getPane(G_MAP_MAP_PANE).appendChild(svgDiv);
// create new svg element and set attributes
var svgRoot = document.createElementNS( "http://www.w3.org/2000/svg", "svg");
svgRoot.setAttribute( "id", "svgRoot");
svgRoot.setAttribute( "width", "100%");
svgRoot.setAttribute( "height","100%");
svgDiv.appendChild( svgRoot);
// load the SVG file
GDownloadUrl( this.svgUrl_, function( data, responseCode)
{
var xml = GXml.parse(data);
// specify the svg attributes
svgRoot.setAttribute("viewBox", xml.documentElement.getAttribute("viewBox"));
// append the defs
var def = xml.documentElement.getElementsByTagName("defs");
//for( var int=0; i<def.length; i++)
svgRoot.appendChild(def[0].cloneNode(true));
//append the main group
var nodes = xml.documentElement.getElementsByTagName("g");
for (var i = 0; i < nodes.length; i++)
if (nodes[i].id=="mainGroup")
svgRoot.appendChild(nodes[i].cloneNode(true));
});
// keep interesting datas
this.svgDiv_ = svgDiv;
this.map_ = map;
// set position and zoom
this.redraw(true);
}
// remove from the map pane
overlaySVG.prototype.remove = function()
{
this.div_.parentNode.removeChild( this.div_);
}
// Copy our data to a new overlaySVG...
overlaySVG.prototype.copy = function()
{
return new overlaySVG( this.url_, this.bounds_, this.center_);
}
// Redraw based on the current projection and zoom level...
overlaySVG.prototype.redraw = function( force)
{
// We only need to redraw if the coordinate system has changed
if (!force) return;
// get the position in pixels of the bound
posNE = map.fromLatLngToDivPixel(this.bounds_.getNorthEast());
posSW = map.fromLatLngToDivPixel(this.bounds_.getSouthWest());
// compute the absolute position (in pixels) of the div ...
this.svgDiv_.style.left = Math.min(posNE.x,posSW.x) + "px";
this.svgDiv_.style.top = Math.min(posSW.y,posNE.y) + "px";
// ... and its size
this.svgDiv_.style.width = Math.abs(posSW.x - posNE.x) + "px";
this.svgDiv_.style.height = Math.abs(posSW.y - posNE.y) + "px";
}
并且,您可以使用以下代码:
if (GBrowserIsCompatible())
{
//load map
map = new GMap2(document.getElementById("map"), G_NORMAL_MAP);
// create overlay
var boundaries = new GLatLngBounds( new GLatLng(48.2831, 1.9675), new GLatLng(49.1872, 2.7774));
map.addOverlay( new overlaySVG( "test.svg", boundaries ));
//add control and set map center
map.addControl(new GLargeMapControl());
map.setCenter(new GLatLng(48.8, 2.4), 12);
}
因此,您可以完全按照GGroundOverlay
函数使用它,除了您的SVG文件应该使用墨卡托投影创建(但如果您将其应用于小区域,例如一个城市或更小的城市,那么不会看到差异。)
这适用于Safari,Firefox和Opera。您可以尝试我的小示例here
告诉我你怎么看待它。
答案 2 :(得分:2)
Google Maps API Group简要讨论过这个问题。这就是他们所说的:
祝你好运!我没试过,但SVG是一个子集 XML,所以你可以阅读它们 GDownloadUrl()并用它们分析它们 GXml.parse()。在一些不稳定的网络服务器上 您可能需要更改文件 扩展到XML。
然后您必须遍历XML DOM,编写你找到的SVG 与document.createElementNS()和 .setAttribute()调用...