Incorporare SVG in SVG?


98

Ho un documento SVG e vorrei includere un'immagine svg esterna al suo interno, cioè qualcosa del tipo:

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

("oggetto" è solo un esempio: il documento esterno sarà SVG anziché xhtml).

Qualche idea? È anche possibile? O la cosa migliore per me è semplicemente schiaffeggiare il logo.svg xml nel mio documento SVG esterno?

Risposte:


135

Usa l' imageelemento e fai riferimento al tuo file SVG. Per divertimento, salva quanto segue come 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>

3
Grazie, per qualche motivo la mia ricerca su Google per questo non ha funzionato fino a dopo aver pubblicato questa domanda. Noto che la larghezza e l'altezza devono essere presenti per il rendering dell'immagine.
Marcin

19
Un'osservazione interessante: le ultime versioni di Firefox, Chrome e Safari mostrano tutte un solo livello di ricorsione (due punti) utilizzando quanto sopra. Tuttavia, se si salva quanto sopra come "a.svg" e si cambia l'immagine in "b.svg", quindi la si salva anche come "b.svg" con l'immagine che fa riferimento a "a.svg", Firefox mostrerà livelli di ricorsione ogni volta che ricarichi i file alternati . Sembra memorizzare nella cache il risultato ogni volta che carichi il file, andando a un livello più profondo.
Phrogz

6
@IanStormTaylor Un elemento SVG non ha proprietà di stile in sé; piuttosto gli elementi all'interno dell'elemento SVG hanno uno stile. Tuttavia, quando si utilizza <image>in SVG (o <img>o <embed>in HTML) per fare riferimento a un file SVG non si ha accesso al DOM sottostante. In quanto tale, no, non è possibile applicare lo stile agli elementi all'interno di un elemento SVG a cui fa riferimento un file <image>.
Phrogz

2
@proteneer <image xlink:href="data:image/svg+xml;utf8,&lt;svg …&gt;… &lt;/svg&gt;" />. (Se utilizzi JavaScript per impostare l' hrefattributo, non è necessario eseguire l'escape dei <caratteri ecc.)
Phrogz

1
xlink:hrefè deprecato , ora dovresti solo usare href. Potresti aggiornare la tua risposta per includerla?
Paperino il

90

Oppure puoi effettivamente incorporare svg figlio in svg genitore in questo modo:

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

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


@toshi hai un altro esempio della tua risposta? Sto provando ma non riesco a implementare il tuo consiglio. il mio SVG "esterno" imposta un cerchio e gradienti. il mio SVG interiore è un oggetto. autonomo, l'SVG interno funziona come previsto. ma l'SVG interno non viene visualizzato nella mia implementazione del tuo consiglio. quindi, la mia richiesta di vedere un altro esempio.
Jay Grey il

40

Vale la pena ricordare che quando si incorporano SVG in un altro SVG con:

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

quindi l'SVG incorporato assume una forma rettangolare con dimensioni date.

Vale a dire, se il tuo SVG incorporato è un cerchio o una forma diversa da un quadrato, allora diventa un quadrato con trasparenza. Pertanto, gli eventi del mouse vengono intrappolati in quel quadrato incorporato e non raggiungono l'SVG genitore. Attento a questo.

Un approccio migliore è usare un pattern. Per riempire una forma, un cerchio, un quadrato o anche un percorso.

<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>

Quindi usa lo schema in questo modo:

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

Ora gli eventi del tuo mouse non rimangono bloccati in quadrati di immagini trasparenti!


Quel motivo di riempimento è perfetto, grazie. Per inserti più piccoli o viewbox più piccoli, i programmatori potrebbero voler ridurre tutta la larghezza e l'altezza in egual misura.
Steve Taylor

7

Ho scoperto che l'utilizzo del <image>tag dava un rendering di bassa qualità del file incorporato. Tuttavia, la seguente tecnica ha funzionato (per incorporare un file SVG all'interno di un file SVG, non necessariamente per il rendering su una pagina HTML):

  • Modifica il file SVG in un editor di testo.

  • Trova la fine dei metadati:

    </metadata>
      <g
       id="layer1"
       inkscape:groupmode="layer"
       inkscape:label="Layer 1">
  • Inserisci questa riga dopo il tag di gruppo:

    <use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />
  • In questo caso includiamo ALTROFILE.svg nel file e tutto il livello1 (il primo e il livello predefinito).

  • Salva questo e quindi apri il file in Inkscape.

Questa tecnica è utile per avere uno sfondo o un logo standard su ogni pagina. Inserendolo per primo nel file verrà renderizzato per primo (e quindi in fondo). Puoi anche bloccarlo aggiungendo questo attributo:

sodipodi:insensitive="true" 

In altre parole:

<use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />

@WilliamEntriken Cosa intendi per "file esterni"? Il metodo che ho descritto utilizza un file esterno, vale a dire il file con le altre cose al suo interno.
Nick Gammon

4

Avevo bisogno di incorporare un SVG nel mio SVG ma anche di cambiarne il colore e applicare le trasformazioni.

Solo Firefox supporta l'attributo "transform" sugli elementi svg nidificati. Inoltre, non è possibile modificare il colore di <image>. Quindi era necessaria una combinazione di entrambi.

Quello che ho finito per fare è stato il seguente

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

Funziona almeno su Firefox, Chrome e Inkscape.

Questo si comporta come il svg figlio nella risposta svg genitore con l'eccezione che ora puoi applicare trasformazioni su di esso.


4

Nota xlink:hrefè stata deprecata , basta usare hrefinvece, ad es

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

viewBox, widthE heightvalori (in questa risposta) sono semplicemente a scopo illustrativo, regolare il layout di conseguenza ( continua ).

Poiché <image> condivide specifiche simili a <img>, il che significa che non supporta lo stile SVG, come menzionato nella risposta di Christiaan . Ad esempio, se ho la seguente riga CSS che imposta il colore della forma SVG in modo che sia uguale al colore del carattere,

svg {
  fill: currentColor;
}

Lo stile sopra non si applicherebbe se <image>fosse usato. Per questo, è necessario utilizzare <use>, come mostrato nella risposta di Nick .

Nota id="layer1"e href="OTHERFILE.svg#layer1"valori nella sua risposta sono obbligatori .

Significa che devi aggiungere l' idattributo al file svg esterno, quindi devi ospitare il file svg esterno (modificato) da solo (il tuo sito web) o da qualche altra parte. Il file svg esterno risultante ha questo aspetto (nota dove ho inserito id):

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

Il valore di id può essere qualsiasi cosa, uso "logo" in questo esempio.

Per incorporare tale svg,

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

Se usi lo svg sopra come inline nel tuo html, non hai bisogno dell'attributo xmlns (almeno quello che so da svgo ).


1
viewBox non è obbligatorio, se lo ometti otterrai un layout diverso, in alcuni casi potrebbe essere quello che desideri. Safari ha appena iniziato a supportare href.
Robert Longson
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.