Angenommen, Sie erstellen ein SVG-Iconsystem. Sie erstellen manuell ein SVG-Sprite voller Symbole oder verwenden ein Build-Tool wie IcoMoon oder grunt-svgstore, um es für Sie zu erstellen.
Was machen Sie mit diesem sprite.svg?
Eine Option ist, es direkt am Anfang des Dokuments einzufügen und dann damit zu arbeiten <use>.
...
</head>
<body>
<!-- include it here -->
<?php include_once("svg/sprite.svg"); ?>
...
<!-- use it here -->
<a href="/" class="logo">
<svg class="logo">
<use xlink:href="#logo" />
</svg>
</a>
Das funktioniert, aber es nutzt das Caching nicht sehr gut. Wenn die Website HTML-Caching verwendet, enthält jede einzelne Seite diesen großen Block identischer SVG-Daten, was etwas aufbläht. Ganz zu schweigen davon, dass der HTML-Parser vor dem Inhalt all diese Daten bei jedem Seitenaufruf im Dokument durchlesen muss.
Wahrscheinlich ist es besser, das Browser-Caching zu nutzen, wie wir es bei allen anderen Assets tun. Das können wir erreichen, indem wir unsere <use>-Elemente auf eine externe Quelle verweisen lassen. Aber einige Browser haben damit Probleme. Nämlich jede Version von IE und einige ältere WebKit-Versionen.
SVG for Everybody, das wir hier empfohlen haben, funktioniert meist gut. Aber es gibt einige Browser, die es mit dem UserAgent-Abgleich nicht erfasst.
Ein alternativer Ansatz ist, das Sprite einfach per Ajax abzurufen (immer) und es auf die Seite zu injizieren. Das bedeutet, dass Sie dieses SVG im Browser cachen können und es überall dort funktioniert, wo Inline-SVG funktioniert.
Wenn Sie ein vollständiges SVG-Dokument per Ajax abrufen (sprite.svg), ist es tatsächlich *etwas* knifflig. Sie müssen sicherstellen, dass das SVG den richtigen Namensraum hat, bevor Sie es auf die Seite einfügen (danke Amelia). Glücklicherweise können wir den HTML-Parser ausnutzen, der normalerweise dafür zuständig ist. Das erreichen wir, indem wir das SVG in ein <div> einfügen und dieses dann auf die Seite einfügen.
var ajax = new XMLHttpRequest();
ajax.open("GET", "svg/sprite.svg", true);
ajax.send();
ajax.onload = function(e) {
var div = document.createElement("div");
div.innerHTML = ajax.responseText;
document.body.insertBefore(div, document.body.childNodes[0]);
}
Wenn Sie jQuery verwenden, sind die Callback-Daten, die es Ihnen liefert, bereits als SVG-Dokument formatiert. Sie müssen es also zuerst wieder in einen String umwandeln, bevor Sie es in das Div und schließlich auf die Seite einfügen.
$.get("svg/sprite.svg", function(data) {
var div = document.createElement("div");
div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
document.body.insertBefore(div, document.body.childNodes[0]);
});
Denken Sie daran, dass Sie bei diesem Ansatz nur den Bezeichner verwenden, nicht die externe Quelle.
<svg class="icon" viewBox="0 0 100 100">
<use xlink:href="#shape-icon-1" />
</svg>
Scheint in IE und Android gut zu funktionieren

Denken Sie auch daran, dass SVG for Everybody Ihnen dabei hilft, die Markup-Elemente in Nicht-Unterstützungs-Browsern in <img src="...png"> umzuwandeln. Wenn Ihnen das wichtig ist, müssten Sie das dort selbst regeln.
Funktioniert überhaupt nicht in Opera.
Wirklich? Es scheint so zu sein.
Habe vor etwa einem Monat etwas Ähnliches geschrieben. Ich verlasse mich auf jQuery, aber man könnte es offensichtlich auch mit Vanilla JS machen. https://pathartl.me/inline-svg-ajax/
Ziemlich cool!
Das sieht so aus, als würde es für jedes einzelne SVG eine Ajax-Anfrage stellen. Die Idee eines SVG-Sprites ist, dass es eine einzige Anfrage ist. Nur etwas zum Nachdenken.
Ja! Ich habe das hauptsächlich für große SVGs geschrieben. Oder besser gesagt, um CSS-fähige SVGs zu laden, so wie normale Bilder geladen werden. Daher das synchrone Laden.
Nur ein bisschen verwirrt. Sie sagen also, dass der Browser durch die Verwendung von Ajax sprite.svg cachen kann, weil der Browser es als Datei behandelt, ja?
Außerdem verlassen Sie sich natürlich darauf, dass JS funktioniert. Wenn es fehlschlägt oder deaktiviert ist, funktioniert dies offensichtlich nicht, aber ich denke, das ist in Ordnung, wenn Sie nur Verbesserungen wie Icons einfügen.
Das ist alles richtig.
Hier wird beispielsweise gezeigt, wie Sie mit .htaccess sicherstellen können, dass das SVG korrekt bereitgestellt und gecacht wird
Ich mag es!
Ich habe etwas Ähnliches verwendet, um SVG zu laden, das von gulp-svgstore kombiniert wurde. Der einzige Unterschied ist, dass ich den Inhalt vor dem Skript-Tag einfüge.
Danke für den Hinweis auf den
innerHTML-Trick, aber den brauchen Sie hier nicht.XMLHttpRequestliefert Ihnen ein vollständiges XML-Dokument; Sie können einfach den SVG-Knoten abrufen und ihn direkt einfügen.(Da eine gültige, eigenständige SVG-Datei *XML* ist, wird dies eine bessere Browserunterstützung haben als für HTML-Dokumente, die eine spätere Erweiterung waren.)
Der einzige Trick ist, dass Sie bei Firefox und IE explizit angeben müssen, dass die Antwort ein Dokument und kein einfacher Text/Binärdaten ist. Ich würde denken, der MIME-Typ
image/svg+xmlwäre ausreichend, aber anscheinend nicht.Der grundlegende JavaScript-Code wäre dann
Ich füge in diesem Pen ein paar zusätzliche Zeilen hinzu, um eine Klasse auf das SVG zu setzen, bevor ich es in das Dokument injiziere, und um einen try/catch-Block hinzuzufügen, falls es Probleme mit dem Dateizugriff gibt. Es funktioniert, wenn Sie ein glänzendes goldenes Rechteck sehen, es funktioniert nicht, wenn Sie ein durchgehend rotes sehen
http://codepen.io/AmeliaBR/pen/OPbrjy
Danke, Amelia. Können Sie mir helfen, den besten Weg zu finden, mehrere SVG-Sprite-Dateien mit AJAX abzurufen und zu laden?
Ich bin überrascht, dass dies mit einer asynchronen Anfrage funktioniert. Was passiert, wenn
<use>vor dem Hinzufügen des SVG zur Seite geparst wird?Liebe es!
Liebe es!
kann man das nur mit html 5 machen?
Nun, es ist knifflig, aber nützlich!
Ich habe einfach
<object>in HTML eingefügtUnd ersetze es dann mit dem SVG-Inhalt, sobald es geladen ist
Meiner Meinung nach erhält man dadurch Caching & sauberes Markup.
Ich habe einen Helfer geschrieben, um diese Ersetzungen für mich wie folgt durchzuführen
Das sieht gut aus, aber bedeutet das, dass jedes einzelne SVG separat ist? Die größere Idee hier ist eine einzige Anfrage.
Ich habe diese Technik verwendet, um einige separate Dateien zu laden, aber das sollte wirklich keine Rolle spielen. Sie können ein Sprite laden und es dann nach Belieben verwenden.
HTML
JS
Habe gerade einen kurzen Test gemacht – es scheint in allen Browsern (FF, Chrome, Safari, Opera, IE 9 – 11) gut zu funktionieren.
Ich bin gerade auf eine üble Eigenart dieser Technik gestoßen: Wo auch immer sie platziert sind, betrachtet Chrome (40) verwendete Symbole (z. B.
<use xlink:href="#symbol-id" />) als Nachfahren des ursprünglichen<svg>-Tags, einschließlich der Position dieses Tags im DOM. Dies schließt die Möglichkeit aus, dasselbe SVG-Symbol mit unterschiedlichen Füllungen basierend auf dem Kontext, in dem dasuse-Tag erscheint, neu zu stylen.z. B. funktioniert das in Chrome nicht
SVG
HTML
CSS
Funktioniert in Firefox, und ich habe es nicht in anderen Browsern ausprobiert, aber Chrome betrachtet das Symbol nicht als tatsächlich innerhalb des
<use>-Tags existierend, sodass der Selektor.pink-logo .logo-parteffektiv nicht übereinstimmt.Kleine Ergänzung; es sieht so aus, als ob das Verhalten von Chrome im Einklang mit den W3C-Spezifikationen steht
http://www.w3.org/TR/SVG11/struct.html#UseElement
Da dies bis in die Interna von SVG reicht, ist die einzige Umgehungslösung, die mir einfällt (für Situationen, in denen Sie bestimmte Elemente innerhalb eines SVG auswählen und stylen müssen), die Verwendung von JS, um Symbole aus dem DOM zu extrahieren und sie direkt an ein neues SVG-Element anzuhängen, wodurch
<use>gänzlich vermieden wird. Für die meisten Situationen ist es fast sicher besser, einfach Duplikate von Symbolen für jede Ihrer Variationen zu erstellen. (Einsatz einer traurigen Posaune.)