我该如何在谷歌地图上叠加SVG图表?

17
我想在Google地图上添加一个覆盖层图片。这个图片是我生成的SVG文件(使用SVGFig的Python)。
我正在使用以下代码:
if (GBrowserIsCompatible()) {
    var map = new GMap2(document.getElementById("map_canvas"));
    map.setCenter(new GLatLng(48.82.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:我阅读了一些类似于此类的作品或swa.ethz.ch/googlemaps的源代码,但似乎它们必须使用JavaScript代码来解析SVG,并逐个添加所有元素(但我没有理解所有源代码...)。

PS2:SVG由不同的填充路径和圆组成,具有透明度。如果无法覆盖我的SVG,则可以使用两种替代解决方案:

  • 将SVG光栅化
  • 将路径和圆转换为GPolygon

但是我不太喜欢第一种解决方案,因为位图质量较差,而且生成时需要抗锯齿。

对于第二种解决方案,弧线、椭圆和圆将必须被分解成小的折线。为了获得良好的结果,需要大量折线。但是我需要绘制约3000个弧线和圆...


这是一个非常好的问题。我的直觉告诉我你的第二种方法不会表现良好,但在确认gmaps处理该数量的折线时,我不敢贸然回答。期待看到这个问题的解决方案。 - RedBlueThing
难道 GGroundOverly 使用了 CSS 背景图片吗?FF 目前还不能处理 SVG 作为背景(但 3.5 版本将可以)。 - Boldewyn
我刚刚尝试了一下使用FF 3.5,但是它也不起作用。 事实上,当我在下载的媒体中查看(工具/页面信息/媒体),我的SVG根本没有加载... - ThibThib
GGroundOverlays 不使用 CSS 背景图像,只用普通的 img 标签。我不知道为什么它们不起作用。 - Chris B
你可以(尝试着)在这里查看结果:http://docmatic.fr/temp/toto.html - ThibThib
3个回答

6
以下是关于IT技术的一些新闻(我希望将它们放在这里作为一个回答,而不是编辑我的问题或创建一个新问题。如果有需要,请随时告诉我,以便我进行更正):
我的问题如下:
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覆盖层,如此处所述。

这就是我为什么需要这个问题的原因(很抱歉,HTML / JavaScript 不是我的强项)。

由于WebKit渲染带有透明背景的SVG时存在小bug,因此我需要根据浏览器使用<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>元素上,鼠标指针不是“手形图标”,无法拖动地图,而只是普通的指针。

我没有找到如何纠正这个问题。我应该添加一个新的鼠标事件(我只看到当单击或双击发生时才会出现鼠标事件,但没有用于拖动地图的鼠标事件...)吗?

还是有另一种方法可以添加此图层以保留可拖动性?

感谢您的评论和答案。

附言:我还尝试逐个添加我的SVG元素,但是...实际上...我不知道如何将它们添加到DOM树中。在这个例子中,SVG使用GXml.parse()进行读取和解析,并获取所有具有给定标记名称的元素(xml.documentElement.getElementsByTagName),并将其添加到SVG节点(svgNode.appendChild(node))。但在我的情况下,我需要直接添加SVG/XML树(添加其所有元素),并且有不同的标记(<defs><g><circle><path>等)。这可能更简单,但我不知道如何做.. :(


6
我昨晚花了些时间解决这个问题,最终找到了解决方法。
这并不是很困难。
像Chris B.所说的那样,想法是使用GDownloadUrl加载SVG文件,用GXml.parse()解析它,并将我需要的每个SVG元素添加到DOM树中。
为了简化起见,我假设所有的SVG元素都被放在一个名为“mainGroup”的大组中。我也假设文件中可能会有一些

2
这个问题在Google Maps API Group上被简要讨论过。以下是他们的回答:

我没有尝试过,但SVG是XML的子集,因此您可以使用GDownloadUrl()读取它们,并使用GXml.parse()分析它们。在某些不稳定的Web服务器上,您可能需要将文件扩展名更改为XML。

然后,您必须浏览XML DOM,使用document.createElementNS()和.setAttribute()调用编写找到的SVG...

这里还有一些Google Maps SVG示例(链接)(链接)

祝好运!


好的,谢谢提供链接。也许我可以加载我的文件,逐个解析并插入所有SVG元素。我会尝试的,即使这个解决方案并不令我满意... 而且我已经能够使用GGroundOverlay(“test.svg”,boundaries)一步加载,但只有Safari 4才行... 我会告诉你进展如何的。 - ThibThib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接