Javascript 如何在Google地图上覆盖SVG图表?
我想在谷歌地图上添加一个覆盖图。该图像是我生成的一个SVG文件(带有SVGFig的Python) 我正在使用以下代码:Javascript 如何在Google地图上覆盖SVG图表?,javascript,google-maps,svg,Javascript,Google Maps,Svg,我想在谷歌地图上添加一个覆盖图。该图像是我生成的一个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 G
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);
}
// 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";
}
令人惊讶的是,它与Safari 4兼容,但与Firefox不兼容(对于Safari 3,背景是不透明的)
有人知道如何覆盖SVG吗
PS1:我读过一些作品,比如或swa.ethz.ch/googlemaps的源代码,但似乎他们必须使用JavaScript代码来解析SVG并逐个添加所有元素(但我不了解所有源代码…)
PS2:SVG由不同的填充路径和圆组成,具有透明度。
如果没有覆盖SVG的解决方案,我可以使用两种替代解决方案:
- 光栅化SVG
- 在GPolygons中转换路径和圆
对于第二种解决方案,圆弧、椭圆和圆必须分解为小的多段线。要想取得好的成绩,他们中的很多人都是必不可少的。但是我有大约3000个弧和圆要画,所以…这个问题在网上被简要讨论过。他们是这么说的: 我没有尝试过,但是SVG是一个子集 XML,因此您可以使用 GDownloadUrl()并使用 GXml.parse()。在一些不可靠的Web服务器上 您可能必须更改该文件 对XML的扩展 然后必须在XML中爬行 DOM,编写您找到的SVG 使用document.createElements()和 .setAttribute()调用 还有一些Google Maps SVG示例和示例 祝你好运 以下是一些新闻(我希望最好将它们放在这里作为答案,而不是编辑我的问题或创建一个新问题。如果需要,请随意移动它,或者告诉我,以便我可以更正): 我的问题是:
var oldmap = new GGroundOverlay("test.svg", boundaries);
map.addOverlay(oldmap);
不适用于Safari 3、Firefox和Opera(即无法绘制SVG)
事实上,此代码生成以下元素的插入(在
中)
<img src="test.svg" style=".....">
Safari 4能够将SVG文件绘制为图像,但这不是其他浏览器的方式。因此,现在的想法是为SVG创建一个自定义覆盖,如前所述
这就是我要求的原因(很抱歉,HTML/javascript不是我的强项)
由于Webkit中有一个小错误,用于使用
元素呈现具有透明背景的SVG,因此我需要使用
或
尚未编写draw
函数
我仍然有一个问题(我进步缓慢,这要感谢我在各地读到的东西,也要感谢那些回答我问题的人)
现在,问题是:使用
标记时,地图无法拖动。在
元素中,鼠标指针不是用来拖动地图的“手形图标”,而是普通的指针
我没有发现如何纠正这一点。我应该添加一个新的鼠标事件(我只是在单击或双击附加时看到鼠标事件,但不是为了拖动地图…)
或者是否有其他方法添加此层以保持拖动能力
谢谢你的评论和回答
PS:我也尝试一个接一个地添加SVG的元素,但是。。。事实上我不知道如何将它们添加到DOM树中。在中,使用GXml.parse()
读取和解析SVG,并获取具有给定标记名的所有元素(xml.documentElement.getElementsByTagName
)并添加到SVG节点(svgNode.appendChild(节点)
)。但是在我的例子中,我需要直接添加SVG/XML树(添加其所有元素),并且有不同的标记(
,
,
,
,等等)。这可能更简单,但我不知道怎么做(我把最后一个晚上花在这个问题上,终于找到了解决问题的办法
这并不难
正如Chris B.所说,这个想法是用GDownloadUrl加载SVG文件,用GXml.parse()解析它,并在DOM树中添加我需要的每个SVG元素
为了简化,我假设所有SVG元素都放在一个名为“mainGroup”的大组中。我还假设一些元素可以在文件中
这是图书馆,基于:
因此,您可以像使用GGroundOverlay
功能一样使用它,只是SVG文件应该使用墨卡托投影创建(但是如果您将其应用于小区域,例如一个城市或更小的区域,您将看不到区别)
这应该适用于Safari、Firefox和Opera
告诉我你是怎么想的。这是一个多么好的问题。我的直觉是,你的第二种方法不会起作用,但在没有确认gmaps如何处理这么多的多段线的情况下,我会犹豫回答。我期待着看一看这是怎么回事。可能是GGP过度使用CSS背景图像吗?FF无法处理(然而,3.5会)SVG作为背景。我只是尝试使用FF 3.5,但它也不起作用。事实上,当我查看下载的媒体(工具/页面信息/媒体)时,我的SVG根本没有加载…GGroundOverlays不使用CSS背景图像。只是普通的img。我不知道它们为什么不起作用。你可以(尝试)看到结果好的,谢谢链接。是的,也许我可以加载我的文件,解析它并逐个插入我所有的SVG元素。我会尝试,即使这个解决方案不能说服我…我已经能够使用GGroundOverlay(“test.SVG”,bounders)一步加载,但只有使用Safari 4…我会告诉你这是怎么回事
// 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);
}