Как анимировать css или svg градиент в SVG?

Нужно сделать эффект заполнения цветом одной буквы, как на гифке.
Кроме, как заполнить градиентом, я не придумал, как это сделать, но проблема в том, что transition не работает на linear-gradient, keyframes тоже не делает анимацию с градиентом, я решил использовать SVG анимацию, но если туда просто прописать значения градиента то он не работает, как это реализовать?

https://jsfiddle.net/morskaya_ulitochka/1k7bjwzs/17/

введите сюда описание изображения


Ответы (1 шт):

Автор решения: Alexandr_TT

Эффект достигается анимацией атрибута offset линейного градиента:

 <stop offset="0" stop-color="black">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
      </stop>

Заполнение цветом сверху-вниз

Анимация начнется после клика

#txt {
stroke:white;
stroke-width:4px;
font-size:100px;
font-weight:bold;
font-family:verdana;
text-anchor:middle;
alignment-baseline:central;
fill:url(#top_bottom);
}
<svg id="svg1"  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="300" height="300" viewBox="0 0 300 300" style="background-color:#111111" >  
 <defs>
    <linearGradient id="top_bottom" x1="0" y1="0" x2="0" y2="100%">
      <stop offset="0" stop-color="black">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
      </stop>
      <stop offset="0" stop-color="white">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
      </stop>
      
    </linearGradient>
  </defs>        

<text id="txt" x="50%" y="50%">TEXT </text>
</svg>   

Заполнение цветом слева-направо

#txt {
stroke:white;
stroke-width:4px;
font-size:100px;
font-weight:bold;
font-family:verdana;
text-anchor:middle;
alignment-baseline:central;
fill:url(#left_right);
}
<svg id="svg1"  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="300" height="300" viewBox="0 0 300 300" style="background-color:#111111" >  
 <defs>
    <linearGradient id="left_right" x1="0" y1="0" x2="100%" y2="0">
      <stop offset="0" stop-color="black">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
      </stop>
      <stop offset="0" stop-color="white">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
      </stop>
      
    </linearGradient>
  </defs>        

<text id="txt" x="50%" y="50%">TEXT </text>
</svg>   

Анимация заполнением градиентом только одной буквы

Используется теги <tspan>X</tspan>, чтобы разбить слово на буквы и применить анимацию только к одной букве

#txt {
stroke:white;
fill:white;
stroke-width:4px;
font-size:90px;
font-weight:bold;
font-family:verdana;
/*fill:url(#top_bottom);*/
}
tspan#x {
fill:url(#top_bottom);
}
<svg id="svg1"  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="300" height="300" viewBox="0 0 300 300" style="background-color:#111111" >  
 <defs>
    <linearGradient id="top_bottom" x1="0" y1="0" x2="0" y2="100%">
      <stop offset="0" stop-color="black">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1"  />
      </stop>
      <stop offset="0" stop-color="white">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1"  />
      </stop>
      
    </linearGradient>
  </defs>        

<text id="txt" x="10" y="180">
  <tspan >TE</tspan>
   <tspan id="x" dx="-20">X </taspan>
   <tspan dx="-20" fill="white">T</tspan> 

</text>
</svg>   

Бесконечное повторение repeatCount="indefinite"

#txt {
stroke:white;
fill:white;
stroke-width:4px;
font-size:90px;
font-weight:bold;
font-family:verdana;

}
tspan#x {
fill:url(#top_bottom);
}
<svg id="svg1"  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="300" height="300" viewBox="0 0 300 300" style="background-color:#111111" >  
 <defs>
    <linearGradient id="top_bottom" x1="0" y1="0" x2="0" y2="100%">
      <stop offset="0" stop-color="black">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" repeatCount="indefinite" />
      </stop>
      <stop offset="0" stop-color="white">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" repeatCount="indefinite" />
      </stop>
      
    </linearGradient>
  </defs>        

<text id="txt" x="10" y="180">
  <tspan >TE</tspan>
   <tspan id="x" dx="-20">X </taspan>
   <tspan dx="-20" fill="white">T</tspan> 

</text>
</svg>   

Вариант интересного эффекта

#txt {
stroke:white;
fill:white;
stroke-width:4px;
font-size:90px;
font-weight:bold;
font-family:verdana;

}
tspan#x {
fill:url(#top_bottom);
}
<svg id="svg1"  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="300" height="300" viewBox="0 0 300 300" style="background-color:#111111" >  
 <defs>
    <linearGradient id="top_bottom" x1="0" y1="0" x2="0" y2="100%">
      <stop offset="0" stop-color="black">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1" repeatCount="indefinite" />
      </stop>
      <stop offset="0" stop-color="white">
        <animate begin="svg1.click" dur="2s" attributeName="offset" fill="freeze" from="0" to="1"  />
      </stop>
      
    </linearGradient>
  </defs>        

<text id="txt" x="10" y="180">
  <tspan >TE</tspan>
   <tspan id="x" dx="-20">X </taspan>
   <tspan dx="-20" fill="white">T</tspan> 

</text>
</svg>   

→ Ссылка