Вставить SVG в SVG?

102

У меня есть документ SVG, и я хотел бы включить в него внешнее изображение svg, то есть что-то вроде:

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

(«объект» - это просто пример - внешний документ будет в формате SVG, а не в формате xhtml).

Любые идеи? Это вообще возможно? Или мне лучше всего просто вставить xml logo.svg в мой внешний SVG-документ?

Марчин
источник

Ответы:

138

Используйте imageэлемент и укажите ссылку на свой файл SVG. Для удовольствия сохраните следующее как 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
источник
3
Спасибо, по какой-то причине мой поиск в Google не работал до тех пор, пока я не опубликовал этот вопрос. Замечу, что для рендеринга изображения должны быть указаны ширина и высота.
Marcin
20
Одно интересное наблюдение: все последние версии Firefox, Chrome и Safari показывают только один уровень рекурсии (две точки), используя вышеизложенное. Однако, если вы сохраните указанное выше как «a.svg» и измените изображение на «b.svg», а затем также сохраните его как «b.svg» с изображением, ссылающимся на «a.svg», Firefox покажет дополнительные уровни рекурсии при каждой перезагрузке чередующихся файлов . Кажется, что результат кешируется каждый раз, когда вы загружаете файл, переходя на один уровень глубже.
Phrogz
6
@IanStormTaylor Сам элемент SVG не имеет свойств стиля; скорее, элементы внутри элемента SVG имеют стиль. Однако при использовании <image>в SVG (или <img>или <embed>в HTML) для ссылки на файл SVG вам не предоставляется доступ к базовой DOM. Таким образом, нет, вы не можете стилизовать элементы внутри элемента SVG, на который ссылается <image>.
Phrogz
2
@proteneer <image xlink:href="data:image/svg+xml;utf8,&lt;svg …&gt;… &lt;/svg&gt;" />. (Если вы используете JavaScript для установки hrefатрибута, вам не нужно экранировать <символы и т. Д.)
Phrogz
1
xlink:hrefустарел , теперь вам нужно просто использовать href. Не могли бы вы обновить свой ответ, включив это?
Дональд Дак,
93

Или вы можете фактически встроить дочерний svg в родительский svg следующим образом:

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

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

тоши
источник
@toshi у вас есть другой пример вашего ответа? Я пытаюсь, но не могу выполнить ваш совет. мой «внешний» SVG задает круг и градиенты. мой внутренний SVG - это объект. автономно, внутренний SVG работает должным образом. но внутренний SVG не отображается в моей реализации вашего совета. следовательно, я прошу увидеть еще один пример.
Джей Грей
+1 за упоминание автономной альтернативы. Как работает позиционирование / размер такого встроенного SVG?
bluenote10
41

Стоит упомянуть, что при встраивании SVG в другой SVG с помощью:

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

тогда встроенный SVG принимает прямоугольную форму с заданными размерами.

То есть, если ваш встроенный SVG представляет собой круг или некоторую форму, отличную от квадрата, тогда он становится квадратом с прозрачностью. Следовательно, события мыши попадают в этот встроенный квадрат и не достигают родительского SVG. Остерегайтесь этого.

Лучше использовать шаблон. Чтобы заполнить фигуру: круг, квадрат или даже путь.

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

Затем используйте такой шаблон:

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

Теперь события мыши не застревают в прозрачных квадратах изображения!

Oabarca
источник
Этот узор заливки идеален, спасибо. Для меньших вставок или меньших окон просмотра кодировщики могут захотеть уменьшить всю ширину и высоту в равной мере.
Стив Тейлор
7

Я обнаружил, что использование <image>тега приводит к некачественной визуализации встроенного файла. Однако сработал следующий метод (для встраивания файла SVG в файл SVG - не обязательно для рендеринга на странице HTML):

  • Отредактируйте файл SVG в текстовом редакторе.

  • Найдите конец метаданных:

    </metadata>
      <g
       id="layer1"
       inkscape:groupmode="layer"
       inkscape:label="Layer 1">
    
  • Вставьте эту строку после этого тега группы:

    <use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />
    
  • В этом случае мы включаем в файл OTHERFILE.svg и весь слой layer1 (первый слой по умолчанию).

  • Сохраните это, а затем откройте файл в Inkscape.

Этот метод полезен, если на каждой странице есть стандартный фон или логотип. Если поместить его первым в файл, он будет отображаться первым (и, следовательно, внизу). Вы также можете заблокировать его, добавив этот атрибут:

sodipodi:insensitive="true" 

Другими словами:

<use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />
Ник Гаммон
источник
@WilliamEntriken Что вы имеете в виду под «внешними файлами»? В описанном мной методе используется внешний файл, а именно файл с остальным содержимым.
Ник Гаммон,
6

Примечание xlink:hrefбыло устаревшим , просто использовать hrefвместо этого, например ,

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

viewBox, widthа heightзначения (в этом ответе) приведены просто для иллюстрации, соответственно настройте макет ( подробнее ).

Поскольку <image> акции аналогичной спецификации , как <img>, имея в виду , что не поддерживает SVG стиль, как указано в ответе Христианом в . Например, если у меня есть следующая строка css, в которой цвет формы svg устанавливается таким же, как цвет шрифта,

svg {
  fill: currentColor;
}

Приведенный выше стиль не будет применяться, если <image>он используется. Для этого вам нужно использовать <use>, как показано в ответе Ника .

Примечание id="layer1"и href="OTHERFILE.svg#layer1"значения в его ответе обязательны .

Это означает, что вам нужно добавить idатрибут во внешний файл svg, поэтому вам нужно разместить (измененный) внешний файл svg самостоятельно (на своем веб-сайте) или где-то еще. Результирующий внешний файл svg выглядит так (обратите внимание, где я поместил id):

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

Значение id может быть любым, в этом примере я использую «логотип».

Чтобы встроить этот SVG,

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

Если вы используете указанный выше svg как встроенный в свой html, вам не нужен атрибут xmlns (по крайней мере, то, что я знаю из svgo ).

Saftever
источник
1
viewBox не является обязательным, если вы его опустите, вы получите другой макет, хотя в некоторых случаях это может быть то, что вам нужно. Safari только-только начал поддерживать href.
Роберт Лонгсон
4

Мне нужно было встроить SVG в свой SVG, но также изменить его цвет и применить преобразования.

Только Firefox поддерживает атрибут "transform" для вложенных элементов svg. Также невозможно изменить цвет <image>. Так что было необходимо сочетание того и другого.

В итоге я сделал следующее

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

Это работает как минимум в Firefox, Chrome и Inkscape.

Это ведет себя так же, как дочерний svg в ответе родительского svg, за исключением того, что теперь вы можете применять к нему преобразования.

Христианский
источник