Создание реалистичной c (синусоидальной) флаговой анимации / трепетания с помощью SVG - PullRequest
2 голосов
/ 01 февраля 2020

Я пытаюсь сделать более реалистичным c анимированный svg флаг, который развевается на ветру. Это простая база флагов, которую я сейчас использую:

<svg
  xmlns="http://www.w3.org/2000/svg"
  width="200px"
  height="100px"
  viewBox="0 0 200 100"
>
  <path
    fill="red"
    d=
    "
      M 20,20
      Q 25,10 50,20
      T 80,20
      L 80,80
      Q 75,90 50,80
      T 20,80
      z
    "
  >
    <animate
      dur="1.8s"
      attributeName="d"
      fill="freeze"
      repeatCount="indefinite"
      values=
      "
        M 20,20
        Q 25,10 50,20
        T 80,20
        L 80,80
        Q 75,90 50,80
        T 20,80
        z;

        M 20,30
        Q 35,30 50,20
        T 80,20
        L 80,80
        Q 65,70 50,80
        T 20,90
        z;

        M 20,20
        Q 25,10 50,20
        T 80,20
        L 80,80
        Q 75,90 50,80
        T 20,80
        z;
      "
      calcMode="spline"
      keySplines="0,0,.58,1; 0,0,.58,1"
    />
  </path>
  <line x1="50" y1="35" x2="50" y2="65" stroke="#fff" stroke-width="10" />
  <line x1="35" y1="50" x2="65" y2="50" stroke="#fff" stroke-width="10" />
</svg>

Как видите, я нарисовал квадрат с дополнительной средней точкой вдоль верхнего и нижнего края. Чтобы оживить мой текущий флаг, я перемещаю угловые точки левого края и кривизну средних точек, однако это не дает очень хорошего «поведения флага».

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

1 Ответ

3 голосов
/ 02 февраля 2020

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

Я думаю, что наилучшим подходом будет программная генерация данных пути с использованием гораздо большего количества контрольных точек и намного больше ключевых кадров. Вот программа, которую я сделал в Python (v2) для демонстрации:

def flag_transform(x, y, t, a):
    from math import sin, pi
    freq = 1.0
    theta = (x * freq - t) * 2 * pi
    amp = a * x
    return (x, y+amp*sin(theta))

def flag_svg(nframes):
    x0 = y0 = 20
    w = h = 160
    amp = 10.0
    frames = []
    for i in range(nframes):
        s = 'M%.1f %.1f' % (x0,y0)
        for x in range(1,11):
            (fx1,fy1) = flag_transform(x*0.1-.05,0,i*1.0/nframes,amp)
            ax = fx1 * w + x0
            ay = fy1 + y0
            (fx2,fy2) = flag_transform(x*0.1,0,i*1.0/nframes,amp)
            bx = fx2 * w + x0
            by = fy2 + y0
            s += 'Q%.1f %.1f %.1f %.1f' % (ax,ay,bx,by)
        by += h
        s += 'L%.1f %.1f' % (bx,by)
        for x in range(9,-1,-1):
            (fx1,fy1) = flag_transform(x*0.1+.05,0,i*1.0/nframes,amp)
            ax = fx1 * w + x0
            ay = fy1 + y0 + h
            (fx2,fy2) = flag_transform(x*0.1,0,i*1.0/nframes,amp)
            bx = fx2 * w + x0
            by = fy2 + y0 + h
            s += 'Q%.1f %.1f %.1f %.1f' % (ax,ay,bx,by)
        s += 'Z'
        frames.append(s.replace('.0',''))
    #
    frames.append(frames[0])
    print '<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px" viewBox="0 0 200 200">'
    print '<path fill="red" d="' + frames[0] + '">'
    print '<animate dur="1.8s" attributeName="d" fill="freeze" repeatCount="indefinite" values="'
    print ';\n'.join(frames)
    print '"/>'
    print '</path>'
    print '</svg>'

flag_svg(10)

А вот и результат. Если вы пытаетесь смоделировать швейцарский флаг, вы можете добавить белый крест в середине точно таким же образом. Используйте квадратичные c кривые (Q) для горизонтальных линий и прямые (L) для вертикальных линий.

<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px" viewBox="0 0 200 200">
<path fill="red" d="M20 20Q28 20.2 36 20.6Q44 21.2 52 21.9Q60 22.5 68 22.9Q76 22.8 84 22.4Q92 21.4 100 20Q108 18.3 116 16.5Q124 14.7 132 13.3Q140 12.5 148 12.4Q156 13.1 164 14.7Q172 17.1 180 20L180 180Q172 177.1 164 174.7Q156 173.1 148 172.4Q140 172.5 132 173.3Q124 174.7 116 176.5Q108 178.3 100 180Q92 181.4 84 182.4Q76 182.8 68 182.9Q60 182.5 52 181.9Q44 181.2 36 180.6Q28 180.2 20 180Z">
<animate dur="1.8s" attributeName="d" fill="freeze" repeatCount="indefinite" values="
M20 20Q28 20.2 36 20.6Q44 21.2 52 21.9Q60 22.5 68 22.9Q76 22.8 84 22.4Q92 21.4 100 20Q108 18.3 116 16.5Q124 14.7 132 13.3Q140 12.5 148 12.4Q156 13.1 164 14.7Q172 17.1 180 20L180 180Q172 177.1 164 174.7Q156 173.1 148 172.4Q140 172.5 132 173.3Q124 174.7 116 176.5Q108 178.3 100 180Q92 181.4 84 182.4Q76 182.8 68 182.9Q60 182.5 52 181.9Q44 181.2 36 180.6Q28 180.2 20 180Z;
M20 20Q28 19.8 36 20Q44 20.5 52 21.2Q60 22 68 22.9Q76 23.5 84 23.8Q92 23.6 100 22.9Q108 21.7 116 20Q124 18 132 15.9Q140 13.9 148 12.4Q156 11.5 164 11.4Q172 12.3 180 14.1L180 174.1Q172 172.3 164 171.4Q156 171.5 148 172.4Q140 173.9 132 175.9Q124 178 116 180Q108 181.7 100 182.9Q92 183.6 84 183.8Q76 183.5 68 182.9Q60 182 52 181.2Q44 180.5 36 180Q28 179.8 20 180Z;
M20 20Q28 19.6 36 19.4Q44 19.5 52 20Q60 20.8 68 21.8Q76 22.8 84 23.8Q92 24.5 100 24.8Q108 24.4 116 23.5Q124 22 132 20Q140 17.7 148 15.3Q156 13.1 164 11.4Q172 10.5 180 10.5L180 170.5Q172 170.5 164 171.4Q156 173.1 148 175.3Q140 177.7 132 180Q124 182 116 183.5Q108 184.4 100 184.8Q92 184.5 84 183.8Q76 182.8 68 181.8Q60 180.8 52 180Q44 179.5 36 179.4Q28 179.6 20 180Z;
M20 20Q28 19.5 36 19Q44 18.8 52 18.8Q60 19.2 68 20Q76 21.1 84 22.4Q92 23.6 100 24.8Q108 25.5 116 25.7Q124 25.3 132 24.1Q140 22.3 148 20Q156 17.4 164 14.7Q172 12.3 180 10.5L180 170.5Q172 172.3 164 174.7Q156 177.4 148 180Q140 182.3 132 184.1Q124 185.3 116 185.7Q108 185.5 100 184.8Q92 183.6 84 182.4Q76 181.1 68 180Q60 179.2 52 178.8Q44 178.8 36 179Q28 179.5 20 180Z;
M20 20Q28 19.6 36 19Q44 18.5 52 18.1Q60 18 68 18.2Q76 18.9 84 20Q92 21.4 100 22.9Q108 24.4 116 25.7Q124 26.5 132 26.7Q140 26.1 148 24.7Q156 22.6 164 20Q172 17.1 180 14.1L180 174.1Q172 177.1 164 180Q156 182.6 148 184.7Q140 186.1 132 186.7Q124 186.5 116 185.7Q108 184.4 100 182.9Q92 181.4 84 180Q76 178.9 68 178.2Q60 178 52 178.1Q44 178.5 36 179Q28 179.6 20 180Z;
M20 20Q28 19.8 36 19.4Q44 18.8 52 18.1Q60 17.5 68 17.1Q76 17.2 84 17.6Q92 18.6 100 20Q108 21.7 116 23.5Q124 25.3 132 26.7Q140 27.5 148 27.6Q156 26.9 164 25.3Q172 22.9 180 20L180 180Q172 182.9 164 185.3Q156 186.9 148 187.6Q140 187.5 132 186.7Q124 185.3 116 183.5Q108 181.7 100 180Q92 178.6 84 177.6Q76 177.2 68 177.1Q60 177.5 52 178.1Q44 178.8 36 179.4Q28 179.8 20 180Z;
M20 20Q28 20.2 36 20Q44 19.5 52 18.8Q60 18 68 17.1Q76 16.5 84 16.2Q92 16.4 100 17.1Q108 18.3 116 20Q124 22 132 24.1Q140 26.1 148 27.6Q156 28.5 164 28.6Q172 27.7 180 25.9L180 185.9Q172 187.7 164 188.6Q156 188.5 148 187.6Q140 186.1 132 184.1Q124 182 116 180Q108 178.3 100 177.1Q92 176.4 84 176.2Q76 176.5 68 177.1Q60 178 52 178.8Q44 179.5 36 180Q28 180.2 20 180Z;
M20 20Q28 20.4 36 20.6Q44 20.5 52 20Q60 19.2 68 18.2Q76 17.2 84 16.2Q92 15.5 100 15.2Q108 15.6 116 16.5Q124 18 132 20Q140 22.3 148 24.7Q156 26.9 164 28.6Q172 29.5 180 29.5L180 189.5Q172 189.5 164 188.6Q156 186.9 148 184.7Q140 182.3 132 180Q124 178 116 176.5Q108 175.6 100 175.2Q92 175.5 84 176.2Q76 177.2 68 178.2Q60 179.2 52 180Q44 180.5 36 180.6Q28 180.4 20 180Z;
M20 20Q28 20.5 36 21Q44 21.2 52 21.2Q60 20.8 68 20Q76 18.9 84 17.6Q92 16.4 100 15.2Q108 14.5 116 14.3Q124 14.7 132 15.9Q140 17.7 148 20Q156 22.6 164 25.3Q172 27.7 180 29.5L180 189.5Q172 187.7 164 185.3Q156 182.6 148 180Q140 177.7 132 175.9Q124 174.7 116 174.3Q108 174.5 100 175.2Q92 176.4 84 177.6Q76 178.9 68 180Q60 180.8 52 181.2Q44 181.2 36 181Q28 180.5 20 180Z;
M20 20Q28 20.4 36 21Q44 21.5 52 21.9Q60 22 68 21.8Q76 21.1 84 20Q92 18.6 100 17.1Q108 15.6 116 14.3Q124 13.5 132 13.3Q140 13.9 148 15.3Q156 17.4 164 20Q172 22.9 180 25.9L180 185.9Q172 182.9 164 180Q156 177.4 148 175.3Q140 173.9 132 173.3Q124 173.5 116 174.3Q108 175.6 100 177.1Q92 178.6 84 180Q76 181.1 68 181.8Q60 182 52 181.9Q44 181.5 36 181Q28 180.4 20 180Z;
M20 20Q28 20.2 36 20.6Q44 21.2 52 21.9Q60 22.5 68 22.9Q76 22.8 84 22.4Q92 21.4 100 20Q108 18.3 116 16.5Q124 14.7 132 13.3Q140 12.5 148 12.4Q156 13.1 164 14.7Q172 17.1 180 20L180 180Q172 177.1 164 174.7Q156 173.1 148 172.4Q140 172.5 132 173.3Q124 174.7 116 176.5Q108 178.3 100 180Q92 181.4 84 182.4Q76 182.8 68 182.9Q60 182.5 52 181.9Q44 181.2 36 180.6Q28 180.2 20 180Z
"/>
</path>
</svg>
...