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

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

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


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

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

теперь у меня есть файл спрайта SVG,социально-спрайт.svg, который вы можете просмотреть в полный здесь.

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

The .svg файл включается через PHP, как только <body> открывается тег (и именно поэтому main <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>

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

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

firefox fills as white

в то время как Chrome отображает его в черном цвете:

chrome fills as black

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

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

  • удаление двух <g> обертки, которые окружают градиент и путь, поэтому весь символ просто <path>-<path>-<linearGradient>-<path>
  • обертывание определения градиента внутри <defs> контейнер
  • обертывание в <defs> а также перемещение его в верхнюю часть SVG-файла, т. е. за пределы Специфичный для YouTube <symbol>
  • изменение имени ID (вы никогда не знаете!)
  • переопределение градиента с процентами, а не значениями пикселей

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


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

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

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

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> элемент. Либо видимость: скрытая, высота / ширина= " 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>