Wenn Sie eine Markup-Zeichenfolge übergeben $
, wird diese mithilfe der Browsereigenschaft innerHTML
in einem <div>
(oder einem anderen geeigneten Container für Sonderfälle wie <tr>
) als HTML analysiert . innerHTML
SVG oder andere Nicht-HTML-Inhalte können nicht analysiert werden, und selbst wenn dies möglich wäre, könnte es nicht erkennen, dass <circle>
sie sich im SVG-Namespace befinden sollten.
innerHTML
ist in SVGElement nicht verfügbar - es ist nur eine Eigenschaft von HTMLElement. Weder gibt es derzeit eine innerSVG
Eigenschaft noch eine andere Möglichkeit (*), Inhalte in ein SVGElement zu analysieren. Aus diesem Grund sollten Sie Methoden im DOM-Stil verwenden. Mit jQuery haben Sie keinen einfachen Zugriff auf die Methoden mit Namespace, die zum Erstellen von SVG-Elementen erforderlich sind. Wirklich, jQuery ist überhaupt nicht für die Verwendung mit SVG ausgelegt und viele Vorgänge können fehlschlagen.
HTML5 verspricht, dass Sie es in Zukunft auch <svg>
ohne ein xmlns
einfaches HTML ( text/html
) -Dokument verwenden können. Dies ist jedoch nur ein Parser-Hack (**). Der SVG-Inhalt ist weiterhin SVGElements im SVG-Namespace und nicht HTMLElements. Sie können ihn also nicht verwenden innerHTML
, obwohl er wie ein Teil eines HTML-Dokuments aussieht .
Für heutige Browser müssen Sie jedoch X- HTML verwenden (ordnungsgemäß application/xhtml+xml
bereitgestellt als : Speichern mit der Dateierweiterung .xhtml für lokale Tests), damit SVG überhaupt funktioniert. (Es macht sowieso Sinn; SVG ist ein ordnungsgemäß XML-basierter Standard.) Dies bedeutet, dass Sie die <
Symbole in Ihrem Skriptblock maskieren (oder in einen CDATA-Abschnitt einschließen) und die XHTML- xmlns
Deklaration einschließen müssen . Beispiel:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
</head><body>
<svg id="s" xmlns="http://www.w3.org/2000/svg"/>
<script type="text/javascript">
function makeSVG(tag, attrs) {
var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
for (var k in attrs)
el.setAttribute(k, attrs[k]);
return el;
}
var circle= makeSVG('circle', {cx: 100, cy: 50, r:40, stroke: 'black', 'stroke-width': 2, fill: 'red'});
document.getElementById('s').appendChild(circle);
circle.onmousedown= function() {
alert('hello');
};
</script>
</body></html>
*: Nun , es gibt parseWithContext von DOM Level 3 LS , aber die Browserunterstützung ist sehr schlecht. Bearbeiten, um hinzuzufügen: Obwohl Sie kein Markup in ein SVGElement einfügen können, können Sie ein neues SVGElement in ein HTMLElement einfügen innerHTML
und es dann auf das gewünschte Ziel übertragen. Es wird wahrscheinlich etwas langsamer sein:
<script type="text/javascript"><![CDATA[
function parseSVG(s) {
var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
var frag= document.createDocumentFragment();
while (div.firstChild.firstChild)
frag.appendChild(div.firstChild.firstChild);
return frag;
}
document.getElementById('s').appendChild(parseSVG(
'<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" onmousedown="alert(\'hello\');"/>'
));
]]></script>
**: Ich hasse die Art und Weise, wie die Autoren von HTML5 Angst vor XML zu haben scheinen und entschlossen sind, XML-basierte Funktionen in das blöde Chaos von HTML zu stecken. XHTML hat diese Probleme vor Jahren gelöst.
RMB
>edit as html
auf dem HTML-Tag drücke und die Eingabetaste drücke, wird alles angezeigt (aber alle Ereignis-Listener verschwinden). Nachdem ich diese Antwort gelesen hatte, änderte ich meine createElement-Aufrufe in createElementNS und jetzt funktioniert alles!d3.select('body').append('svg').attr('width','100%');
$.parseXML
.Die akzeptierte Antwort zeigt einen zu komplizierten Weg. Wie Forresto in seiner Antwort behauptet , " scheint es, sie im DOM-Explorer hinzuzufügen, aber nicht auf dem Bildschirm ", und der Grund dafür sind unterschiedliche Namespaces für HTML und SVG.
Die einfachste Problemumgehung besteht darin, das gesamte SVG zu "aktualisieren". Verwenden Sie nach dem Anhängen eines Kreises (oder anderer Elemente) Folgendes:
Das macht den Trick. Der Kreis wird auf dem Bildschirm angezeigt.
Oder wenn Sie möchten, verwenden Sie einen Container div:
Und wickeln Sie Ihre SVG in Container div:
Das Funktionsbeispiel:
http://jsbin.com/ejifab/1/edit
Die Vorteile dieser Technik:
$('svg').prepend('<defs><marker></marker><mask></mask></defs>');
wie in jQuery.$("#cont").html($("#cont").html());
ihrer Attribute auf dem Bildschirm sichtbar gemacht wurden , können sie mit jQuery bearbeitet werden.BEARBEITEN:
Die obige Technik funktioniert nur mit "hartcodiertem" oder DOM-manipuliertem (= document.createElementNS usw.) SVG. Wenn Raphael zum Erstellen von Elementen verwendet wird, wird (nach meinen Tests) die Verknüpfung zwischen Raphael-Objekten und SVG-DOM unterbrochen, wenn
$("#cont").html($("#cont").html());
es verwendet wird. Die Problemumgehung besteht darin, überhaupt nicht zu verwenden$("#cont").html($("#cont").html());
und stattdessen ein Dummy-SVG-Dokument zu verwenden.Diese Dummy-SVG ist zunächst eine Textdarstellung des SVG-Dokuments und enthält nur Elemente, die benötigt werden. Wenn wir zB wollen. Um dem Raphael-Dokument ein Filterelement hinzuzufügen, könnte der Dummy so etwas wie sein
<svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
. Die Textdarstellung wird zuerst mit der Methode $ ("body"). Append () von jQuery in DOM konvertiert. Wenn sich das (Filter-) Element im DOM befindet, kann es mit Standard-jQuery-Methoden abgefragt und an das von Raphael erstellte SVG-Hauptdokument angehängt werden.Warum wird dieser Dummy benötigt? Warum nicht ein Filterelement ausschließlich dem von Raphael erstellten Dokument hinzufügen? Wenn Sie es mit z.
$("svg").append("<circle ... />")
wird es als HTML-Element erstellt und es wird nichts auf dem Bildschirm angezeigt, wie in den Antworten beschrieben. Wenn jedoch das gesamte SVG-Dokument angehängt wird, übernimmt der Browser automatisch die Namespace-Konvertierung aller Elemente im SVG-Dokument.Ein Beispiel zur Aufklärung der Technik:
Die vollständige Demo dieser Technik finden Sie hier: http://jsbin.com/ilinan/1/edit .
(Ich habe (noch) keine Ahnung, warum
$("#cont").html($("#cont").html());
bei Verwendung von Raphael nicht funktioniert. Es wäre ein sehr kurzer Hack.)quelle
$("#cont").html($("#cont").html());
hat in Chrome großartig funktioniert, aber in IE 11 für mich nicht funktioniert.Die immer beliebter werdende D3- Bibliothek behandelt die Kuriositäten des Anhängens / Manipulierens von SVG sehr gut. Möglicherweise möchten Sie es im Gegensatz zu den hier genannten jQuery-Hacks verwenden.
HTML
Javascript
quelle
JQuery kann keine Elemente anhängen
<svg>
(es scheint sie im DOM-Explorer hinzuzufügen, aber nicht auf dem Bildschirm).Eine Problemumgehung besteht darin, ein
<svg>
mit allen Elementen, die Sie benötigen, an die Seite anzuhängen und dann die Attribute der Elemente mithilfe von zu ändern.attr()
.http://jsfiddle.net/8FBjb/1/
quelle
<circle>
einzelne Elemente mit komplexen und langsamen DOM-Methoden (z. B.createDocumentFragment()
odercreateElementNS()
) einzeln anzuhängen, hängen Sie das gesamte SVG-Dokument an den Container an. Anstelle von $ ('body') kann es natürlich auch $ ('div') geben. Danach befindet sich das SVG-Dokument im DOM und kann auf vertraute Weise mit z. $ ('c'). attr ('fill', 'red').Ich habe noch niemanden gesehen, der diese Methode erwähnt hat,
document.createElementNS()
ist aber in diesem Fall hilfreich.Sie können die Elemente mit Vanilla Javascript als normale DOM-Knoten mit dem richtigen Namespace erstellen und von dort aus jQuery-ify. Wie so:
Der einzige Nachteil ist, dass Sie jedes SVG-Element mit dem richtigen Namespace einzeln erstellen müssen, sonst funktioniert es nicht.
quelle
Es wurde ein einfacher Weg gefunden, der mit allen Browsern funktioniert, die ich habe (Chrome 49, Edge 25, Firefox 44, IE11, Safari 5 [Win], Safari 8 (MacOS)):
quelle
Ich kann einen Kreis in Firefox sehen, der zwei Dinge tut:
1) Umbenennen der Datei von HTML in XML
2) Ändern Sie das Skript in
quelle
Basierend auf der Antwort von @ chris-dolphin, aber mit Hilfe der Hilfsfunktion:
quelle
$svg.append($s('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'));
Wenn die Zeichenfolge, die Sie anhängen müssen, SVG ist und Sie den richtigen Namespace hinzufügen, können Sie die Zeichenfolge als XML analysieren und an das übergeordnete Element anhängen.
quelle
Die akzeptierte Antwort von Bobince ist eine kurze, tragbare Lösung. Wenn Sie SVG nicht nur anhängen, sondern auch bearbeiten müssen, können Sie die JavaScript-Bibliothek "Pablo" (ich habe es geschrieben) ausprobieren . JQuery-Benutzern wird es bekannt vorkommen.
Ihr Codebeispiel würde dann folgendermaßen aussehen:
Sie können SVG-Elemente auch im laufenden Betrieb erstellen, ohne ein Markup anzugeben:
quelle
Ich würde vorschlagen, dass es besser ist, Ajax zu verwenden und das SVG-Element von einer anderen Seite zu laden.
Wobei href der Speicherort der Seite mit dem SVG ist. Auf diese Weise können Sie nervöse Effekte vermeiden, die beim Ersetzen des HTML-Inhalts auftreten können. Vergessen Sie auch nicht, das SVG nach dem Laden auszupacken:
quelle
Das funktioniert heute bei mir mit FF 57:
Macht:
quelle
$(this).clone()
klont ein SVG-Element (und es sind Kinder, wenn es welche hatte). Schauen Sie über die Verwendung von hinaustext()
. Ich nehme einen einzelnen Tspan mit "Your New" und erhalte zwei Tspans, einen mit "Your" (schwarz) und einen mit "New in it" (blau mit Line-Through). Herrgott, von 0 Stimmen auf -1 :-(quelle
Eine viel einfachere Möglichkeit besteht darin, Ihre SVG-Datei einfach in eine Zeichenfolge zu generieren, ein Wrapper-HTML-Element zu erstellen und die SVG-Zeichenfolge mithilfe von in das HTML-Element einzufügen
$("#wrapperElement").html(svgString)
. Dies funktioniert gut in Chrome und Firefox.quelle