javascript - icon - ¿Cómo puedo superponer los diagramas SVG en Google Maps?
icon for google maps (3)
Aquí hay algunas noticias (espero que sea mejor ponerlas aquí en una respuesta, en lugar de editar mis preguntas o crear una nueva pregunta. Por favor, siéntase libre de moverla si es necesario, o de decirme, para poder rectificar):
Mi problema fue el siguiente:
var oldmap = new GGroundOverlay("test.svg", boundaries);
map.addOverlay(oldmap);
no funcionó en Safari 3, Firefox y Opera (IE no está habilitado para dibujar SVG).
De hecho, este código produce la inserción (en un <div>
) del siguiente elemento
<img src="test.svg" style=".....">
Y Safari 4 puede dibujar un archivo SVG como una imagen, pero esta no es la forma de hacerlo para el otro navegador. Entonces, la idea ahora es crear una superposición personalizada para el SVG, como se explica here .
Esa es la razón por la que hice esta pregunta (lo siento, pero HTML / javascript no son mis puntos fuertes).
Y dado que hay un pequeño error con Webkit para representar un SVG con fondo transparente con el elemento <object>
, necesito usar <object>
o <img>
consecuencia al navegador (no me gusta esto, pero ... para el momento, sigue siendo los experimentos rápidos y sucios)
Así que empecé con este código (todavía trabajo en progreso):
// 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);
}
...
La función de draw
aún no está escrita.
Todavía tengo un problema (progreso lentamente, gracias a lo que leo / aprendo en todas partes, y también gracias a las personas que responden mis preguntas).
Ahora, el problema es el siguiente: con la etiqueta <object>
, el mapa no se puede arrastrar. En todo el elemento <object>
, el puntero del mouse no es "el ícono de la mano" para arrastrar el mapa, sino el puntero normal.
Y no encontré cómo corregir esto. ¿Debo agregar un nuevo evento de mouse (acabo de ver un evento de mouse cuando se agrega un clic o un doble clic, pero no para arrastrar el mapa ...)?
¿O hay otra forma de agregar esta capa para preservar la capacidad de arrastre?
Gracias por sus comentarios y respuestas.
PD: También trato de agregar uno por uno los elementos de mi SVG, pero ... de hecho ... no sé cómo agregarlos en el árbol DOM. En este ejemplo , el SVG se lee y analiza con GXml.parse()
, y todos los elementos con un nombre de etiqueta dado se obtienen ( xml.documentElement.getElementsByTagName
) y se agregan al nodo SVG ( svgNode.appendChild(node)
). Pero en mi caso, necesito agregar directamente el árbol SVG / XML (agregar todos sus elementos), y hay diferentes etiquetas ( <defs>
, <g>
, <circle>
, <path>
, etc.). Puede que sea más simple, pero no sé cómo hacerlo ... :(
Me gustaría agregar una imagen de superposición en un mapa de Google. La imagen es un archivo SVG que he generado (Python con SVGFig).
Estoy usando el siguiente código:
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);
}
Sorprendentemente, funciona con Safari 4, pero no funciona con Firefox (con Safari 3, el fondo no es transparente).
¿Alguien tiene una idea de cómo podría superponer un SVG?
PS1: Leí algunos trabajos como this o el código fuente de swa.ethz.ch/googlemaps, pero parece que tienen que usar el código JavaScript para analizar el SVG y agregar uno por uno todos los elementos (pero no entendí todos la fuente...).
PS2: El SVG se compone de diferentes caminos y círculos rellenos, con transparencia. Si no hay una solución para superponer mi SVG, puedo usar 2 soluciones alternativas:
- rasterizar el SVG
- Convertir los caminos y círculos en GPolygons.
Pero realmente no me gusta la primera solución debido a la mala calidad del mapa de bits y el tiempo para generarlo con antialiasing.
Y para la segunda solución, los arcos, elipsis y círculos deberán descomponerse en pequeñas polilíneas. Muchos de ellos serán necesarios para un buen resultado. Pero tengo alrededor de 3000 arcos y círculos para dibujar, así que ...
Esta pregunta fue discutida brevemente en el Grupo API de Google Maps . Esto es lo que dijeron:
No lo he probado, pero SVG es un subconjunto de XML, por lo que puede leerlos con GDownloadUrl () y analizarlos con GXml.parse (). En algunos servidores web no resueltos, es posible que deba cambiar la extensión del archivo a XML.
Luego, tiene que rastrear a través del XML DOM, escribiendo el SVG que encuentre con las llamadas document.createElementNS () y .setAttribute () ...
También hay algunos ejemplos de SVG de Google Maps aquí y this .
¡Buena suerte!
Pasé la última noche en este problema, y finalmente encontré la solución a mi problema.
No fue tan difícil.
La idea es, como dijo Chris B., cargar el archivo SVG con GDownloadUrl, analizarlo con GXml.parse () y agregar en el árbol DOM todos los elementos SVG que necesito
Para simplificar, supongo que todos los elementos SVG se pusieron en un grupo grande llamado "mainGroup". También he supuesto que algunos elementos pueden estar en el archivo.
Así que aquí está la biblioteca, basada en las here :
// 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";
}
Y, puedes usarlo con el siguiente código:
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);
}
Entonces, puede usarlo exactamente como usa la función GGroundOverlay
, excepto que su archivo SVG debe crearse con la proyección de Mercator (pero si lo aplica en un área pequeña, como una ciudad o más pequeña, no verá la diferencia).
Esto debería funcionar con Safari, Firefox y Opera. Puedes probar mi pequeño ejemplo here
Dime qué piensas al respecto.