Incorporar SVG em SVG?

98

Tenho um documento SVG e gostaria de incluir uma imagem SVG externa nele, ou seja, algo como:

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

("objeto" é apenas um exemplo - o documento externo será SVG em vez de xhtml).

Alguma ideia? Isso é mesmo possível? Ou é melhor simplesmente inserir o xml logo.svg em meu documento SVG externo?

Marcin
fonte

Respostas:

135

Use o imageelemento e faça referência ao seu arquivo SVG. Para se divertir, salve o seguinte como 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
fonte
3
Obrigado, por algum motivo, minha busca no Google por isso não funcionou até depois de postar essa pergunta. Observo que a largura e a altura devem estar presentes para que a imagem seja renderizada.
Marcin
19
Uma observação interessante: as versões mais recentes do Firefox, Chrome e Safari mostram apenas um nível de recursão (dois pontos) usando o acima. No entanto, se você salvar o acima como "a.svg" e alterar a imagem para "b.svg", e também salvá-lo como "b.svg" com a imagem referenciando "a.svg", o Firefox mostrará níveis de recursão para cada vez que você recarregar os arquivos alternados . Parece que o resultado é armazenado em cache cada vez que você carrega o arquivo, indo um nível mais profundo.
Phrogz,
6
@IanStormTaylor Um elemento SVG não possui propriedades de estilo; em vez disso, os itens dentro do elemento SVG têm estilo. No entanto, ao usar <image>em SVG (ou <img>ou <embed>em HTML) para fazer referência a um arquivo SVG, você não tem acesso ao DOM subjacente. Portanto, não, você não pode definir o estilo de elementos dentro de um elemento SVG que foi referenciado por um <image>.
Phrogz
2
@proteneer <image xlink:href="data:image/svg+xml;utf8,&lt;svg …&gt;… &lt;/svg&gt;" />. (Se estiver usando JavaScript para definir o hrefatributo, não é necessário escapar os <caracteres etc.)
Phrogz
1
xlink:hrefestá obsoleto , agora você deve apenas usar href. Você poderia atualizar sua resposta para incluir isso?
Pato Donald
90

Ou você pode incorporar o svg filho no svg pai assim:

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

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

toshi
fonte
@toshi você tem outro exemplo de sua resposta? Estou tentando, mas não consigo implementar seu conselho. meu SVG 'externo' define um círculo e gradientes. meu SVG interno é um objeto. autônomo, o SVG interno funciona conforme o esperado. mas o SVG interno não é exibido na minha implementação de seu conselho. daí, meu pedido para ver outro exemplo.
Jay Gray de
40

É importante mencionar que quando você incorpora SVGs em outro SVG com:

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

então, o SVG incorporado assume uma forma retangular com as dimensões fornecidas.

Ou seja, se o seu SVG incorporado for um círculo ou outra forma que não seja um quadrado, ele se tornará um quadrado com transparência. Portanto, os eventos do mouse ficam presos nesse quadrado incorporado e não alcançam o SVG pai. Cuidado com isso.

Uma abordagem melhor é usar um padrão. Para preencher uma forma, seja um círculo, um quadrado ou mesmo um caminho.

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

Em seguida, use o padrão como este:

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

Agora os eventos do mouse não ficam presos em quadrados de imagem transparentes!

oabarca
fonte
Esse padrão de preenchimento é perfeito, obrigado. Para inserções menores ou caixas de visualização menores, os codificadores podem querer reduzir toda a largura e altura na mesma medida.
Steve Taylor
7

Descobri que o uso da <image>tag gerou uma renderização de baixa qualidade do arquivo incorporado. No entanto, a seguinte técnica funcionou (para incorporar um arquivo SVG dentro de um arquivo SVG - não necessariamente para renderização em uma página HTML):

  • Edite o arquivo SVG em um editor de texto.

  • Encontre o final dos metadados:

    </metadata>
      <g
       id="layer1"
       inkscape:groupmode="layer"
       inkscape:label="Layer 1">
  • Insira esta linha após a tag de grupo:

    <use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />
  • Neste caso, estamos incluindo OTHERFILE.svg no arquivo e toda a camada 1 (a primeira camada padrão).

  • Salve e abra o arquivo no Inkscape.

Essa técnica é útil para ter um plano de fundo ou logotipo padrão em cada página. Colocando-o primeiro no arquivo, ele será renderizado primeiro (e, portanto, na parte inferior). Você também pode bloqueá-lo adicionando este atributo:

sodipodi:insensitive="true" 

Em outras palavras:

<use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />
Nick Gammon
fonte
@WilliamEntriken O que você quer dizer com "arquivos externos"? O método que descrevi usa um arquivo externo, ou seja, o arquivo com as outras coisas nele.
Nick Gammon,
4

Eu precisava incorporar um SVG em meu SVG, mas também mudar sua cor e aplicar transformações.

Apenas o Firefox suporta o atributo "transform" nos elementos svg aninhados. Alterar a cor de <imagem> também não é possível. Portanto, uma combinação de ambos era necessária.

O que acabei fazendo foi o seguinte

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

Isso funciona pelo menos no Firefox, Chrome e Inkscape.

Este se comporta da mesma forma que o svg filho na resposta svg pai, com a exceção de que agora você pode aplicar transformações nele.

Christiaan
fonte
4

Nota xlink:hreffoi descontinuada , basta usar em seu hreflugar, por exemplo

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

viewBox, widthe os heightvalores (nesta resposta) são apenas para fins ilustrativos, ajuste o layout de acordo ( leia mais ).

Desde <image> ações especificação semelhante como <img>, o que significa que não suporta SVG styling, conforme mencionado na resposta de Christiaan . Por exemplo, se eu tiver a seguinte linha css que define a cor da forma svg para ser igual à cor da fonte,

svg {
  fill: currentColor;
}

O estilo acima não se aplicaria se <image>fosse usado. Para isso, você precisa usar <use>, conforme mostrado na resposta de Nick .

Nota id="layer1"e href="OTHERFILE.svg#layer1"valores em sua resposta são obrigatórios .

Significa que você tem que adicionar o idatributo ao arquivo svg externo, então você precisa hospedar o arquivo svg externo (modificado) por você (seu site) ou em outro lugar. O arquivo svg externo resultante tem a seguinte aparência (observe onde coloquei o id):

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

O valor de id pode ser qualquer coisa, eu uso "logo" neste exemplo.

Para incorporar esse svg,

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

Se você usar o svg acima como embutido em seu html, você não precisa do atributo xmlns (pelo menos o que eu sei do svgo ).

Saftever
fonte
1
viewBox não é obrigatório, se você omiti-lo, obterá um layout diferente, mas em alguns casos pode ser o que você deseja. O Safari apenas começou a suportar href.
Robert Longson