SVG Как зациклить анимацию волн

302
20 августа 2021, 23:10

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 1920 150" preserveAspectRatio="none"> 
    <path id="waves" d="M1920,150.4l-1920,0L0,17.19c0,0,111.94,45.39,145.82,48.62c65.77,6.26,159.1-57.84,225.53-57.28 
	c61.02,0.52,142.91,57.39,203.94,57.28C635.31,65.7,773,20.92,833,19.85c72.2-1.29,193.34,55.5,265.53,53.95 
	c57.97-1.25,176.24-63.16,234.24-63.94c66.09-0.89,210.02,56.01,276.12,55.95c65.42-0.06,143.53-59.13,208.29-65.27 
	C1837.43-1.38,1920,17.19,1920,17.19L1920,150.4z"> 
    <animate attributeName="d" 
        dur="2s" 
        repeatCount="indefinite" 
				values="M1920,225L0,225L0,25c0,0,111.94,68.15,145.82,73c65.77,9.41,159.1-86.84,225.53-86 
	c61.02,0.78,142.91,86.16,203.94,86C635.31,97.84,773,30.61,833,29c72.2-1.93,193.34,83.33,265.53,81 
	c57.97-1.87,176.24-94.83,234.24-96c66.09-1.33,210.02,84.1,276.12,84c65.42-0.1,143.53-88.78,208.29-98 
	C1837.43-2.88,1920,25,1920,25L1920,225z; 
M1920,150.4l-1920,0L0,17.19c0,0,71.94,55.39,105.82,58.62c65.77,6.26,223.1-63.84,289.53-63.28 
	c61.02,0.52,171.91,61.39,232.94,61.28C688.31,73.7,782,7.92,842,6.85c72.2-1.29,224.34,75.5,296.53,73.95 
	c57.97-1.25,193.24-64.16,251.24-64.94c66.09-0.89,196.02,56.01,262.12,55.95c65.42-0.06,140.53-53.13,205.29-59.27 
	c20.25-1.92,62.82,4.65,62.82,4.65L1920,150.4z; 
M1920,225L0,225L0,25c0,0,111.94,68.15,145.82,73c65.77,9.41,159.1-86.84,225.53-86 
	c61.02,0.78,142.91,86.16,203.94,86C635.31,97.84,773,30.61,833,29c72.2-1.93,193.34,83.33,265.53,81 
	c57.97-1.87,176.24-94.83,234.24-96c66.09-1.33,210.02,84.1,276.12,84c65.42-0.1,143.53-88.78,208.29-98 
	C1837.43-2.88,1920,25,1920,25L1920,225z;"/> 
    </path> 
</svg>

Вопрос заключается в том, чтобы зациклить анимацию таким образом, чтобы она шла бесконечно.

В данный момент она выполняется как бы с реверсом. Есть ли какие-нибудь способы, статьи или ещё другие возможные источники информации по правильной анимации подобного?

Волна может идти в любом направлении, - влево или вправо , главное, чтобы была бесшовность и не было такого как в данном примере, что идёт эффект "назад" (реверс). Кроме JS существуют ли способы в самом SVG создать данный эффект?

пример на JS

Answer 1

Форма анимированной волны целиком зависит от начального и конечного патча.
Чтобы не было реверса движения верхушек волн, необходимо, чтобы узловые точки по координате "X" совпадали в обоих патчах.

Это можно сделать в векторном редакторе.

Открываем в редакторе начальный патч и перемещаем узловые точки по вертикали.

Где была вершина волны должна появиться впадина

Сохраняем формулы патчей и пишем команду анимации:

values="Начальный патч; Конечный патч; Начальный патч"

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  
 viewBox="0 0 1920 150" preserveAspectRatio="none" > 
    <path id="waves" fill="dodgerblue" d="M 1920,150.4 H 0 L -1.6556647,53.97145 c 0,0 99.9646317,-38.30844 152.4426547,-39.487054 75.69431,-1.700034 146.50531,46.95496 222.21867,47.026873 68.32997,0.0649 132.31281,-40.670131 200.62868,-42.059879 C 661.27596,17.668497 745.34028,62.9697 833,62.897281 c 90.60889,-0.07485 177.4305,-47.36535 268.017,-45.350453 79.5666,1.769783 153.8269,49.412747 233.4087,50.261435 93.7352,0.999626 182.3849,-54.343391 276.12,-53.323867 72.1529,0.784782 139.8086,52.903288 211.6013,45.659532 C 1857.5889,56.5679 1920,17.19 1920,17.19 Z"> 
    <animate attributeName="d" 
        dur="1.5s"  
        repeatCount="indefinite" 
				values="M 1920,150.4 H 0 L -1.6556647,53.97145 c 0,0 99.9646317,-38.30844 152.4426547,-39.487054 75.69431,-1.700034 146.50531,46.95496 222.21867,47.026873 68.32997,0.0649 132.31281,-40.670131 200.62868,-42.059879 C 661.27596,17.668497 745.34028,62.9697 833,62.897281 c 90.60889,-0.07485 177.4305,-47.36535 268.017,-45.350453 79.5666,1.769783 153.8269,49.412747 233.4087,50.261435 93.7352,0.999626 182.3849,-54.343391 276.12,-53.323867 72.1529,0.784782 139.8086,52.903288 211.6013,45.659532 C 1857.5889,56.5679 1920,17.19 1920,17.19 Z; 
				 
M 1920,150.4 H 0 L -1.6556647,12.57983 c 0,0 95.5240937,47.94883 147.4756647,51.574505 C 223.41726,69.569811 296.87883,17.725442 374.66133,18.463988 443.12634,19.114064 506.8451,60.716884 575.29,62.498671 662.33223,64.764591 745.93193,20.646472 833,19.85 c 89.73431,-0.820862 176.627,39.903669 266.3614,39.088444 79.9749,-0.726562 156.7418,-39.233781 236.7199,-39.144456 92.765,0.103606 181.7437,48.885769 274.4644,46.016012 71.8066,-2.222457 138.5067,-56.3033082 209.9456,-48.713353 36.451,3.872694 99.5087,46.808791 99.5087,46.808791 z; 
 
M 1920,150.4 H 0 L -1.6556647,53.97145 c 0,0 99.9646317,-38.30844 152.4426547,-39.487054 75.69431,-1.700034 146.50531,46.95496 222.21867,47.026873 68.32997,0.0649 132.31281,-40.670131 200.62868,-42.059879 C 661.27596,17.668497 745.34028,62.9697 833,62.897281 c 90.60889,-0.07485 177.4305,-47.36535 268.017,-45.350453 79.5666,1.769783 153.8269,49.412747 233.4087,50.261435 93.7352,0.999626 182.3849,-54.343391 276.12,-53.323867 72.1529,0.784782 139.8086,52.903288 211.6013,45.659532 C 1857.5889,56.5679 1920,17.19 1920,17.19 Z"/> 
    </path> 
</svg>

Связанный вопрос, где более подробно, на примерах рассказано о данной технике анимации с помощью анимации атрибута d path

Answer 2

Может просто двигать волну вправо или влево? Единственное - она должна быть идеально затайлена (я создал path скриптом).

for (var i = 0; i < 5; i++) 
  wave(20 + i * 3, 70 - i * 10, 2 + 1 * Math.random(), 0.4 + i * 0.05, 40 + i * 25) 
 
function wave(amp, freq, time, scaleY, translateY) { 
  let pts = []; 
  for (var x = 0; x < 2000; x += 10) 
    pts.push([x, (Math.sin(x / freq) * amp + translateY).toFixed(1)]) 
  svg.innerHTML += `<path class="wave" d="M${pts.join('L')}v1000h-2000" 
        style="--t:${time}s;--sy:${scaleY};--tx:-${freq*2*Math.PI}px" />`; 
}
.wave { 
  fill: steelblue; 
  stroke: white; 
  opacity: 0.5; 
  stroke-width: 2px; 
  animation: wave var(--t) linear infinite; 
} 
 
@keyframes wave { 
    0% {transform: scale(1, var(--sy)) translate(0px, 0px)} 
   50% {transform:                     translate(calc(var(--tx)*0.5), 0px)} 
  100% {transform: scale(1, var(--sy)) translate(var(--tx), 0px)} 
}
<svg id=svg viewBox="0 0 1000 175" preserveAspectRatio="none"></svg>

Answer 3

Несколько волн

Чем хорош SVG, так это тем, что создав один объект можно его многократно использовать. Меняя у клонов параметры: окраску, размеры, позицию размещения и даже будет сохранена анимация у потомков от родителя.

Сохранив в секции <defs> код одной волны, будем её клонировать с помощью команды <use>

<use xlink:href="#waves" x="0" y="0" width="1920" height="150" fill="#0000C1" /> 
      <use xlink:href="#waves" x="-125" y="70" width="1920" height="150" fill="blue"/> 
        <use xlink:href="#waves" x="-250" y="150" width="1920" height="150" fill="dodgerblue"/>

Ниже полный код:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  
 width="1800" height="450" viewBox="0 0 1920 450" preserveAspectRatio="none" > 
 <defs> 
    <path id="waves"   d="M 1920,150.4 H 0 L -1.6556647,53.97145 c 0,0 99.9646317,-38.30844 152.4426547,-39.487054 75.69431,-1.700034 146.50531,46.95496 222.21867,47.026873 68.32997,0.0649 132.31281,-40.670131 200.62868,-42.059879 C 661.27596,17.668497 745.34028,62.9697 833,62.897281 c 90.60889,-0.07485 177.4305,-47.36535 268.017,-45.350453 79.5666,1.769783 153.8269,49.412747 233.4087,50.261435 93.7352,0.999626 182.3849,-54.343391 276.12,-53.323867 72.1529,0.784782 139.8086,52.903288 211.6013,45.659532 C 1857.5889,56.5679 1920,17.19 1920,17.19 Z"> 
    <animate attributeName="d" 
        dur="4s"  
        repeatCount="indefinite" 
				values=" 
        M 1920,150.4 H 0 L -1.6556647,53.97145 c 0,0 99.9646317,-38.30844 152.4426547,-39.487054 75.69431,-1.700034 146.50531,46.95496 222.21867,47.026873 68.32997,0.0649 132.31281,-40.670131 200.62868,-42.059879 C 661.27596,17.668497 745.34028,62.9697 833,62.897281 c 90.60889,-0.07485 177.4305,-47.36535 268.017,-45.350453 79.5666,1.769783 153.8269,49.412747 233.4087,50.261435 93.7352,0.999626 182.3849,-54.343391 276.12,-53.323867 72.1529,0.784782 139.8086,52.903288 211.6013,45.659532 C 1857.5889,56.5679 1920,17.19 1920,17.19 Z; 
				 
M 1920,150.4 H 0 L -1.6556647,12.57983 c 0,0 95.5240937,47.94883 147.4756647,51.574505 C 223.41726,69.569811 296.87883,17.725442 374.66133,18.463988 443.12634,19.114064 506.8451,60.716884 575.29,62.498671 662.33223,64.764591 745.93193,20.646472 833,19.85 c 89.73431,-0.820862 176.627,39.903669 266.3614,39.088444 79.9749,-0.726562 156.7418,-39.233781 236.7199,-39.144456 92.765,0.103606 181.7437,48.885769 274.4644,46.016012 71.8066,-2.222457 138.5067,-56.3033082 209.9456,-48.713353 36.451,3.872694 99.5087,46.808791 99.5087,46.808791 z; 
 
M 1920,150.4 H 0 L -1.6556647,53.97145 c 0,0 99.9646317,-38.30844 152.4426547,-39.487054 75.69431,-1.700034 146.50531,46.95496 222.21867,47.026873 68.32997,0.0649 132.31281,-40.670131 200.62868,-42.059879 C 661.27596,17.668497 745.34028,62.9697 833,62.897281 c 90.60889,-0.07485 177.4305,-47.36535 268.017,-45.350453 79.5666,1.769783 153.8269,49.412747 233.4087,50.261435 93.7352,0.999626 182.3849,-54.343391 276.12,-53.323867 72.1529,0.784782 139.8086,52.903288 211.6013,45.659532 C 1857.5889,56.5679 1920,17.19 1920,17.19 Z"/> 
    </path> 
</defs> 
	<use xlink:href="#waves" x="0" y="0" width="1920" height="150" fill="#0000C1" />  
	  <use xlink:href="#waves" x="-125" y="70" width="1920" height="150" fill="blue"/>  
	    <use xlink:href="#waves" x="-250" y="150" width="1920" height="150" fill="#0080FF" /> 
	 
</svg>

Answer 4

Ответ немного не по теме, но показать, как и в ответе @Stranger in the Q взаимодействие CSS правил и форм SVG.

Css изменяет размер волны и перемещает её.

body { 
  width: 960px; 
  height: 100%; 
  background-color: #d3d3d3; 
} 
 
 
 
#wave1 { 
  animation: popup 5s ease infinite; 
} 
 
@keyframes popup { 
  0% { 
    transform: translate( -500px, 0) scale(1, 1); 
  } 
  100% { 
    transform: translate(400px, 0) scale(1, 0); 
  } 
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="960px" height="200px" viewBox="91.43 -87.5 960 200" overflow="visible" enable-background="new 91.43 -87.5 960 200" xml:space="preserve"> 
  <path id="wave1" fill="none" stroke="#2E2925" stroke-miterlimit="10" d="M0,24.5c28.57,0,28.57-24,57.141-24c28.57,0,28.57,24,57.141,24 
	c28.572,0,28.572-24,57.142-24c28.57,0,28.57,24,57.141,24c28.572,0,28.572-24,57.143-24c28.569,0,28.569,24,57.138,24 
	c28.57,0,28.57-24,57.14-24c28.57,0,28.57,24,57.139,24s28.569-24,57.14-24c28.57,0,28.57,24,57.14,24c28.572,0,28.572-24,57.145-24 
	s28.572,24,57.145,24c28.571,0,28.571-24,57.143-24c28.572,0,28.572,24,57.145,24c28.573,0,28.573-24,57.146-24 
	c28.571,0,28.571,24,57.143,24c28.573,0,28.573-24,57.146-24c28.573,0,28.573,24,57.146,24c28.574,0,28.574-24,57.149-24 
	s28.575,24,57.149,24" /> 
</svg>

READ ALSO
Один и тот же background для header и следующей section

Один и тот же background для header и следующей section

Задача: для header и секции, следующей за ним, нужно задать один backgroundPosition:absolute; для header ситуацию не исправил

190
скругление углов для изображения

скругление углов для изображения

Сразу к делу,вот скриншот моей верстки:

127
onClick запись значения ссылки

onClick запись значения ссылки

Как сделать чтобы при выборе кода, через onclick прокидывалось значение в функцию и записывалось значение в переменную

120
Как написать функцию проверки на существование треугольника? c++

Как написать функцию проверки на существование треугольника? c++

Как написать функцию проверки на существование треугольника? Вот мой код:

280