2010-05-02 24 views
65

Estoy jugando con SVG y esperaba poder crear archivos SVG en Illustrator y acceder a los elementos con Javascript.Cómo acceder a los elementos SVG con Javascript

Aquí está el archivo SVG Illustrator echa (También parece añadir una carga de basura al principio del archivo que he eliminado)

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" 
    width="276.843px" height="233.242px" viewBox="0 0 276.843 233.242" enable-background="new 0 0 276.843 233.242" 
    xml:space="preserve"> 
<path id="delta" fill="#231F20" d="M34.074,86.094L0,185.354l44.444,38.519l80.741-0.74l29.63-25.186l-26.667-37.037 
    c0,0-34.815-5.926-37.778-6.667s-13.333-28.889-13.333-28.889l7.407-18.519l31.111-2.963l5.926-21.481l-12.593-38.519l-43.704-5.185 
    L34.074,86.094z"/> 
<path id="cargo" fill="#DFB800" d="M68.148,32.761l43.704,4.445l14.815,42.963l-7.407,26.667l-33.333,2.963l-4.444,14.074 
    l54.074-1.481l22.222,36.296l25.926-3.704l25.926-54.074c0,0-19.259-47.408-21.481-47.408s-31.852-0.741-31.852-0.741 
    l-19.259-39.259L92.593,8.316L68.148,32.761z"/> 
<polygon id="beta" fill="#35FF1F" points="86.722,128.316 134.593,124.613 158.296,163.872 190.889,155.724 214.593,100.909 
    194.593,52.02 227.186,49.057 246.444,92.02 238.297,140.909 216.074,172.761 197.556,188.316 179.778,169.798 164.963,174.983 
    163.481,197.946 156.815,197.946 134.593,159.428 94.593,151.279 "/> 
<path class="monkey" id="alpha" fill="#FD00FF" d="M96.315,4.354l42.963,5.185l18.519,42.222l71.852-8.148l20.74,46.667l-5.926,52.593 
    l-24.444,34.074l-25.185,15.555l-14.074-19.259l-8.889,2.964l-1.481,22.222l-14.074,2.963l-25.186,22.963l-74.074,4.444 
    l101.481,4.444c0,0,96.297-17.777,109.63-71.852S282.24,53.983,250.389,20.65S96.315,4.354,96.315,4.354z"/> 
</svg> 

Como podrán ver, cada elemento tiene una ID, y esperaba poder acceder a elementos individuales con Javascript para poder cambiar el atributo Rellenar y responder a eventos como hacer clic.

El HTML es BOG básica

<!DOCTYPE html> 
<html> 
    <head> 
     <title>SVG Illustrator Test</title> 
    </head> 
    <body> 

     <object data="alpha.svg" type="image/svg+xml" id="alphasvg" width="100%" height="100%"></object> 

    </body> 
</html> 

supongo que esto es realmente dos preguntas.

  1. Es posible hacerlo de esta manera, en lugar de usar algo como Raphael o jQuery SVG.

  2. Si es posible, ¿cuál es la técnica?


ACTUALIZACIÓN

Por el momento, he recurrido al uso de Illustrator para crear el archivo SVG, y estoy usando Raphaël JS para crear rutas y simplemente copiar los datos de los puntos de el archivo SVG y pegándolo en la función path(). Crear rutas complejas, como las que podrían necesitarse para un mapa, al codificar manualmente los datos de puntos, es (a mi entender) prohibitivamente complejo.

Respuesta

82

¿Es posible hacerlo de esta manera, en lugar de usar algo como Raphael o jQuery SVG?

Definitivamente.

Si es posible, ¿cuál es la técnica?

Este fragmento de código anotado funciona:

<!DOCTYPE html> 
<html> 
    <head> 
     <title>SVG Illustrator Test</title> 
    </head> 
    <body> 

     <object data="alpha.svg" type="image/svg+xml" 
     id="alphasvg" width="100%" height="100%"></object> 

     <script> 
      var a = document.getElementById("alphasvg"); 

      // It's important to add an load event listener to the object, 
      // as it will load the svg doc asynchronously 
      a.addEventListener("load",function(){ 

       // get the inner DOM of alpha.svg 
       var svgDoc = a.contentDocument; 
       // get the inner element by id 
       var delta = svgDoc.getElementById("delta"); 
       // add behaviour 
       delta.addEventListener("mousedown",function(){ 
         alert('hello world!') 
       }, false); 
      }, false); 
     </script> 
    </body> 
</html> 

Tenga en cuenta que una limitación de esta técnica es que está restringido por la política del mismo origen, por lo alpha.svg deben estar alojados en el mismo dominio que el .html archivo, de lo contrario el DOM interno del objeto será inaccesible.

+3

nota en la nota de @ jbeard4: en algunos navegadores, esta política del mismo origen implica la necesidad de usar un servidor (incluso si el código solo utiliza html y js [servidor]) la política de acceso impedirá el acceso a el svg. – Michael

16

En caso de usar jQuery que es necesario esperar a $(window).load, debido a que el documento SVG incrustado no podría ser todavía cargado en $(document).ready

$(window).load(function() { 

    //alert("Document loaded, including graphics and embedded documents (like SVG)"); 
    var a = document.getElementById("alphasvg"); 

    //get the inner DOM of alpha.svg 
    var svgDoc = a.contentDocument; 

    //get the inner element by id 
    var delta = svgDoc.getElementById("delta"); 
    delta.addEventListener("mousedown", function(){ alert('hello world!')}, false); 
}); 
+3

Al usar este código, esta otra respuesta podría ser un complemento útil: http://stackoverflow.com/a/5990945/1515819 –

+0

Ese tidbit en la carga me salvó la vida. Gracias – Russ

+0

en el caso de jQuery es mejor usar '$ ('# alphasvg'). Load' en lugar de' $ (ventana) .load'. Esto le permitirá cambiar el atributo 'data' sobre la marcha – vkabachenko

1

Si está utilizando una etiqueta <img> para el SVG, entonces no se puede manipular su contenido (hasta donde yo sé).

Como muestra la respuesta aceptada, usar <object> es una opción.

Necesitaba esto recientemente y se utiliza gulp-inject durante mi trago de construcción para inyectar el contenido de un archivo SVG directamente en el documento HTML como un elemento <svg>, que luego es muy fácil trabajar con el uso de selectores CSS y querySelector/getElementBy*.

Cuestiones relacionadas