SVG로 사실적인(정현파) 플래그 애니메이션/플러터 만들기 (Making realistic (sinusoid) flag animation / flutter with SVG)


문제 설명

SVG로 사실적인(정현파) 플래그 애니메이션/플러터 만들기 (Making realistic (sinusoid) flag animation / flutter with SVG)

바람에 펄럭이는 보다 사실적인 애니메이션 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:

I think it would be impossible to get satisfactory results just by animating two end points and a control point between two keyframes. In any case, one side of your flag should stay still if it's going to look like it's attached to a flagpole.

I think the best approach would be to generate the path data programmatically using a lot more control points and a lot more keyframes. Here's a program I made in Python (v2) to demonstrate:

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)

And here's the output. If you're trying to simulate a Swiss flag, you can add the white cross in the middle in exactly the same way. Use quadratic curves (Q) for the horizontal lines, and straight lines (L) for the vertical lines.

<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>

(by Maštarijar3mainer)

참조 문서

  1. Making realistic (sinusoid) flag animation / flutter with SVG (CC BY‑SA 2.5/3.0/4.0)

#svg #css #html #smil #animation






관련 질문

D3/SVG: 범위를 수정하여 시간 척도로 d3.svg.axis의 크기를 조정하는 방법은 무엇입니까? (D3/SVG: How to resize a d3.svg.axis with time scale by modifying range?)

d3 SVG의 드롭다운 메뉴 (Drop down menu over d3 SVG)

단색 배경의 SVG 투명도 (SVG transparency on a solid background)

그룹을 번역할 때 이미지가 포함된 SVG 채우기가 작동하지 않음 (SVG fill with image not working when translate the group)

프로그래밍 방식으로 SVG 파일의 변환을 병합하는 방법은 무엇입니까? (How to flatten transforms in an SVG file programmatically?)

Jquery/Javascript - SVG를 클릭할 때 IE에서 요소 외부 클릭 감지가 실패함 (Jquery/Javascript - Detecting a click outside an element fails on IE when clicking an SVG)

snap.svg에서 그룹의 요소/자식을 반복하는 방법은 무엇입니까? (How to iterate on a group's elements/children in snap.svg?)

svgwrite로 기존 svg를 가져오는 방법 - Python (How to import an existing svg with svgwrite - Python)

SVG로 사실적인(정현파) 플래그 애니메이션/플러터 만들기 (Making realistic (sinusoid) flag animation / flutter with SVG)

javascript/svg에서 호로 양면이 있는 상자 그리기 (Drawing a box with two sides as an Arc in javascript/svg)

요소를 제외한 SVG 마우스 이벤트 통과 (SVG Mouse Event Passthrough except for elements)

단일 svg 요소를 만들기 위해 여러 모양 병합 (Merging number of shapes to make a single svg element)







코멘트