Ketika Anda meneruskan string markup $
, itu diuraikan sebagai HTML menggunakan innerHTML
properti browser pada <div>
(atau wadah lain yang cocok untuk kasus khusus seperti <tr>
). innerHTML
tidak dapat mem-parsing SVG atau konten non-HTML lainnya, dan bahkan jika itu bisa, itu tidak akan dapat mengatakan bahwa <circle>
itu seharusnya ada dalam namespace SVG.
innerHTML
tidak tersedia di SVGElement — ini hanya milik HTMLElement. Saat ini tidak ada innerSVG
properti atau cara lain (*) untuk mem-parsing konten ke dalam SVGElement. Untuk alasan ini, Anda harus menggunakan metode DOM-style. jQuery tidak memberi Anda akses mudah ke metode namespaced yang diperlukan untuk membuat elemen SVG. Sungguh jQuery tidak dirancang untuk digunakan dengan SVG sama sekali dan banyak operasi mungkin gagal.
HTML5 berjanji untuk membiarkan Anda menggunakannya <svg>
tanpa dokumen xmlns
HTML ( text/html
) biasa di masa mendatang. Tapi ini hanya hack parser (**), konten SVG masih akan menjadi SVGElements di namespace SVG, dan bukan HTMLElements, jadi Anda tidak akan dapat menggunakan innerHTML
meskipun mereka terlihat seperti bagian dari dokumen HTML.
Namun, untuk peramban hari ini Anda harus menggunakan X HTML (berfungsi dengan baik application/xhtml+xml
; simpan dengan ekstensi file .xhtml untuk pengujian lokal) agar SVG berfungsi sama sekali. (Ini agak masuk akal untuk tetap; SVG adalah standar berbasis XML dengan benar.) Ini berarti Anda harus melarikan diri <
simbol di dalam blok skrip Anda (atau melampirkan di bagian CDATA), dan termasuk xmlns
deklarasi XHTML . contoh:
<!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>
*: well, ada parseWithContext DOM Level 3 LS , tetapi dukungan browser sangat buruk. Sunting untuk menambahkan: namun, sementara Anda tidak bisa menyuntikkan markup ke dalam SVGElement, Anda bisa menyuntikkan SVGElement baru ke dalam HTMLElement menggunakan innerHTML
, lalu mentransfernya ke target yang diinginkan. Ini mungkin akan sedikit lebih lambat:
<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>
**: Saya benci cara penulis HTML5 tampaknya takut pada XML dan bertekad untuk menyuntikkan fitur berbasis XML ke dalam kekacauan crufty yaitu HTML. XHTML memecahkan masalah ini bertahun-tahun yang lalu.
RMB
>edit as html
pada tag html dan tekan enter semuanya menampilkan (tetapi semua pendengar acara menghilang). Setelah membaca jawaban ini, saya mengubah panggilan createElement saya menjadi createElementNS dan sekarang semuanya berfungsi!d3.select('body').append('svg').attr('width','100%');
$.parseXML
.The jawaban yang diterima menunjukkan terlalu rumit cara. Seperti yang Forresto klaim dalam jawabannya , " sepertinya menambahkan mereka di DOM explorer, tetapi tidak di layar " dan alasan untuk ini adalah ruang nama yang berbeda untuk html dan svg.
Solusi termudah adalah "menyegarkan" seluruh svg. Setelah menambahkan lingkaran (atau elemen lain), gunakan ini:
Ini caranya. Lingkaran ada di layar.
Atau jika Anda ingin, gunakan div wadah:
Dan bungkus svg Anda di dalam wadah:
Contoh fungsional:
http://jsbin.com/ejifab/1/edit
Keuntungan dari teknik ini:
$('svg').prepend('<defs><marker></marker><mask></mask></defs>');
seperti yang Anda lakukan di jQuery.$("#cont").html($("#cont").html());
atributnya dapat diedit menggunakan jQuery.EDIT:
Teknik di atas berfungsi dengan "kode keras" atau DOM dimanipulasi (= document.createElementNS dll.) Hanya SVG. Jika Raphael digunakan untuk membuat elemen, (menurut tes saya) hubungan antara objek Raphael dan DOM SVG rusak jika
$("#cont").html($("#cont").html());
digunakan. Solusi untuk ini adalah tidak menggunakan$("#cont").html($("#cont").html());
sama sekali dan alih-alih menggunakan dokumen dummy SVG.Dummy SVG ini merupakan representasi tekstual dari dokumen SVG dan hanya berisi elemen yang diperlukan. Jika kita ingin mis. untuk menambahkan elemen filter ke dokumen Raphael, dummy bisa berupa sesuatu
<svg id="dummy" style="display:none"><defs><filter><!-- Filter definitons --></filter></defs></svg>
. Representasi tekstual pertama kali dikonversi ke DOM menggunakan metode $ ("body"). Append () jQuery. Dan ketika elemen (filter) ada di DOM, ia dapat ditanyakan menggunakan metode jQuery standar dan ditambahkan ke dokumen SVG utama yang dibuat oleh Raphael.Mengapa boneka ini dibutuhkan? Mengapa tidak menambahkan elemen filter secara ketat ke dokumen yang dibuat Raphael? Jika Anda mencobanya menggunakan mis.
$("svg").append("<circle ... />")
, itu dibuat sebagai elemen html dan tidak ada yang ada di layar seperti yang dijelaskan dalam jawaban. Tetapi jika seluruh dokumen SVG ditambahkan, maka browser menangani secara otomatis konversi namespace dari semua elemen dalam dokumen SVG.Contoh mencerahkan teknik:
Demo kerja penuh dari teknik ini ada di sini: http://jsbin.com/ilinan/1/edit .
(Saya (belum) tidak tahu, mengapa
$("#cont").html($("#cont").html());
tidak bekerja saat menggunakan Raphael. Ini akan menjadi retasan yang sangat singkat.)sumber
$("#cont").html($("#cont").html());
bekerja dengan baik di Chrome, tetapi tidak berhasil di IE 11 untuk saya.Pustaka D3 yang semakin populer menangani keanehan menambahkan / memanipulasi svg dengan sangat baik. Anda mungkin ingin mempertimbangkan untuk menggunakannya sebagai lawan dari peretasan jQuery yang disebutkan di sini.
HTML
Javascript
sumber
JQuery tidak dapat menambahkan elemen ke
<svg>
(sepertinya menambahkannya di DOM explorer, tetapi tidak di layar).Salah satu solusinya adalah menambahkan
<svg>
dengan semua elemen yang Anda butuhkan ke halaman, dan kemudian memodifikasi atribut dari elemen yang digunakan.attr()
.http://jsfiddle.net/8FBjb/1/
sumber
<circle>
atau elemen lain secara individual menggunakan metode DOM yang kompleks dan lambat (misalnya.createDocumentFragment()
AtaucreateElementNS()
), tambahkan seluruh dokumen svg ke dalam wadah. Alih-alih $ ('tubuh') tentu saja dapat beberapa $ ('div') juga. Dan setelah itu dokumen svg ada di DOM dan dapat di-query dengan cara yang umum menggunakan mis. $ ('c'). attr ('fill', 'red').Saya belum pernah melihat seseorang yang menyebutkan metode ini tetapi
document.createElementNS()
sangat membantu dalam hal ini.Anda dapat membuat elemen menggunakan Javascript vanilla sebagai node DOM normal dengan namespace yang benar dan kemudian jQuery-ify mereka dari sana. Seperti itu:
Satu-satunya sisi negatifnya adalah Anda harus membuat setiap elemen SVG dengan namespace yang tepat secara individual atau tidak akan berfungsi.
sumber
Menemukan cara mudah yang berfungsi dengan semua browser yang saya miliki (Chrome 49, Edge 25, Firefox 44, IE11, Safari 5 [Win], Safari 8 (MacOS)):
sumber
Saya dapat melihat lingkaran di firefox, melakukan 2 hal:
1) Mengganti nama file dari html ke xhtml
2) Ubah skrip menjadi
sumber
Berdasarkan jawaban @ chris-dolphin tetapi menggunakan fungsi helper:
sumber
$svg.append($s('<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>'));
Jika string yang Anda perlu tambahkan adalah SVG dan Anda menambahkan namespace yang tepat, Anda dapat menguraikan string sebagai XML dan menambahkan ke induk.
sumber
Jawaban yang diterima oleh Bobince adalah solusi singkat dan portabel. Jika Anda tidak hanya perlu menambahkan SVG tetapi juga memanipulasi, Anda bisa mencoba perpustakaan JavaScript "Pablo" (saya menulisnya). Ini akan terasa akrab bagi pengguna jQuery.
Contoh kode Anda kemudian akan terlihat seperti:
Anda juga dapat membuat elemen SVG dengan cepat, tanpa menentukan markup:
sumber
Saya akan menyarankan mungkin lebih baik menggunakan ajax dan memuat elemen svg dari halaman lain.
Di mana href adalah lokasi halaman dengan svg. Dengan cara ini Anda dapat menghindari efek gelisah yang mungkin terjadi karena mengganti konten html. Juga, jangan lupa membuka bungkusan svg setelah dimuat:
sumber
Ini bekerja untuk saya hari ini dengan FF 57:
Membuat:
sumber
$(this).clone()
mengkloning elemen SVG (dan itu anak-anak jika ada). Lihatlah melewati penggunaantext()
. Saya mengambil satu tspan yang memiliki "Your New" di dalamnya, dan berakhir dengan dua tspan, satu dengan "Your" di dalamnya (hitam) dan satu dengan "New in it" (w / line-through biru). Astaga, turun dari 0 suara ke -1 :-(sumber
Cara yang jauh lebih sederhana adalah dengan hanya menghasilkan SVG Anda menjadi sebuah string, membuat elemen HTML pembungkus dan memasukkan string svg ke dalam elemen HTML menggunakan
$("#wrapperElement").html(svgString)
. Ini berfungsi dengan baik di Chrome dan Firefox.sumber