SVG модифицирует градиент для элемента, который повторно используется с помощью «use» - PullRequest
3 голосов
/ 10 июня 2019

Я использую простой SVG треугольный путь, который заливка редактируется через CSS с использованием ссылки на SVG Gradient .

SVG:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <linearGradient id="gradient">
        <stop offset="0%" />
        <stop offset="100%" />
      </linearGradient>
    <polygon id="triangle" points="0,0 100,0 0,66" />     
</svg>

CSS:

#triangle {
  fill: url(#gradient);
}

Чтобы получить немного больше свободы с цветами , используемыми в градиенте, и получить цвета из разметки Я выбралиспользовать CSS пользовательские свойства (иначе переменные CSS)

CSS:

#gradient stop:first-child {
    stop-color: var(--color-stop);
}
#gradient stop {
    stop-color: var(--color-stop2);
}

Софар настолько хорош, проблема в том, что я хочу повторно используйте эту треугольную форму и придайте ей другой цвет. Перезапись переменных CSS не имеет никакого эффекта! https://codepen.io/Type-Style/pen/gNYpjL

// nothing in js this time
svg {width: 250px; height:200px;}
:root {
  --color-stop: orange;
  --color-stop2: red;
}
.second { /* has no effect */
	 --color-stop: lime;
 	 --color-stop2: green;	
}

#gradient stop:first-child {
	stop-color: var(--color-stop);
}
#gradient stop {
	stop-color: var(--color-stop2);
}

#triangle {
  fill: url(#gradient);
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <linearGradient id="gradient">
        <stop offset="0%" />
        <stop offset="100%" />
      </linearGradient>
    <polygon id="triangle" points="0,0 100,0 0,66" />	  
</svg>
<svg class="second" viewBox="0 0 100 100">
	<use class="use-triangle" href="#triangle" />
</svg>

Ожидаемый результат:

Я хотел, чтобы второй треугольник был окрашен другим способом.


Результат:

Но мне кажется, что после использования градиента его невозможно изменить / перезаписать.Такое ощущение, что градиент принимает только то значение, которое ему непосредственно присвоено, и которое нельзя изменить после его использования.Это может быть связано с характером использования заполнения, ссылающегося на идентификатор, но я не уверен


Что я пробовал / кредит:

Я проверил SVG-градиент, используя CSS , где я получил и изменил пример.(Thx to @ Maciej-Kwas)

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


Неудовлетворительный обходной путь:

Так как моя цель - сохранить цвета снаружиразметки я мог бы переместить svg в строку css в качестве data-Uri, примерно так:

fill: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><linearGradient id='grad'><stop offset='0%' stop-color='%23ff00cc'/><stop offset='100%' stop-color='%23333399'/></linearGradient></svg>#grad")

Большой кредит за статью об этом: https://fvsch.com/svg-gradient-fill/

Но так как этоработает только в Firefox и кажется хакерским.


Заключительные мысли:

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

Ответы [ 2 ]

2 голосов
/ 10 июня 2019

Я не уверен, что вы ищете универсальное решение, но для этого конкретного случая вы можете сделать тот же эффект, используя чистый CSS.

Приведенный ниже прием работает нормально, поскольку направление градиента является горизонтальным:

:root {
  --c1: orange;
  --c2: red;
}

.second {
  --c1: lime;
  --c2: green;
}

.triangle {
  width: 200px;
  height: 132px;
  display: inline-block;
  overflow: hidden;
  position: relative;
}

.triangle:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(to right, var(--c1), var(--c2));
  transform: skewY(-33.42deg); /* arctan(132/200)*/
  transform-origin: left;
}
<div class="triangle">

</div>

<div class="triangle second">

</div>

Вы также можете рассмотреть clip-path, где будет легче определить любой вид градиента, но вы должны обратить внимание на поддержку браузера.Вы также можете заметить, что синтаксис многоугольника почти аналогичен синтаксису SVG, поэтому вы также можете рассмотреть любую форму.

:root {
  --c1: orange;
  --c2: red;
}

.second {
  --c1: lime;
  --c2: green;
}

.triangle {
  width: 200px;
  height: 132px;
  display: inline-block;
  background: linear-gradient(65deg, var(--c1), var(--c2));
  -webkit-clip-path:polygon(0 0,100% 0,0 100%);
  clip-path:polygon(0 0,100% 0,0 100%);
}
<div class="triangle">

</div>

<div class="triangle second">

</div>
1 голос
/ 10 июня 2019

Два наблюдения:

  1. Вам нужно определить 2 градиента и выбрать, какой из них с переменной: fill: var(--grd);

  2. Вы не 'Заполните <polygon>, что вам нужно использовать повторно.Вы заполняете элемент <use>.

Надеюсь, это поможет.

svg {width: 250px; height:200px;border:1px solid}
:root {
  --grd: url(#gradient);
}
.second{--grd: url(#gradient2);}

use {
  fill: var(--grd);
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"> 
	<defs>
	   <linearGradient id="gradient">
        <stop offset="0%" stop-color="orange"/>
        <stop offset="100%" stop-color="red" />
      </linearGradient>
	  <linearGradient id="gradient2">
        <stop offset="0%" stop-color="lime"/>
        <stop offset="100%" stop-color="green" />
      </linearGradient>
    <polygon id="triangle" points="0,0 100,0 0,66" />	 
	</defs>
	
	<use class="use-triangle" xlink:href="#triangle" />
</svg>
<svg class="second" viewBox="0 0 100 100">
	<use class="use-triangle" xlink:href="#triangle" />
</svg>
...