La respuesta aceptada muestra una forma demasiado complicada. Como Forresto afirma en su respuesta , " parece agregarlos en el explorador DOM, pero no en la pantalla " y la razón de esto son los diferentes espacios de nombres para html y svg.
La solución más fácil es "actualizar" todo el svg. Después de agregar un círculo (u otros elementos), use esto:
$("body").html($("body").html());
Esto hace el truco. El círculo está en la pantalla.
O si lo desea, use un contenedor div:
$("#cont").html($("#cont").html());
Y envuelva su svg dentro del contenedor div:
<div id="cont">
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" width="200px" height="100px">
</svg>
</div>
El ejemplo funcional:
http://jsbin.com/ejifab/1/edit
Las ventajas de esta técnica:
- puede editar svg existente (que ya está en DOM), por ejemplo. creado usando Rafael o similar en su ejemplo "codificado" sin scripting.
- puede agregar estructuras de elementos complejos como cadenas, por ejemplo.
$('svg').prepend('<defs><marker></marker><mask></mask></defs>');
como haces en jQuery.
- después de que los elementos se agreguen y se hagan visibles en la pantalla con
$("#cont").html($("#cont").html());
sus atributos, se pueden editar con jQuery.
EDITAR:
La técnica anterior funciona solo con SVG "codificado" o DOM manipulado (= document.createElementNS, etc.). Si se usa Raphael para crear elementos, (de acuerdo con mis pruebas) la conexión entre los objetos Raphael y SVG DOM se rompe si $("#cont").html($("#cont").html());
se usa. La solución a esto es no usar $("#cont").html($("#cont").html());
en absoluto y en lugar de usar un documento SVG ficticio.
Este SVG ficticio es primero una representación textual del documento SVG y contiene solo los elementos necesarios. Si queremos, por ejemplo. para agregar un elemento de filtro al documento de Raphael, el ficticio podría ser algo así <svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
. La representación textual se convierte primero a DOM utilizando el método $ ("body"). Append () de jQuery. Y cuando el elemento (filtro) está en DOM, puede consultarse utilizando métodos jQuery estándar y adjuntarse al documento SVG principal creado por Raphael.
¿Por qué se necesita este muñeco? ¿Por qué no agregar un elemento de filtro estrictamente al documento creado por Raphael? Si lo intentas usando eg. $("svg").append("<circle ... />")
, se crea como elemento html y no hay nada en la pantalla como se describe en las respuestas. Pero si se agrega todo el documento SVG, entonces el navegador maneja automáticamente la conversión del espacio de nombres de todos los elementos en el documento SVG.
Un ejemplo ilustra la técnica:
// Add Raphael SVG document to container element
var p = Raphael("cont", 200, 200);
// Add id for easy access
$(p.canvas).attr("id","p");
// Textual representation of element(s) to be added
var f = '<filter id="myfilter"><!-- filter definitions --></filter>';
// Create dummy svg with filter definition
$("body").append('<svg id="dummy" style="display:none"><defs>' + f + '</defs></svg>');
// Append filter definition to Raphael created svg
$("#p defs").append($("#dummy filter"));
// Remove dummy
$("#dummy").remove();
// Now we can create Raphael objects and add filters to them:
var r = p.rect(10,10,100,100);
$(r.node).attr("filter","url(#myfilter)");
La demostración de trabajo completa de esta técnica está aquí: http://jsbin.com/ilinan/1/edit .
(Todavía no tengo idea, por qué $("#cont").html($("#cont").html());
no funciona cuando se usa Raphael. Sería un truco muy corto).
RMB
>edit as html
en la etiqueta html y presiono enter, se muestra todo (pero todos los oyentes de eventos desaparecen). Después de leer esta respuesta, cambié mis llamadas createElement a createElementNS y ahora todo funciona.