El réponse acceptée montre une manière trop compliquée. Comme l'affirme Forresto dans sa réponse , " il semble les ajouter dans l'explorateur DOM, mais pas à l'écran. "La raison en est que les espaces de noms sont différents pour html et svg.
La solution la plus simple consiste à "rafraîchir" l'ensemble du svg. Après avoir ajouté le cercle (ou d'autres éléments), utilisez ceci :
$("body").html($("body").html());
Cela fait l'affaire. Le cercle est sur l'écran.
Ou si vous le souhaitez, utilisez un div de conteneur :
$("#cont").html($("#cont").html());
Et enfermez votre svg dans le div du conteneur :
<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>
L'exemple fonctionnel :
http://jsbin.com/ejifab/1/edit
Les avantages de cette technique :
- vous pouvez modifier un svg existant (qui est déjà dans le DOM), par exemple créé à l'aide de Raphael ou comme dans votre exemple "codé en dur" sans script.
- vous pouvez ajouter des structures d'éléments complexes comme des chaînes de caractères, par exemple.
$('svg').prepend('<defs><marker></marker><mask></mask></defs>');
comme vous le faites dans jQuery.
- après que les éléments aient été ajoutés et rendus visibles à l'écran à l'aide de la fonction
$("#cont").html($("#cont").html());
leurs attributs peuvent être modifiés à l'aide de jQuery.
EDITAR:
La technique ci-dessus fonctionne uniquement avec les SVG "codés en dur" ou manipulés par DOM ( = document.createElementNS etc.). Si Raphael est utilisé pour créer des éléments, (selon mes tests) le lien entre les objets Raphael et le DOM SVG est rompu si $("#cont").html($("#cont").html());
est utilisé. La solution de contournement consiste à ne pas utiliser la fonction $("#cont").html($("#cont").html());
au lieu d'utiliser un document SVG factice.
Ce SVG factice est d'abord une représentation textuelle du document SVG et ne contient que les éléments nécessaires. Si nous voulons par exemple ajouter un élément de filtre au document Raphael, le dummy pourrait être quelque chose comme <svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
. La représentation textuelle est d'abord convertie en DOM à l'aide de la méthode $("body").append() de jQuery. Et lorsque l'élément (filtre) est dans le DOM, il peut être interrogé à l'aide des méthodes standard de jQuery et ajouté au document SVG principal qui est créé par Raphael.
Pourquoi cet élément factice est-il nécessaire ? Pourquoi ne pas ajouter un élément de filtre strictement au document créé par Raphael ? Si vous l'essayez en utilisant par exemple $("svg").append("<circle ... />")
il est créé comme élément html et rien n'apparaît à l'écran comme décrit dans les réponses. Mais si le document SVG entier est annexé, le navigateur gère automatiquement la conversion de l'espace de nom de tous les éléments du document SVG.
Un exemple permet d'éclairer la technique :
// 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)");
Une démonstration complète de cette technique est disponible ici : http://jsbin.com/ilinan/1/edit .
( Je n'ai (encore) aucune idée, pourquoi $("#cont").html($("#cont").html());
ne fonctionne pas quand on utilise Raphael. Ce serait un hack très court. )