Как анимировать радиальный градиент с помощью CSS?

122
01 мая 2021, 05:00

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

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

Большинство примеров, которые я нашел, выглядит так: http://jsfiddle.net/nqQc7/512/.

Ниже то, что у меня пока получилось:

#shine-div { 
  height: 30vh; 
  width: 60vw; 
  margin-right: auto; 
  margin-left: auto; 
  border-radius: 10px; 
  /*background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);*/ 
  display: flex; 
  justify-content: center; 
  align-items: center; 
  color: white; 
  font-weight: bold; 
  animation: colorChange 5s infinite; 
} 
 
@keyframes colorChange { 
  0% { 
    background: radial-gradient(ellipse farthest-corner at left top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%) 
  } 
  50% { 
    background: radial-gradient(ellipse farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%) 
  } 
  100% { 
    background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%) 
  } 
  /*0% { transform: translateY(-20vh) translateX(-7vw) ; opacity: 0;  }*/ 
  /*10% { transform: translateY(-20vh) translateX(-7vw) ; opacity: 1;  }*/ 
  /*40% { transform: translateY(-20vh) translateX(17vw) ; opacity: 1; }*/ 
  /*50% { transform: translateY(-20vh) translateX(17vw) ; opacity: 0; }*/ 
  /*60% { transform: translateY(-20vh) translateX(17vw) ; opacity: 1; }*/ 
  /*90% { transform: translateY(-20vh) translateX(-7vw) ; opacity: 1; }*/ 
  /*100% { transform: translateY(-20vh) translateX(-7vw) ; opacity: 0; }*/ 
}
<div id="shine-div"> 
  Shine 
</div>

Возможно ли и как, заставить белый блеск сверху плавно переходить слева направо?

Answer 1

Вы можете сделать градиент по-разному и анимировать его позицию. Хитрость состоит в том, чтобы удвоить размер градиента и сделать так, чтобы значение stop-color составляло половину их фактических значений, чтобы сохранить тот же визуальный градиент, а затем анимировать его слева направо.

  • Он не будет выглядеть точно так же, как градиент, который вы определили в анимации из-за вычисления дальнего угла

    #shine-div { 
      height: 30vh; 
      width: 60vw; 
      margin-right: auto; 
      margin-left: auto; 
      border-radius: 10px; 
      background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%) top right/200% 200%; 
      display: flex; 
      justify-content: center; 
      align-items: center; 
      color: white; 
      font-weight: bold; 
      animation: colorChange 5s infinite alternate; 
    } 
     
    @keyframes colorChange { 
      to { 
        background-position:top left; 
      } 
    }
    <div id="shine-div"> 
      Shine 
    </div>

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

    #shine-div { 
      height: 30vh; 
      width: 60vw; 
      margin-right: auto; 
      margin-left: auto; 
      border-radius: 10px; 
      background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%) top right/400% 200%; 
      display: flex; 
      justify-content: center; 
      align-items: center; 
      color: white; 
      font-weight: bold; 
      animation: colorChange 5s infinite alternate linear; 
    } 
     
    @keyframes colorChange { 
      from { 
        background-position:top 0 left 33%; 
        background-size:400% 200%; 
       
      } 
      50% { 
        background-position:top center; 
        background-size:200% 200%; 
      } 
      to { 
        background-position:top 0 right 33%; 
        background-size:400% 200%; 
      } 
    }
    <div id="shine-div"> 
      Shine 
    </div>

  • Вы также можете сделать ту же анимацию с учетом псевдоэлемента и transform, чтобы иметь лучшую производительность:

    #shine-div { 
      height: 30vh; 
      width: 60vw; 
      margin-right: auto; 
      margin-left: auto; 
      border-radius: 10px; 
      display: flex; 
      justify-content: center; 
      align-items: center; 
      color: white; 
      font-weight: bold; 
      overflow:hidden; 
      position:relative; 
      z-index:0; 
    } 
    #shine-div:before { 
      content:""; 
      position:absolute; 
      z-index:-1; 
      top:0; 
      left:0; 
      width:400%; 
      height:200%; 
      background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%); 
      animation: colorChange 5s infinite alternate linear; 
    } 
     
    @keyframes colorChange { 
      from { 
        transform:translateX(-50%); 
      } 
      50% { 
        transform:scaleX(0.75) translateX(-50%) 
      } 
      to { 
        transform:translateX(-25%); 
      } 
     }
    <div id="shine-div"> 
      Shine 
    </div>

Answer 2

Решение SVG

Все фильтры, градиенты, маски, клипы пришли в CSS из SVG. Поэтому необходимо добавить решение c SVG градиентами.

Всё в принципе повторю из css решения, те же цвета в stop-color, те же проценты в stop offset, но анимация получается более мощной и зрелищной.

Горизонтальное перемещение градиента

Анимация достигается изменением значения параметра fx радиального градиента, отвечающего за горизонтальную координату центра градиента.

Запуск анимации - клик по прямоугольнику

<div id="shine-div"> 
   
  <svg xmlns="http://www.w3.org/2000/svg"  
    xmlns:xlink="http://www.w3.org/1999/xlink" width="400"  height="100" viewBox="0 0 400 100"> 
   <defs> 
   <radialGradient id="radGrad"  fx="0%" fy="5%" r="200%" 
           > 
     <stop offset="0%" stop-color ="#FFFFFF" /> 
	  <stop offset="4%" stop-color ="#ffb3ff" /> 
	   <stop offset="12.25%" stop-color ="#ff33ff" /> 
	    <stop offset="31.25%" stop-color ="#800080" /> 
	     <stop offset="50%" stop-color ="#b300b3" />  
		  
   </radialGradient> 
   </defs>  
    <g id="gr1" >  
   <rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"  />  
      <text x="50%" y="60%" font-size="28px"  text-anchor="middle" font-weight="bold" font-family="sans-serif" fill="#FFDD00" > Sun shine </text> 
	</g>   
    <animate xlink:href="#radGrad" 
	  attributeName="fx" 
	  dur="2s"begin="gr1.click" 
	  values="0%;50%;50%;100%;0%" 
	  repeatCount="1" 
	  restart="whenNotActive" /> 
  </svg> 
</div>

Атрибут keyTimes обеспечивает неравномерность движения, количество значений должно равняться количеству значений в атрибуте values Подробнее здесь.

  values="0%;50%;50%;100%;0%"
keyTimes="0;0.1;0.5;0.9;1"

Вертикальная анимация градиента

В этом случае анимируется fy

<div id="shine-div"> 
   
  <svg xmlns="http://www.w3.org/2000/svg"  
    xmlns:xlink="http://www.w3.org/1999/xlink" width="400"  height="100" viewBox="0 0 400 100"> 
   <defs> 
   <radialGradient id="radGrad"  fx="48%" fy="0%" r="200%" 
           > 
     <stop offset="0%" stop-color ="#FFFFFF" /> 
	  <stop offset="3%" stop-color ="#ffb3ff" /> 
	  <stop offset="12.25%" stop-color ="#ff33ff" /> 
	  <stop offset="31.25%" stop-color ="#800080" /> 
	    <stop offset="50%" stop-color ="#b300b3" />  
		  
   </radialGradient> 
   </defs>  
    <g id="gr1" >  
   <rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"  />  
      <text x="50%" y="60%" font-size="28px"  text-anchor="middle" font-weight="bold" font-family="sans-serif" fill="#FFDD00" > Sun shine </text> 
	</g>   
    <animate xlink:href="#radGrad" 
	  attributeName="fy" 
	  dur="2s"begin="gr1.click" 
	  values="0%;50%;50%;100%;50%;50%;0%" 
	  repeatCount="1" 
	  restart="whenNotActive" /> 
  </svg> 
</div>

Анимация по диагонали

Анимируются одновременно оба параметра fx, fy

<div id="shine-div"> 
   
  <svg xmlns="http://www.w3.org/2000/svg"  
    xmlns:xlink="http://www.w3.org/1999/xlink" width="400"  height="100" viewBox="0 0 400 100"> 
   <defs> 
   <radialGradient id="radGrad"  fx="0%" fy="0%" r="200%"> 
     <stop offset="0%" stop-color ="#FFFFFF" /> 
	  <stop offset="3%" stop-color ="#ffb3ff" /> 
	  <stop offset="12.25%" stop-color ="#ff33ff" /> 
	  <stop offset="31.25%" stop-color ="#800080" /> 
	  <stop offset="50%" stop-color ="#b300b3" />  
		  
   </radialGradient> 
   </defs>  
    <g id="gr1" >  
   <rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"  />  
      <text x="50%" y="60%" font-size="28px"  text-anchor="middle" font-weight="bold" font-family="sans-serif" fill="#FFDD00" > Sun shine </text> 
	</g>   
    <animate xlink:href="#radGrad" 
	  attributeName="fy" 
	  dur="2s"begin="gr1.click" 
	  values="0%;50%;50%;100%;50%;50%;0%" 
	  repeatCount="1" 
	  restart="whenNotActive" /> 
	     <animate xlink:href="#radGrad" 
	  attributeName="fx" 
	  dur="2s"begin="gr1.click" 
	  values="0%;50%;50%;100%;50%;50%;0%" 
	   repeatCount="1" 
	  restart="whenNotActive" /> 
  </svg> 
</div>

Анимация по наведению курсора

Условие запуска анимации: begin="rect1.mouseover"

<style> 
  
</style> 
<div id="shine-div"> 
   
  <svg xmlns="http://www.w3.org/2000/svg"  
    xmlns:xlink="http://www.w3.org/1999/xlink" width="400"  height="100" viewBox="0 0 400 100"> 
   <defs> 
   <radialGradient id="radGrad"  fx="0%" fy="5%" r="200%" 
           > 
     <stop offset="0%" stop-color ="#FFFFFF" /> 
	  <stop offset="4%" stop-color ="#ffb3ff" /> 
	  <stop offset="12.25%" stop-color ="#ff33ff" /> 
	  <stop offset="31.25%" stop-color ="#800080" /> 
	  <stop offset="50%" stop-color ="#b300b3" />  
		  
   </radialGradient> 
   </defs>  
    <g id="gr1" >  
   <rect id="rect1" fill="url(#radGrad)" x="5%" y="5%" width="95%" height="95%" rx="10%"  />  
      <text x="50%" y="60%" font-size="28px"  text-anchor="middle" font-weight="bold" font-family="sans-serif" fill="#FFDD00" > Sun shine </text> 
	</g>   
    <animate xlink:href="#radGrad" 
	  attributeName="fx" 
	  dur="1s" 
	  begin="rect1.mouseover" 
	   values="0%;100%;0%" 
	   repeatCount="1" 
     fill="freeze" 
	   /> 
  </svg> 
</div>

READ ALSO
Создание копий при возвращении из функции

Создание копий при возвращении из функции

Всё глубже и глубже погружаясь в C++, я начинаю немного сходить с ума, виной этому то, что некоторые вещи я просто не могу объяснить, а заучивать...

125
Glfw С++ Ввод русского текста с клавиатуры

Glfw С++ Ввод русского текста с клавиатуры

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

139
Несколько вопросов по указателям в С++

Несколько вопросов по указателям в С++

Возникло несколько вопросов связанных с raw pointers в С++Рассмотрим следующий код

103
Чем открыть проект .cbproj?

Чем открыть проект .cbproj?

Достался проект с расширениемcbproj

105