Подтвердить что ты не робот

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

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

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


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

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

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

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

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

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

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

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

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

firefox fills as white

в то время как Chrome делает его черным:

chrome fills as black

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

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

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

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


РЕДАКТИРОВАТЬ: Оказывается, градиент не работает, когда весь блок <svg> помечен style="display: none;". Если этот стиль удален, градиент отобразится правильно. Но в качестве напоминания этот стиль добавляется так, что при импорте спрайта SVG он не отображается мгновенно на странице и просто позволяет вам ссылаться на определенные символом символы по мере необходимости.

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

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