Как я могу изменить CSS-анимацию с помощью переменной, заданной в typescript

#css #typescript #animation

Вопрос:

У меня есть много отдельных анимаций для разных элементов, которые все делают одно и то же, только с другим цветом. В моем файле .ts у меня есть переменная this.fillColor, которая содержит значение RGB выбранного элемента. Есть ли способ сократить анимацию до 1 блока кода и изменить жестко заданное значение RGB на эту переменную?

 #loading {
    animation-name:             changing;
    animation-duration:         4s;
    animation-direction:        alternate;
    animation-iteration-count:  infinite;
  }

  @keyframes changing {
      0% {
          fill:rgb(105,105,105);
          width: 20px;
      }
      100% {
          fill: rgb(250,230,0);
          width: 200px;
      }
  }

  #loading2 {
    animation-name:             changing2;
    animation-duration:         4s;
    animation-direction:        alternate;
    animation-iteration-count:  infinite;
  }

  @keyframes changing2 {
      0% {
          fill:rgb(105,105,105);
          width: 20px;
      }
      100% {
          fill: rgb(13,255,191);
          width: 200px;
      }
  }
 

Ответ №1:

Вы можете просто использовать переменные CSS/пользовательские свойства, чтобы сделать это за вас. Второй аргумент в var() принимает запасное значение/значение по умолчанию, в случае, если переменная CSS не определена.

Например, если вы хотите задать #loading начальный и конечный цвета заливки для пользовательского значения, вы можете сделать это:

 @keyframes changing {
    0% {
        fill: var(--loading-fill-from, rgb(105,105,105));
        width: 20px;
    }
    100% {
        fill: var(--loading-fill-to, rgb(250,230,0));
        width: 200px;
    }
}
 

Это означает, что changing ключевой кадр будет иметь резервные цвета по умолчанию rgb(105, 105, 105) для начала и rgb(250, 230, 0) для конца, но также принимает --loading-fill-from и --loading-fill-to пользовательские свойства, если они указаны.

Вы можете установить их в корневом элементе, так как пользовательские свойства CSS наследуются:

 document.documentElement.style.setProperty('--loading-fill-from', YOUR_COLOR_HERE);
 

Ниже приведен пример, подтверждающий концепцию (написан на ES6 JS, но вы можете легко просто преобразовать его в машинописный текст самостоятельно).:

 const varNames = ['loading-fill-from', 'loading-fill-to', 'loading2-fill-from', 'loading2-fill-to'];
document.querySelector('#btn').addEventListener('click', () => {
  for (let varName of varNames) {
    document.documentElement.style.setProperty(`--${varName}`, document.querySelector(`#${varName}`).value);
  }
}); 
 #loading {
    animation-name:             changing;
    animation-duration:         4s;
    animation-direction:        alternate;
    animation-iteration-count:  infinite;
  }

  @keyframes changing {
      0% {
          fill: var(--loading-fill-from, rgb(105,105,105));
          width: 20px;
      }
      100% {
          fill: var(--loading-fill-to, rgb(250,230,0));
          width: 200px;
      }
  }

  #loading2 {
    animation-name:             changing2;
    animation-duration:         4s;
    animation-direction:        alternate;
    animation-iteration-count:  infinite;
  }

  @keyframes changing2 {
      0% {
          fill: var(---loading2-fill-from, rgb(105,105,105));
          width: 20px;
      }
      100% {
          fill: var(--loading2-fill-to, rgb(13,255,191));
          width: 200px;
      }
  } 
 <form>
  <fieldset>
    <legend>#loading</legend>
    <label>
      Loading button fill from:
      <input type="color" id="loading-fill-from" value="#005f73"/>
    </label>
    <label>
      Loading button fill to:
      <input type="color" id="loading-fill-to" value="#94d2bd" />
    </label>
  </fieldset>
  <fieldset>
    <legend>#loading2</legend>
    <label>
      Loading2 button fill from:
      <input type="color" id="loading2-fill-from" value="#f07167" />
    </label>
    <label>
      Loading2 button fill to:
      <input type="color" id="loading2-fill-to" value="#fed9b7" />
    </label>
  </fieldset>
  <button type="button" id="btn">Change color</button>
</form>

<svg id="loading" viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" /></svg>

<svg id="loading2" viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" /></svg>