Kiedy przekazujesz ciąg znaczników $
, jest on analizowany jako HTML przy użyciu właściwości przeglądarki innerHTML
na <div>
(lub innym odpowiednim kontenerze w szczególnych przypadkach, takich jak <tr>
). innerHTML
nie może przeanalizować SVG ani innej treści innej niż HTML, a nawet gdyby mógł, nie byłby w stanie stwierdzić, że <circle>
powinien znajdować się w przestrzeni nazw SVG.
innerHTML
nie jest dostępny w SVGElement - jest tylko własnością HTMLElement. Nie ma obecnie innerSVG
właściwości ani innego sposobu (*) do parsowania treści w SVGElement. Z tego powodu powinieneś używać metod w stylu DOM. jQuery nie zapewnia łatwego dostępu do metod przestrzeni nazw potrzebnych do tworzenia elementów SVG. Naprawdę jQuery nie jest w ogóle przeznaczony do użytku z SVG i wiele operacji może się nie powieść.
HTML5 obiecuje, że w przyszłości będziesz mógł używać go <svg>
bez xmlns
zwykłego text/html
dokumentu HTML ( ). Ale to tylko hack parsera (**), zawartość SVG nadal będzie SVGElements w przestrzeni nazw SVG, a nie HTMLElements, więc nie będziesz mógł używać, innerHTML
nawet jeśli wyglądają jak część dokumentu HTML.
Jednak w dzisiejszych przeglądarkach musisz używać X HTML (poprawnie wyświetlanego jako application/xhtml+xml
; zapisz z rozszerzeniem .xhtml do testowania lokalnego), aby SVG w ogóle działało. (W każdym razie ma to sens; SVG jest właściwie standardem opartym na XML.) Oznacza to, że będziesz musiał uciec od <
symboli wewnątrz bloku skryptu (lub ująć w sekcji CDATA) i dołączyć xmlns
deklarację XHTML . przykład:
<!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>
*: cóż, istnieje parseWithContext DOM Level 3 LS , ale obsługa przeglądarki jest bardzo słaba. Edytuj, aby dodać: chociaż nie możesz wstrzykiwać znaczników do SVGElement, możesz wstrzyknąć nowy SVGElement do HTMLElement za pomocą innerHTML
, a następnie przenieść go do pożądanego celu. Prawdopodobnie będzie trochę wolniej:
<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>
**: Nienawidzę sposobu, w jaki autorzy HTML5 boją się XML-a i postanowili wprowadzić funkcje oparte na XML w kruchym bałaganie jakim jest HTML. XHTML rozwiązał te problemy lata temu.
RMB
>edit as html
na znaczniku html i naciśniesz, wpisz wszystko, co się wyświetla (ale wszystkie detektory zdarzeń znikają). Po przeczytaniu tej odpowiedzi zmieniłem wywołania createElement na createElementNS i teraz wszystko działa!d3.select('body').append('svg').attr('width','100%');
$.parseXML
.W Zaakceptowanych odpowiedź pokazuje zbyt skomplikowany sposób. Jak twierdzi Forresto w swojej odpowiedzi „ wydaje się, że dodaje je w eksploratorze DOM, ale nie na ekranie ”, a przyczyną tego są różne przestrzenie nazw dla html i svg.
Najłatwiejszym obejściem jest „odświeżenie” całego pliku svg. Po dołączeniu kręgu (lub innych elementów) użyj tego:
To załatwia sprawę. Krąg jest na ekranie.
Lub jeśli chcesz, użyj div kontenera:
I owinąć swój plik SVG wewnątrz div pojemnika:
Przykład funkcjonalny:
http://jsbin.com/ejifab/1/edit
Zalety tej techniki:
$('svg').prepend('<defs><marker></marker><mask></mask></defs>');
jak ty w jQuery.$("#cont").html($("#cont").html());
ich na ekranie za pomocą ich atrybutów można je edytować za pomocą jQuery.EDYTOWAĆ:
Powyższa technika działa tylko z SVG „zakodowanym na stałe” lub DOM (= document.createElementNS itp.). Jeśli Raphael jest używany do tworzenia elementów, (zgodnie z moimi testami) połączenie między obiektami Raphaela i SVG DOM zostanie przerwane, jeśli
$("#cont").html($("#cont").html());
zostanie użyte. Obejściem tego problemu jest w ogóle nieużywanie,$("#cont").html($("#cont").html());
a zamiast tego używanie fałszywego dokumentu SVG.Ten manekin SVG jest najpierw tekstową reprezentacją dokumentu SVG i zawiera tylko potrzebne elementy. Jeśli chcemy np. aby dodać element filtrujący do dokumentu Raphaela, manekin może być podobny
<svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
. Reprezentacja tekstowa jest najpierw konwertowana na DOM za pomocą metody $ („body”). Append () jQuery'ego. A gdy element (filter) znajduje się w DOM, można go odpytywać przy użyciu standardowych metod jQuery i dołączać do głównego dokumentu SVG, który jest tworzony przez Raphaela.Dlaczego ten manekin jest potrzebny? Dlaczego nie dodać elementu filtrującego ściśle do dokumentu utworzonego przez Raphaela? Jeśli spróbujesz użyć np.
$("svg").append("<circle ... />")
, jest tworzony jako element HTML i nic nie jest wyświetlane na ekranie, jak opisano w odpowiedziach. Ale jeśli dołączony jest cały dokument SVG, przeglądarka automatycznie obsługuje konwersję przestrzeni nazw wszystkich elementów w dokumencie SVG.Przykład oświeca technikę:
Pełna działająca wersja demonstracyjna tej techniki znajduje się tutaj: http://jsbin.com/ilinan/1/edit .
(Nie mam (jeszcze) pojęcia, dlaczego
$("#cont").html($("#cont").html());
nie działa przy użyciu Rafaela. Byłby to bardzo krótki hack.)źródło
$("#cont").html($("#cont").html());
działał świetnie w Chrome, ale nie działał w IE 11 dla mnie.Coraz popularniejsza biblioteka D3 bardzo ładnie radzi sobie z dziwactwami związanymi z dodawaniem / manipulowaniem SVG. Możesz rozważyć użycie go w przeciwieństwie do wspomnianych tutaj hacków jQuery.
HTML
JavaScript
źródło
JQuery nie może dołączać elementów
<svg>
(wydaje się, że dodaje je w eksploratorze DOM, ale nie na ekranie).Jednym z obejść tego problemu jest dołączenie
<svg>
wszystkich elementów potrzebnych do strony, a następnie zmodyfikowanie atrybutów elementów za pomocą.attr()
.http://jsfiddle.net/8FBjb/1/
źródło
<circle>
lub innych elementów indywidualnie przy użyciu złożonych i powolnych metod DOM (np.createDocumentFragment()
LubcreateElementNS()
), dołącz cały dokument svg do kontenera. Zamiast $ („body”) może to być oczywiście również $ („div”). A potem dokument svg znajduje się w DOM i można go przeszukiwać w znany sposób, używając np. $ („c”). attr („fill”, „red”).Nie widziałem, żeby ktoś wspominał o tej metodzie, ale
document.createElementNS()
jest pomocny w tym przypadku.Możesz tworzyć elementy za pomocą waniliowego Javascript jako normalnych węzłów DOM z poprawną przestrzenią nazw, a następnie stamtąd je pobrać. Tak jak:
Jedynym minusem jest to, że musisz utworzyć każdy element SVG z odpowiednią przestrzenią nazw osobno, inaczej nie zadziała.
źródło
Znalazłem prosty sposób, który działa ze wszystkimi przeglądarkami, które mam (Chrome 49, Edge 25, Firefox 44, IE11, Safari 5 [Win], Safari 8 (MacOS)):
źródło
Widzę okrąg w firefoxie, robiąc 2 rzeczy:
1) Zmiana nazwy pliku z html na xhtml
2) Zmień skrypt na
źródło
Na podstawie odpowiedzi @ chris-dolphin, ale używając funkcji pomocnika:
źródło
$svg.append($s('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'));
Jeśli ciąg, który musisz dołączyć, to SVG i dodasz odpowiednią przestrzeń nazw, możesz przeanalizować ciąg jako XML i dołączyć do elementu nadrzędnego.
źródło
Odpowiedź zaakceptowana przez Bobince to krótkie, przenośne rozwiązanie. Jeśli potrzebujesz nie tylko dołączyć SVG, ale także nim manipulować, możesz wypróbować bibliotekę JavaScript „Pablo” (napisałem to). Będzie to dobrze znane użytkownikom jQuery.
Twój przykład kodu wyglądałby wtedy następująco:
Możesz także tworzyć elementy SVG w locie, bez określania znaczników:
źródło
Sugerowałbym, że lepiej byłoby użyć ajax i załadować element svg z innej strony.
Gdzie href to lokalizacja strony z svg. W ten sposób można uniknąć efektów roztrzęsienia, które mogą wystąpić podczas zastępowania zawartości HTML. Nie zapomnij też rozpakować pliku svg po załadowaniu:
źródło
Działa to dla mnie dzisiaj z FF 57:
Sprawia:
źródło
$(this).clone()
klonuje element SVG (i to dzieci, jeśli takie miały). Rozejrzyj się za użyciemtext()
. Biorę pojedynczy tspan, który zawierał „Your New”, i kończę na dwóch tspan, jednym z „Your” w nim (czarny) i jednym z „New in it” (niebieski w / line-through). Jezu, z 0 głosów na -1 :-(źródło
Znacznie prostszym sposobem jest po prostu wygenerowanie pliku SVG w ciąg, utworzenie opakowania HTML i wstawienie ciągu svg do elementu HTML za pomocą
$("#wrapperElement").html(svgString)
. Działa to dobrze w Chrome i Firefox.źródło