Sematkan SVG di SVG?

103

Saya memiliki dokumen SVG, dan saya ingin menyertakan gambar svg eksternal di dalamnya, misalnya:

<object data="logo.svgz" width="100" height="100" x="200" y="400"/>

("object" hanyalah sebuah contoh - dokumen terluar akan menjadi SVG bukan xhtml).

Ada ide? Apakah ini mungkin? Ataukah hal terbaik bagi saya untuk menampar logo.svg xml ke dalam dokumen SVG luar saya?

Marcin
sumber

Jawaban:

142

Gunakan imageelemen dan rujuk file SVG Anda. Untuk bersenang-senang, simpan yang berikut ini sebagai recursion.svg:

<svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1"
     xmlns="http://www.w3.org/2000/svg">
  <circle cx="-50" cy="-50" r="30" style="fill:red" />
  <image x="10" y="20" width="80" height="80" href="recursion.svg" />
</svg>
Phrogz
sumber
4
Terima kasih, untuk beberapa alasan googling saya untuk ini tidak berfungsi sampai saya memposting pertanyaan ini. Saya perhatikan bahwa lebar dan tinggi harus ada agar gambar dapat dirender.
Marcin
20
Satu pengamatan menarik: versi terbaru Firefox, Chrome, dan Safari semuanya hanya menampilkan satu tingkat rekursi (dua titik) menggunakan yang di atas. Namun, jika Anda menyimpan gambar di atas sebagai "a.svg" dan mengubah gambar menjadi "b.svg", lalu menyimpannya juga sebagai "b.svg" dengan gambar merujuk "a.svg", maka Firefox akan menampilkan tambahan tingkat rekursi untuk setiap kali Anda memuat ulang file bergantian . Tampaknya hasil cache setiap kali Anda memuat file, semakin dalam satu tingkat.
Phrogz
6
@IanStormTaylor Elemen SVG tidak memiliki properti gayanya sendiri; melainkan item di dalam elemen SVG memiliki gaya. Namun, bila menggunakan <image>dalam SVG (atau <img>atau <embed>di HTML) untuk referensi file SVG Anda tidak diberi akses ke DOM yang mendasari. Karena itu, tidak, Anda tidak dapat mengatur gaya elemen di dalam elemen SVG yang telah direferensikan oleh <image>.
Phrogz
2
@proteneer <image xlink:href="data:image/svg+xml;utf8,&lt;svg …&gt;… &lt;/svg&gt;" />. (Jika Anda menggunakan JavaScript untuk menyetel hrefatribut, Anda tidak perlu keluar dari <karakter dll.)
Phrogz
1
xlink:hrefsudah usang , sekarang Anda harus menggunakan href. Bisakah Anda memperbarui jawaban Anda untuk memasukkan itu?
Donald Duck
97

Atau Anda sebenarnya dapat menyematkan anak svg di orang tua svg seperti ini:

<svg>
    <g>
        <svg>
            ...
        </svg>
    </g>
</svg>

demo:
http://hitokun-s.github.io/old/demo/path-between-two-svg.html

toshi
sumber
@toshi apakah Anda memiliki contoh lain dari jawaban Anda? saya mencoba tetapi gagal menerapkan saran Anda. SVG 'luar' saya menetapkan lingkaran dan gradien. SVG batin saya adalah sebuah objek. berdiri sendiri, SVG bagian dalam bekerja seperti yang diharapkan. tetapi SVG bagian dalam tidak ditampilkan dalam implementasi saran Anda. karenanya, permintaan saya untuk melihat contoh lain.
Jay Grey
1
1 untuk menyebutkan alternatif mandiri. Bagaimana cara kerja positioning / ukuran dari svg yang tersemat seperti itu?
bluenote10
Saya ingin menambahkan bahwa Anda dapat menambahkan transformasi ke elemen <g> ini: terjemahan, rotasi, dll. Dengan cara ini Anda dapat memposisikan ulang elemen secara dinamis
Christoph B
Misalnya, untuk memindahkan elemen Anda harus menulis: <g transform = "translate (30,10)"> ... </g>
Christoph B
42

Perlu disebutkan bahwa saat Anda menyematkan SVG ke SVG lain dengan:

<image x="10" y="20" width="80" height="80" xlink:href="image.svg" />

kemudian SVG yang disematkan mengambil bentuk persegi panjang dengan dimensi tertentu.

Artinya, jika SVG Anda yang disematkan adalah lingkaran atau beberapa bentuk selain persegi, maka itu menjadi persegi dengan transparansi. Oleh karena itu, peristiwa mouse terjebak ke dalam kotak sematan itu dan tidak mencapai SVG induk. Hati-hati dengan itu.

Pendekatan yang lebih baik adalah menggunakan pola. Untuk mengisi bentuk, baik lingkaran, persegi, atau bahkan jalur.

<defs>
 <pattern id="pat" x="0" y="0" width="500" height="500" patternUnits="userSpaceOnUse">
   <image x="0" y="0" width="500" height="500" xlink:href="images/mysvg.svg"></image>
 </pattern>
</defs>

Kemudian gunakan pola seperti ini:

<circle cx="0" cy="0" r="250" fill="url(#pat)"></circle>

Sekarang acara mouse Anda tidak terjebak dalam kotak gambar transparan!

oabarca
sumber
Pola isian itu sempurna, terima kasih. Untuk sisipan yang lebih kecil atau kotak tampilan yang lebih kecil, pembuat kode mungkin ingin mengurangi semua lebar dan tinggi dalam ukuran yang sama.
Steve Taylor
7

Saya menemukan bahwa menggunakan <image>tag memberikan kualitas rendah dari file yang disematkan. Namun teknik berikut berhasil (untuk menyematkan file SVG di dalam file SVG - tidak harus untuk rendering di halaman HTML):

  • Edit file SVG di editor teks.

  • Temukan akhir metadata:

    </metadata>
      <g
       id="layer1"
       inkscape:groupmode="layer"
       inkscape:label="Layer 1">
    
  • Masukkan baris ini setelah tag grup itu:

    <use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />
    
  • Dalam hal ini kami memasukkan OTHERFILE.svg ke dalam file, dan semua layer1 (lapisan pertama dan default).

  • Simpan ini dan kemudian buka file di Inkscape.

Teknik ini berguna untuk memiliki latar belakang atau logo standar pada setiap halaman. Dengan meletakkannya terlebih dahulu di file, itu akan dirender terlebih dahulu (dan dengan demikian di bagian bawah). Anda juga bisa menguncinya dengan menambahkan atribut ini:

sodipodi:insensitive="true" 

Dengan kata lain:

<use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />
Nick Gammon
sumber
@WilliamEntriken Apa yang Anda maksud dengan "file eksternal"? Cara yang saya jelaskan menggunakan file eksternal yaitu file dengan barang-barang lain di dalamnya.
Nick Gammon
6

Catatan xlink:hrefsudah tidak digunakan lagi , gunakan hrefsaja, mis

<svg viewBox="0 0 512 512">
  <image width="512" height="512" href="external.svg"/>
</svg>

viewBox, widthdan heightnilai (dalam jawaban ini) hanya untuk tujuan ilustrasi, sesuaikan tata letak yang sesuai ( baca lebih lanjut ).

Karena <image> memiliki spesifikasi yang mirip dengan <img>, artinya tidak mendukung gaya SVG, seperti yang disebutkan dalam jawaban Christiaan . Misalnya, jika saya memiliki baris css berikut yang mengatur warna bentuk svg menjadi sama dengan warna font,

svg {
  fill: currentColor;
}

Gaya di atas tidak akan berlaku jika <image>digunakan. Untuk itu, Anda perlu menggunakan <use>, seperti yang ditunjukkan pada jawaban Nick .

Catatan id="layer1"dan href="OTHERFILE.svg#layer1"nilai dalam jawabannya adalah wajib .

Artinya Anda harus menambahkan idatribut ke file svg eksternal, jadi Anda perlu meng-host file svg eksternal (yang dimodifikasi) sendiri (situs web Anda) atau di tempat lain. File svg eksternal yang dihasilkan terlihat seperti ini (perhatikan di mana saya meletakkan id):

<svg id="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
  <path d="..."/>
</svg>

Nilai id bisa apa saja, saya menggunakan "logo" dalam contoh ini.

Untuk menyematkan svg itu,

<svg viewBox="0 0 512 512">
  <use href="edited-external.svg#logo"/>
</svg>

Jika Anda menggunakan svg di atas sebagai inline di html Anda, Anda tidak memerlukan atribut xmlns (setidaknya yang saya ketahui dari svgo ).

Saftever
sumber
1
viewBox tidak wajib, jika Anda mengabaikannya Anda akan mendapatkan tata letak yang berbeda, dalam beberapa kasus mungkin itu yang Anda inginkan. Safari baru saja mulai mendukung href.
Robert Longson
5

Saya perlu menyematkan SVG di SVG saya, tetapi juga mengubah warnanya dan menerapkan transformasi.

Hanya Firefox yang mendukung atribut "transform" pada elemen svg bersarang. Mengubah warna <image> juga tidak dimungkinkan. Jadi dibutuhkan kombinasi keduanya.

Apa yang akhirnya saya lakukan adalah sebagai berikut

<svg>
  <image x="0" y="0" xlink:href="data:image/svg+xml;base64,[base64 of nested svg]"></image>
</svg>

Ini berfungsi setidaknya di Firefox, Chrome, dan Inkscape.

Ini berperilaku sama dengan anak svg di jawaban orang tua svg dengan pengecualian bahwa Anda sekarang dapat menerapkan transformasi di atasnya.

Christiaan
sumber