Как я могу ссылаться на определение внутреннего градиента внутри символа SVG sprite?



резюме: SVG-спрайт содержит пять блоков значков <symbol>, один из которых ссылается на собственное определение градиента по идентификатору. Он больше не может найти этот градиент и отрисовывать его должным образом.



JSFIDDLE: http://jsfiddle.net/Qtq24/1/





Я переключаю некоторые графики на SVG, и поскольку они являются значками (в данном случае для профилей социальных сетей) ,я хотел бы сохранить их в спрайте (как это было с PNG до).



Я следовал этому руководству по SVG sprites на CSS-tricks.com (вместе с это продолжение, которое советует использовать <symbol> вместо <g>).



Теперь у меня есть файл SVG sprite, social-sprite.svg , который вы можете просмотреть полностью Здесь.



Это один полный блок <svg>, содержащий пять различных блоков <symbol>, Каждый из которых имеет атрибут id и атрибут viewBox. В каждом случае я получил код SVG для каждого символа, подготовив официальный иконки в Adobe Illustrator и сохранение соответствующих частей обработанного кода.

The .svg-файл включается через PHP, как только открывается тег <body> (и именно поэтому основной контейнер <svg> внутри него помечен style="display: none;"), так что ссылки на каждый символ работают из HTML.



Четыре иконки работают идеально, и единственная, с которой у меня возникли проблемы,-это иконка YouTube, потому что она использует внутренний градиент. Вот YouTube часть SVG код:

<symbol id="youtube" viewBox="0 0 400 281.641">
<path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/>
<path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
l13.061-6.778L159.845,81.348z"/>
<g id="Lozenge">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292">
<stop offset="0" style="stop-color:#E52D27"/>
<stop offset="1" style="stop-color:#BF171D"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
l106.152,55.384L159.863,191.73z"/>
</g>
</g>
</symbol>


И это называется в HTML с:



<svg width="30" height="21">
<use xlink:href="#youtube" src="fallback.png" width="30" height="21" />
</svg>


Открытие двух путей работает нормально, проблема в том, что в этом новом объединенном файле sprite SVG, с каждым значком, разделенным как <symbol>, "ромбик" <path> не удается найти ссылку #SVGID_1_ на <linearGradient>.



В Firefox это приводит к тому, что ромбик отображается как Белый (я предполагаю, что, возможно, он вообще не отображается - не очень смотрел в него):



firefox заполняется белым цветом



Пока Хром делает его черным:



хром заливается черным цветом



Очевидно, что ни то, ни другое не приемлемо. Единственное, что я могу сделать в данный момент, это удалить fill="url(#SVGID_1_)" на пути и просто заполнить плоским красным цветом, соответствующим логотипу YouTube. Однако это не правильное решение, даже если отбросить тот факт, что незаконное использование логотипа YouTube таким образом не будет принято в соответствии с их рекомендациями по бренду.

Вещи, которые я пробовал (и не имел успеха):




  • удаление двух <g> обертки, которые окружают градиент и путь, так что весь символ просто <path>-<path>-<linearGradient>-<path>

  • обертывание определения градиента внутри контейнера <defs>

  • обертывание его в <defs> , а также перемещение его в верхнюю часть SVG-файла, т. е. за пределы специфичного для YouTube <symbol>

  • изменение имени идентификатора (вы никогда не знаете!)

  • переопределение градиента с помощью процентов, а не значений пикселей


Так как же мне получить уже внутреннее <symbol>, чтобы ссылка на также-внутреннее определение <linearGradient>?





EDIT: оказывается, что градиент не работает, когда весь блок <svg> помечен style="display: none;". Если этот стиль удален, градиент отображается правильно. Но в качестве напоминания, этот стиль добавляется так, чтобы при импорте SVG-спрайта он не отображался мгновенно на странице, а просто позволял делать ссылки на определенные идентификаторами символы по мере необходимости.



visibility: hidden или opacity: 0 оба позволяют градиенту отрисовываться должным образом, очевидно, что они не предлагают правильных решений, хотя, поскольку они все еще разграничивают пространство, которое SVG занял бы, если бы был виден.



Обнаружив все это, я был почти уверен, что не будет проблемой иметь полностью видимый <svg> без стилизации, добавленнойвнутри контейнера <div>, который скрыт. Однако даже это приводит к тому, что градиент не отображается. Я не приблизился к решению этой проблемы.

775   2  

2 ответов:

Во-первых, обратите внимание на редактирование моего вопроса - после чего я обнаруживаю, что использование display: none для скрытия символов SVG, пока они нам не понадобятся, было проблемой.

Я продолжал возиться и остановился на этом "ответе", который далек от совершенства, но все же должен быть надежным для любой такой ситуации.

Все, что вам нужно сделать, это обернуть весь код <svg> в контейнер <div>, который должен отображаться, но никогда не повлияет на макет , поэтому я только что сделал это с помощью mega overkill CSS. как:

height: 0; width: 0; position: absolute; visibility: hidden;

И это прекрасно работает. Смотрите финальную скрипку: http://jsfiddle.net/Qtq24/5/

Если у кого-то есть лучшее решение, я хотел бы услышать его, поскольку это похоже на немного избитый способ сделать это, но я думаю, не более избитый, чем необходимость использовать display: none; в любом случае.

У вас есть две проблемы:

Не используйте style= "display: none;" в SVG. Он находится в корневом элементе <svg>. Либо visibility: hidden, height / width= "0", либо <defs> являются лучшими альтернативами.

В Firefox есть ошибка, что градиентные элементы не работают, если они находятся внутри символов. Обходной путь довольно прост, просто переместите linearGradient за пределы символа, чтобы он выглядел следующим образом...

<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="200.4204" y1="2.6162" x2="200.4204" y2="278.9292">
    <stop  offset="0" style="stop-color:#E52D27"/>
    <stop  offset="1" style="stop-color:#BF171D"/>
</linearGradient>
<symbol id="youtube" viewBox="0 0 400 281.641">
    <path id="Triangle" fill="#FFFFFF" d="M159.845,191.73l106.152-54.999L159.845,81.348V191.73z"/>
    <path id="The_Sharpness" opacity="0.12" fill-rule="evenodd" clip-rule="evenodd" fill="#420000" d="M159.845,81.348l93.091,62.162
    l13.061-6.778L159.845,81.348z"/>
    <g id="Lozenge">
        <g>
            <path fill="url(#SVGID_1_)" d="M392.928,62.226c0,0-3.839-27.073-15.617-38.995C362.371,7.583,345.626,7.506,337.947,6.59
            c-54.975-3.974-137.441-3.974-137.441-3.974h-0.171c0,0-82.464,0-137.44,3.974c-7.68,0.916-24.419,0.993-39.364,16.641
            C11.753,35.153,7.92,62.226,7.92,62.226s-3.929,31.792-3.929,63.583v29.805c0,31.791,3.929,63.582,3.929,63.582
            s3.833,27.073,15.611,38.995c14.945,15.646,34.575,15.152,43.318,16.792c31.43,3.015,133.571,3.946,133.571,3.946
            s82.552-0.124,137.526-4.099c7.679-0.915,24.424-0.993,39.363-16.64c11.778-11.922,15.617-38.995,15.617-38.995
            s3.923-31.791,3.923-63.582v-29.805C396.851,94.017,392.928,62.226,392.928,62.226z M159.863,191.73l-0.018-110.383
            l106.152,55.384L159.863,191.73z"/>
        </g>
    </g>
</symbol>

Comments

    Ничего не найдено.