SVG 애니메이션 가이드(SMIL). SVG 애니메이션 가이드(SMIL) SVG 예제의 간단한 애니메이션




저자로부터: GIF처럼 작동하지만 벡터 그래픽에서만 작동하는 이미지 형식이 있다고 말하면 어떻게 될까요? 이 형식으로 애니메이션의 방향을 바꿀 수 있다고 말하면 어떨까요? 그렇다면 하나의 이미지를 기본으로 삼아 이미지의 여러 부분을 개별적으로 다른 속도로 애니메이션화할 수 있습니까? 예, 그러한 형식은 이미 존재하며 SVG입니다. 조금 용기를 내면 됩니다.

이 기사에서 나는 오래된 것과 새로운 것을 혼합하여 원시적인 것을 취하고 거기에 새로운 생명을 불어넣을 것입니다. Sass는 작업 흐름을 간소화하고 자동화를 시연하는 데 도움이 될 것입니다. 때로는 자동화가 창의성을 발휘할 수도 있습니다.

애니메이션, 오래된 접근 방식

나는 애니메이션 전문가와는 거리가 멀지만, 내가 정말 좋아하는 것이 무엇인지는 알고 있다. 모든 것이 움직일 때 말이다. 매우 간단합니다. 저는 웹 디자이너이고 웹 애니메이션은 제 직업의 일부입니다. 애니메이션에 대한 지원은 이미 널리 퍼져 있어 우리는 애니메이션의 목적과 의미와 같은 더 높은 차원에 관심을 돌릴 수 있습니다.

애니메이션은 본질적으로 표현력이 풍부하고 유연해야 하지만 모든 것이 순조롭게 진행되는 것은 아닙니다. 이 글에서 다룬 애니메이션이 제가 태어나기 오래 전부터 큰 인기를 끌었다는 사실은 조금 우울합니다.

지속적인 매력

“컴퓨터를 사용할 때에도 모든 것을 스스로 하세요.”- 미야자키 하야오

센과 치히로의 행방불명, 하울의 움직이는 성, 모노노케 공주 등 수많은 훌륭한 작품을 제작한 미야자키 하요의 스튜디오 지브리는 전통적인 수작업 애니메이션 기법인 레이어드 애니메이션을 고수합니다. CSS를 사용하는 CGI나 키프레임 애니메이션과 달리 이 접근 방식은 훨씬 더 많은 시간이 걸립니다.

미야자키는 성공을 위해 늦은 밤 애니메이션 스태프들을 위해 직접 라면을 만들어주는 것으로도 유명합니다.

그러나 스튜디오 지브리는 일종의 과거 페티쉬이기 때문에 손으로 작업하지 않습니다. 카메라가 발명된 이후 애니메이션이 여전히 인기를 끄는 이유는 몇 번의 스트로크만으로 삶을 바라볼 수 있기 때문입니다. 이 모든 것은 애니메이션에 적용되며, 각 프레임은 벡터 아트 가공물이 아닌 아티스트가 전적으로 그린 ​​것입니다. 최종 제품은 훨씬 더 풍부합니다. 손으로 그리는 무언의 전통이 있으므로 각 프레임은 몇 가지 정보를 전달합니다.

왼쪽의 부드러운 애니메이션은 키프레임 변환을 사용하여 만들어진 반면 오른쪽은 세 개의 독립 프레임을 차례로 기반으로 합니다. Firefix 사용자는 위의 애니메이션에 변환 원본 속성이 적용되지 않았음을 알 수 있습니다. 이는 모두 버그 때문입니다.

불편한 미소

인터넷에 레이어드 웹애니메이션을 만드는 기술이 없다고 하면 거짓말이다. SMIL(Synchronized Multimedia Integration Language)이라는 이름은 번거롭지만 이 언어는 애니메이션 제작을 위해 설계되었습니다. Jonathan Ingram은 Mortal Kombat 캐릭터를 예로 들어 SMIL을 사용하여 계층화되고 반복되는 애니메이션을 만드는 방법에 대한 훌륭한 튜토리얼을 제공합니다.

< animate

아이디 = "프레임2"

속성 이름 = "표시"

값 = "없음;인라인;없음;없음"

keyTimes = "0;0.33;0.66;1"

dur = "1초"

시작 = "0초"

RepeatCount = "무한" / >

animate 요소는 상위 요소의 애니메이션 상태를 정의하는 데 사용됩니다.

그러나 심각한 문제가 없는 것은 아닙니다. 상당히 오래된 분류임에도 불구하고 SMIL은 여전히 ​​IE에서 지원되지 않습니다. 또한 IE12, 15 또는 38에서도 지원이 계획되지 않습니다. 동시에 언어는 더 이상 사용되지 않으며 Chrome에서의 지원도 줄어들고 있습니다. Google의 Paul Kinlan은 Chrome 45 베타가 실제로 SMIL 지원 중단 경고를 무시했다고 말했습니다.

SMIL에 대한 지원은 계속 감소하고 있으며 XML 마크업을 사용하여 애니메이션을 만드는 것이 조금 이상하다고 생각합니다. 저는 애니메이션이 별도의 스타일 파일에 있는 데 익숙하며 이 파일이 거기에 속한다고 생각합니다. 결국 요소에 애니메이션을 적용하면 시각적 위치만 변경되고 마크업에는 영향을 주지 않습니다. 이는 JavaScript에서만 가능합니다.
안타깝게도 CSS에서 계층화된 애니메이션을 만드는 명시적이거나 빠른 방법은 없지만 거의 사용되지 않는 CSS 키프레임 속성을 기반으로 방법을 설명하겠습니다.

시작하자

@keyframe 애니메이션은 animation-timing-function 속성을 사용하여 작동하므로 일부 타이밍 기능에 대해 알아야 합니다. 예를 들어, easy-in 속성은 애니메이션이 완료될 때 애니메이션 속도를 줄입니다.

거의 사용되지 않는 steps() 함수도 흥미로운데, 그 이유는 애니메이션이 차례로 재생되는 별도의 레이어로 구성된 것처럼 경련 효과를 시뮬레이션하기 때문입니다. 예를 들어, 단계(5)는 5개의 개별 레이어에 대해 상당히 부드러운 애니메이션을 수행합니다.

steps() 함수의 모든 값은 키프레임 애니메이션을 시뮬레이션합니다. 마법의 프레임 전환은 없습니다. 그러나 단계(1)을 사용하면 애니메이션 없이 프레임 간을 간단히 전환할 수 있습니다. 불투명도 속성을 1에서 0으로 변경하면 애니메이션 요소를 한 단계로 표시하고 숨길 수 있습니다. 즉, 여기에 있고 저기에는 없습니다. 이는 제가 만들려는 레이어 애니메이션을 만드는 데 매우 중요한 단계입니다.

별도의 레이어로 요소

지금까지 나는 그 자체로 애니메이션을 수행하지 않고 미야자키 국수를 사용할 자격이 없는 하나의 요소 또는 레이어에 대해서만 걱정했습니다. 이것은 그림이 단순히 나타났다가 사라지는 경우입니다.

본격적인 애니메이션을 만들려면 더 많은 이미지, 즉 애니메이션을 구성할 레이어 세트를 만들어야 합니다. 이 단계는 매우 길고 쉽지는 않지만 불평하지는 않습니다. 각 개별 레이어를 그리는 것이 이러한 유형의 애니메이션을 특별하게 만드는 것입니다. 나중에 애니메이션 로직을 작성하는 데 도움이 필요할 것입니다.

마킹

이를 위해서는 SVG가 필요합니다. 기술적으로는 원하는 만큼 많은 레이어가 있을 수 있지만 SVG에서는 경로 요소 세트를 쉽게 정의하고 이를 서로 위에 레이어할 수 있습니다. 아래 예에서는 SVG 요소를 사용하여 애니메이션 컨테이너를 만들었습니다. (그룹), 레이어가 위치합니다. 이러한 레이어는 표시하려는 순서대로 작성되어야 합니다.

< g class = "animation-name" >

< path d = "" > < / path >

< path d = > < / path >

< path d = "" > < / path >

< / g >

레이어 만들기

SVG 작업을 위한 그래픽 편집기는 많이 있지만 Inkscape는 이 형식 작업을 위해 특별히 제작되었으며 내장 XML 편집 패널도 포함되어 있습니다. 그것은 우리의 삶을 훨씬 더 쉽게 만들어 줄 것입니다. 그리고 그것은 또한 무료입니다. 메커니즘을 시연하기 위해 SVG를 빠르게 살펴보겠습니다. 새 Inkscape 문서를 만들고 아래 이미지와 같은 세 가지 도형을 그립니다. 그것들은 정확히 동일할 필요는 없습니다.

모든 도형을 서로 겹쳐 놓고 문서의 크기를 도형의 크기에 맞게 조정합니다. 이렇게 하려면 파일->문서 속성을 선택한 다음 페이지 크기를 그림이나 선택 항목에 맞게 조정합니다. 개별 모양을 선택하지 않았는지 확인하십시오. 그렇지 않으면 문서의 크기가 해당 특정 모양에 맞게 조정됩니다.

그런 다음 모든 모양을 선택하고 개체->그룹을 클릭하면 그룹 요소가 생성됩니다. . 그런 다음 그룹을 선택한 상태에서 편집 &-> XML 편집기를 열고 그룹에 class.shapes를 지정합니다.

좋습니다. 이제 SVG 파일을 저장하세요. 목록에서 최적화된 SVG를 선택하고 뷰박스 활성화 옆의 확인란을 선택합니다. 이제 SVG는 애니메이션을 위한 준비가 완전히 완료되었습니다.

최적화 참고사항

우리와 같은 단순한 모양을 사용하면 SVG 데이터가 최소한으로 유지됩니다. 이 경우 애니메이션 SVG(나중에 작성할 CSS 포함)의 크기는 2.3KB에 불과합니다. 간단히 말해서, 각 레이어의 모양이 단순할수록 더 많은 레이어를 감당할 수 있습니다. 이 기사에서 사용할 기념일 로고와 ​​같이 보다 복잡한 이미지에 애니메이션을 적용하려면 Jake Archibald의 SVGOMG 도구를 사용하는 것이 좋습니다.

레이어링

위에서 쓴 것처럼 단계(1)을 사용하면 불투명도를 사용하여 요소의 가시성을 전환할 수 있습니다. 특정 값만 취하기 때문에(애니메이션화할 것이 없음) 디스플레이 속성으로는 동일한 효과를 얻을 수 없습니다. 먼저 컨테이너의 모든 레이어를 불투명도:0으로 설정하겠습니다.

모양 > * ( 불투명도: 0; 애니메이션 지속 시간: 0.75s; 애니메이션 반복 횟수: 무한; 애니메이션 타이밍 기능: 단계(1); )

모양 > * (

불투명도: 0;

애니메이션 - 지속 시간: 0.75초 ;

애니메이션 - 반복 - 횟수: 무한 ;

애니메이션 - 타이밍 - 기능 : 단계 ( 1 ) ;

단계별 시간 함수 설정과 마찬가지로 애니메이션 지속 시간이 0.75초인 무한 반복 횟수를 선택했습니다. 각 프레임은 동일한 시간 동안 나타나며 3개의 프레임이 있으므로 각 프레임은 0.25초, 즉 초당 4프레임 동안 나타나야 합니다.

그렇다면 명시된 대로 각 프레임이 다른 프레임 뒤에 나타납니까? 각 요소는 애니메이션 지속 시간을 0.75초로 설정한 다음 모든 프레임을 동시에 실행하여 하나를 다른 프레임 위에 원활하게 표시해야 합니다. 세 개의 레이어를 사용하면 각 레이어가 3분의 1 동안 표시되어야 합니다. @keyframe 구문에서 백분율을 사용하고 각 n번째 하위 항목에 대해 다른 애니메이션을 적용했습니다.

@keyframes 모양-1 ( 0% ( 불투명도: 1; ) 33.33333% ( 불투명도: 0; ) .shapes > :nth-child(1) ( 애니메이션 이름: 모양-1; ) @keyframes 모양-2 ( 33.33333 % ( 불투명도: 1; ) 66.66667% ( 불투명도: 0; ) .shapes > :nth-child(2) ( 애니메이션 이름:shape-2; ) @keyframesshape-3 ( 66.66667% ( 불투명도: 1; ) 100% ( 불투명도: 0; ) .shapes > :nth-child(3) ( 애니메이션 이름:shape-3; )

@keyframes 모양 - 1(

0 % {

불투명도: 1;

33.33333 % {

불투명도: 0;

도형 > : n번째 - 자식 (1 ) (

애니메이션 - 이름 : 모양 - 1 ;

@keyframes 모양 - 2(

33.33333 % {

불투명도: 1;

66.66667 % {

불투명도: 0;

도형 > : n번째 - 하위(2 ) (

애니메이션 - 이름 : 모양 - 2 ;

@keyframes 모양 - 3(

66.66667 % {

불투명도: 1;

100 % {

불투명도: 0;

도형 > : n번째 - 하위(3 ) (

애니메이션 - 이름 : 모양 - 3 ;

임베딩 및 연결

이제 확장 가능한 GIF 애니메이션을 만들기 위해 마침내 SVG 파일에 스타일을 추가할 수 있습니다. 내 컴퓨터에 작업 실행기가 없기 때문에 온라인 버전의 autoprefixer를 사용하여 공급업체 접두사를 자동으로 추가했습니다.

< svg viewBox = "0 0 100 100" >

< g class = "animation-name" >

< path d = "" > < / path >

< path d = "" > < / path >

< path d = "" > < / path >

< / g >

< / svg >

img 태그를 통해 SVG를 포함하더라도 모든 브라우저가 아닌 일부 브라우저에서 애니메이션을 재생합니다. 객체를 사용하는 것이 더 안정적입니다.

< object type = "image/svg+xml" data = "path_to/shapes.svg" role = "img" aria - label = "shapes animation" >

< div role = "img" class = "shapes-fallback" aria - label = "shapes animation" > < / div >

< / object >

객체와 DIV 요소 모두에 img 값과 aria-label 속성이 있는 WAI-ARIA 역할이 의미적 정확성을 위해 사용된다는 점에 유의하세요. 일부 브라우저는 SVG 외에 이 태그를 로드하기 때문에 img를 사용하는 이전 브라우저에 대한 대체 작업을 수행하지 않았습니다. 하지만 물론 element.shapes-fallback의 background-image 속성을 사용하여 CSS를 통해 정적 배경 이미지를 추가해야 합니다.

하나의 이미지, 많은 애니메이션

확장성 외에도 SVG는 GIF에 비해 또 다른 장점이 있는데, 이는 하나의 이미지의 개별 부분에 애니메이션 속도와 지속 시간을 다르게 적용할 수 있는 기능입니다. 아래의 상어 예에서는 꼬리와 눈이 다양한 속도와 다양한 레이어 수로 애니메이션됩니다.

수학적으로 말하면 여기서 흥미로운 일이 발생합니다. 동일한 파일 내에 두 개의 개별 애니메이션이 있는 경우 애니메이션의 총 지속 시간은 개별 구성 요소보다 길어집니다. 따라서 한 애니메이션이 3개의 프레임으로 구성되고 다른 애니메이션이 4개의 프레임으로 구성되면 총 길이는 12프레임이 됩니다. 이는 두 개의 개별 애니메이션 중 가장 긴 것보다 3배 더 긴 것입니다.

각 프레임이 레이어와 직접 연결되어 있는 GIF에서는 새 이미지를 추가해야만 이 효과를 얻을 수 있습니다. 따라서 파일 크기가 증가합니다.

가변 애니메이션

내 shark.svg 예에서 흔들리는 꼬리와 깜박이는 눈은 모두 교대 대칭 애니메이션을 사용합니다. 여기서 모든 레이어는 먼저 앞으로 재생된 다음 뒤로 재생되는 방식으로 무한정 재생됩니다. 레이어로 구성된 각 애니메이션 요소는 동시에 움직이기 시작하여 각 레이어의 animation-direction: 대체 속성을 사용하여 무한한 애니메이션 효과를 생성합니다.

꼬리 > * ( 애니메이션 방향: 대체; )

꼬리 > * (

애니메이션 - 방향: 대체;

이 접근 방식은 무게를 줄여줍니다. GIF에서 동일한 효과를 얻으려면 이미지를 두 번 추가해야 합니다. 먼저 일반 순서로 추가한 다음 역순으로 추가해야 합니다.

진정한 레이어드 애니메이션

나는 전통적인 레이어 애니메이션을 현대 키프레임 애니메이션과 비교하기 어렵다는 결론으로 ​​기사를 시작했습니다. 레이어 애니메이션이 등장하기 전에는 각 프레임이 이미지의 애니메이션 부분뿐만 아니라 전체로 그려졌습니다. 레이어에 애니메이션 부분만 그리면 정적 배경을 재사용할 수 있습니다. 이 접근 방식은 시간을 절약할 뿐만 아니라 부드러움도 향상시킵니다.

SVG는 마크업의 여러 "하위 트리"로 구분되는 텍스트 기반 이미지 형식입니다. 따라서 이 형식은 정적 이미지와 애니메이션 이미지를 결합하는 데 이상적입니다.

Sass를 사용한 자동화

내 애니메이션은 점점 더 정교해지고 있으며 각 레이어에 대해 별도의 애니메이션 클래스를 만드는 것이 조금 지루해지고 있습니다. 무거운 작업을 수행하기 위해 Sass를 연결했습니다. @for 지시문과 일부 계산을 사용하여 애니메이션을 자동으로 생성할 수 있었습니다.

$셀: 6; $fraction: 100 / $cels; 1에서 $cels까지의 @for $i ( $name: 모양; $start: ($fraction * $i) - $fraction; @keyframes #($name)-#($i) ( #($start * 1% ) ( 불투명도: 1; ) #(($start + $fraction) * 1%) ( 불투명도: 0; ) ) > :nth-child(#($i)) ( 애니메이션 이름: #($name)- #($i); ) )

시리즈의 이전 강의에서는 벡터 그래픽을 사용하는 방법을 살펴보았습니다. SVG HTML로. 이제 애니메이션을 볼 시간이다 SVG.

기초

SVG 애니메이션은 요소를 사용하여 수행됩니다. :

요소를 추가합니다 내부에요소 , 우리는 애니메이션을 적용할 것입니다. 요소 다음 속성을 포함합니다:

속성이름: 애니메이션에 참여할 속성을 정의합니다.

~에서: 선택적 속성입니다. 시작 값을 정의하며, 기본적으로 현재 값이 사용됩니다.

에게: 이 속성은 애니메이션의 방향을 지정합니다. attributeName 속성에 지정된 값에 따라 결과가 달라질 수 있습니다. 위의 예에서는 요소의 높이가 변경됩니다.

기간: 애니메이션의 지속 시간을 결정합니다. 값은 시계 값 구문 형식으로 지정되어야 합니다. 예를 들어 02:33은 2분 33초에 해당하고, 3h는 3시간에 해당합니다. 이 예에서는 애니메이션 지속 시간을 3초로 정의합니다.

우리는 요소에 대해서도 동일한 작업을 수행합니다. , 그러나 반경(r) 속성에 애니메이션을 적용합니다.

움직이는 요소

SVG 요소를 이동하려면 x 및 y 좌표만 지정하면 됩니다.

예제에서는 3초 안에 직사각형을 0에서 200으로 이동합니다. 또한 요소에 채우기 속성을 추가합니다. . 이 속성은 완료 후 애니메이션이 작동하는 방식을 결정합니다. 예제에서 값 고정은 애니메이션이 끝나는 위치에 요소를 강제로 유지합니다.

요소에도 동일하게 적용됩니다. , 그러나 이를 위해 cx 또는 cy 속성을 변경합니다.

여러 속성에 애니메이션 적용

물론 요소에서는 하나의 속성에만 변경 사항을 설정할 수 있지만 요소 자체에는 변경 사항을 설정할 수 없습니다. 우리는 여러 가지를 정의할 수 있습니다. 예를 들면 다음과 같습니다.

여기서는 요소의 속성에 애니메이션을 적용합니다. - 스트로크의 반경과 너비.

2014년 1월 5일 오후 4시 27분

SVG 경로 요소 애니메이션

  • 웹사이트 개발,
  • 데이터 시각화
  • 지도 시간

제 생각에는 많은 사람들이 차세대 게임 콘솔에 대한 리뷰를 본 것 같습니다. 다각형(Vox Media). 블루프린트 스타일로 그려진 콘솔은 다음과 같습니다:

리뷰는 멋지고 매우 특이하며 새 것처럼 보였습니다. 리뷰의 주요 기능(SVG 애니메이션, 유사한 작업을 직접 수행하는 방법)이 어떻게 구현되는지 컷 아래에서 확인할 수 있으며 경로 요소의 애니메이션 측면에서 오래된 SVG가 숨기는 다른 "비밀" 기능이 무엇인지 확인할 수 있습니다.

스트로크-다샤레이 보간, 이론

일반적으로 이러한 라인 애니메이션 기술은 새로운 것이 아니며 최근까지 SVG 및 이와 관련된 모든 것이 부당하게 망각에 맡겨졌지만 다행스럽게도 상황이 바뀌고 있습니다. 따라서 경로 요소의 스트로크-다샤레이 속성 덕분에 경로 요소에 애니메이션을 적용하는 트릭이 가능합니다. 이 속성을 사용하면 점선의 매개변수, 즉 획의 길이와 획 사이의 간격을 설정할 수 있습니다. 획의 길이를 선의 전체 길이와 동일하게 설정하면 일반적인 실선이 생성됩니다. 획의 길이를 0으로 설정하고 간격의 길이를 다시 선의 전체 길이와 동일하게 설정하면 보이지 않는 선이 생깁니다. 그리고 전체 선의 길이와 동일한 간격 길이로 획의 길이를 점차적으로 늘려서 그 그림을 시뮬레이션할 수 있습니다. 이 접근 방식을 사용하면 선의 시작 부분부터 그리기가 발생합니다. 갑자기 끝부터 그려야 하는 경우, 스트로크 대시오프셋이라는 속성을 하나 더 사용해야 합니다. 이 속성은 첫 번째 획의 오프셋을 지정합니다. 따라서 오프셋을 줄이고 획의 길이를 늘려 선 끝에서 그림을 그립니다.

에서 온 사람들 복스미디어그들은 하이브리드 옵션(내 생각에는 중복됨)을 사용했습니다. 그런데 그들이 어떻게 이 작업을 수행했는지 블로그에서 읽을 수 있습니다(그리고 읽어야 합니다): Polygon feature design: SVG animations for fun andprofit.

SVG 애니메이션 구현

안에 복스미디어그들은 부드러운 애니메이션을 위해 requestAnimationFrame을 사용할 것을 제안하지만 우리는 약간 다른 목표를 가지고 있으므로 더 간단한 경로를 택하여 D3.js 라이브러리와 여기에 구현된 지속 시간 기반 애니메이션을 사용하겠습니다.

다음은 기사 시작 부분부터 콘솔에 애니메이션을 적용하는 데 사용된 실제 작업 코드입니다.

대기열() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(ready); function Ready(error, xml) ( //HTML 문서에 svg 파일 추가 var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("너비"), svgHeight = svg.attr("높이"); var paths = svg.selectAll("경로") .call(전환) ; 함수 전환(경로) ( path.transition() .duration(5000) .attrTween("Stroke-dasharray", tweenDash) .each("end", function() ( d3.select(this).call(transition) ; )); // 무한 루프 ) function tweenDash() ( var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // 획 보간 -dasharray 속성 return function(t) ( return i(t); ); ) )


지금은 회전하지 않고 선을 따라 이동하는 것부터 시작하겠습니다.

대기열() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(ready); function Ready(error, xml) ( //HTML 문서에 svg 파일 추가 var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(경로); var marker = svg.append("circle"); marker.attr(" r", 7).attr("transform", "translate(" + startPoint + ")"); Transition(); //마커 함수 배치를 위한 경로 시작점 가져오기 pathStartPoint(path) ( var d = path.attr( "d"), dsplitted = d.split(" "); return dsplitted.split(","); ) 함수 전환() ( marker.transition() .duration(7500) .attrTween("transform",translateAlong( path.node())) .each("end", 전환);// 무한 루프 ) function moveAlong(path) ( var l = path.getTotalLength(); return function(i) ( return function(t) ( var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")";//마커 이동 ) ) ) )
여기서 pathStartPoint(path)는 경로 요소의 속성에서 선의 시작 좌표를 가져옵니다. TranslateAlong(path)에서 마커의 좌표는 보간기를 사용하여 설정됩니다. 예는 여기에서 볼 수 있습니다: D3.js를 사용하는 SVG 경로 요소에 따른 마커 애니메이션. 선 그리기 애니메이션과 마커 이동을 결합할 수도 있습니다. 이는 다음과 같이 보일 수 있습니다: D3.js II를 사용하여 SVG 경로 요소를 따르는 마커 애니메이션.

작업을 복잡하게 만들고 회전을 추가해 보겠습니다. 마커를 원에서 더 흥미로운 것으로 변경해 보겠습니다. 마커로 너비가 48이고 길이가 24인 로켓이 있습니다. 마커의 기본 앵커 포인트는 왼쪽 상단이므로 마커 중앙에 맞춰지도록 오프셋을 적용해야 합니다. 회전할 때도 이 점을 고려해야 합니다. 기본적으로 왼쪽 상단 모서리 주변에서도 발생하기 때문입니다. 변위를 정리 한 것 같습니다. 이제 직접 회전으로 넘어가겠습니다. 여기서 접선의 정의가 도움이 될 것이며 아크탄젠트를 사용하여 각도를 결정할 것입니다.

보간기를 정의하는 TranslateAlong(path) 함수는 다음과 같습니다:

함수 moveAlong(path) ( var l = path.getTotalLength(); var t0 = 0; return function(i) ( return function(t) ( var p0 = path.getPointAtLength(t0 * l);//이전 지점 var p = path.getPointAtLength(t * l);///현재 점 var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//접선 각도 t0 = t ; //중심을 로켓 중심으로 이동 var centerX = p.x - 24, centerY = p.y - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12 "+")"; ) ) )
구현은 여기에서 볼 수 있습니다.

SVG 그래픽은 애니메이션 요소를 사용하여 애니메이션을 적용할 수 있습니다. 이러한 요소는 원래 SMIL 애니메이션 사양에 정의되었습니다. 여기에는 다음이 포함됩니다.

  • — 특정 기간 동안 스칼라 속성 및 속성에 대한 애니메이션을 설정할 수 있습니다.
  • 가시성 속성과 같은 숫자가 아닌 속성 및 속성에 애니메이션 값을 할당할 수 있는 편리한 애니메이션 약어입니다.
  • — 이동 경로를 따라 요소를 이동합니다.
  • - 일정 기간 동안 특정 속성이나 속성의 색상 값을 변경합니다. 요소를 사용하는 데 유의하세요. 색상 값을 취할 수 있는 속성을 정의하기 위해 애니메이션 요소를 사용하는 것과 비교하면 오래된 관행입니다. SVG 1.1 사양에는 여전히 존재하지만 동일한 사양에서는 더 이상 사용되지 않는다고 분명히 명시했습니다. SVG-2 사양에서는 완전히 제거되었습니다.

SMIL 사양에 정의된 애니메이션 요소 외에도 SVG에는 SMIL 애니메이션 사양과 호환되는 확장이 포함되어 있습니다. 이러한 확장에는 요소의 기능을 확장하는 속성이 포함됩니다. 그리고 추가 애니메이션 요소.

SVG 확장에는 다음이 포함됩니다.

  • — 특정 기간 동안 SVG 변환 속성 중 하나로 애니메이션을 설정할 수 있습니다(예: 변환 속성).
  • 경로(속성) - animateMotion 요소의 경로 속성에 모든 SVG 경로 데이터 구문 함수를 지정할 수 있습니다( SMIL 애니메이션을 사용하면 SVG 경로 데이터 구문의 하위 집합만 경로 속성에 사용할 수 있습니다.).

다음 섹션에서는 animateMotion에 대해 설명하겠습니다.

  • - 모션 경로와 같이 사용해야 하는 모션 경로를 참조하기 위해 animateMotion 요소와 함께 사용됩니다. mpath 요소는 animateMotion 요소 내부의 닫는 태그 앞에 포함됩니다.
  • 키포인트(속성) - 애니메이션 요소가 경로를 따라 이동하는 속도를 정밀하게 제어하기 위해 animateMotion의 속성으로 사용됩니다.
  • 회전(속성) - animateMotion의 속성으로 사용되어 객체의 x축 점이 모션 경로의 접선 벡터 방향과 동일한(또는 반대) 방향으로 회전하도록 객체가 자동으로 회전하는지 여부를 제어합니다. 이 속성은 원하는 방식으로 작동하는 경로를 따라 움직임을 만드는 열쇠입니다. 이에 대한 자세한 내용은 animateMotion 섹션을 참조하세요.

SVG 애니메이션은 특성상 CSS 애니메이션 및 전환과 유사할 수 있습니다. 사이프레임이 생성되고, 모든 것이 움직이고, 색상이 변경되는 등의 작업을 수행합니다. 그러나 CSS 애니메이션이 할 수 없는 몇 가지 작업을 수행할 수 있습니다. 이 가이드에서 이에 대해 다루겠습니다.

SVG 애니메이션은 어떤 용도로 사용되나요?

SVG는 CSS(슬라이드)를 사용하여 스타일을 지정하고 애니메이션을 적용할 수 있습니다. 기본적으로 HTML 요소에 적용할 수 있는 모든 변환 또는 전환 애니메이션은 SVG 요소에도 적용할 수 있습니다. 그러나 CSS를 통해 애니메이션화할 수 없는 일부 SVG 속성이 있지만 SVG를 통해 직접 수행할 수 있습니다.

예를 들어 SVG 경로는 해당 경로의 모양을 정의하는 데이터 세트(d="" 속성)로 정의됩니다. 이 데이터는 SMIL을 통해 변경 및 애니메이션화할 수 있지만 CSS를 통해서는 불가능합니다.

이는 SVG 요소가 SVG 표시 속성으로 알려진 일련의 속성을 사용하여 설명되기 때문입니다. 이러한 속성 중 일부는 CSS를 사용하여 설정, 수정 및 애니메이션화할 수 있지만 다른 속성은 그렇지 않습니다.

따라서 현재 많은 애니메이션 효과는 CSS를 사용하여 구현할 수 없습니다. 이 격차는 JavaScript나 SMIL에서 파생된 선언적 SVG 애니메이션으로 채워질 수 있습니다.

JavaScript 사용을 선호한다면 "SVG용 jQuery"라고 불리는 Dmitry Baranovsky의 snap.svg를 추천합니다.

또는 애니메이션에 대한 보다 세련된 접근 방식을 선호한다면 SVG 요소를 사용할 수 있습니다. 이에 대해서는 이 튜토리얼에서 다룰 것입니다!

JS 애니메이션에 비해 SMIL의 또 다른 장점은 SVG가 img로 포함되거나 CSS에서 배경 이미지로 사용될 때 JS가 작동하지 않는다는 것입니다. SMIL 애니메이션은 두 경우 모두에서 작동합니다( 또는 곧 브라우저에서 지원될 것으로 예상됩니다.).

제 생각에는 이것이 상당한 이점입니다. SMIL을 선택해야 하는 다른 이유를 찾을 수도 있습니다. 이 문서는 지금 SMIL을 시작하는 데 도움이 되는 가이드입니다.

브라우저 지원 및 대안

SMIL은 브라우저에서 상당히 광범위하게 지원됩니다. Internet Explorer 및 Opera Mini를 제외한 모든 브라우저에서 작동합니다. 브라우저 지원에 관한 포괄적인 정보는 다음을 참조하세요. 호환성 표 또는 "사용할 수 있나요?".

SMIL 애니메이션에 대한 폴백을 제공해야 하는 경우 Modernizr을 사용하여 브라우저 지원을 확인할 수 있습니다. SMIL이 지원되지 않는 경우 일종의 대안을 제공할 수 있습니다( JavaScript 애니메이션, 대체 접근 방식 등.).

xlink:href를 사용하여 애니메이션 대상 지정

네 가지 애니메이션 요소 중 어떤 요소를 선택하든 해당 요소에 의해 정의된 대상 애니메이션을 지정해야 합니다.

대상을 지정하려면 xlink:href 속성을 사용할 수 있습니다. 속성은 이 애니메이션의 개체인 요소에 대한 URI 참조를 사용하므로 시간이 지남에 따라 변경됩니다. 대상 요소는 문서의 현재 SVG 조각의 일부여야 합니다.

이전에 SVG 애니메이션 요소를 다룬 적이 있다면 해당 요소가 애니메이션을 적용해야 하는 다른 요소 내에 중첩된 요소로 접했을 것입니다. 이는 사양에 의해 제공됩니다.

xlink:href 속성이 사용되지 않으면 대상 요소는 현재 애니메이션 요소보다 첫 번째 수준 위의 상위 요소가 됩니다.

따라서 원한다면 " 캡슐화하다» 애니메이션이 적용되는 요소에 추가하면 그렇게 할 수 있습니다. 그리고 애니메이션 요소를 문서의 다른 곳에 저장하려면 xlink:href를 사용하여 각 애니메이션 요소의 대상을 지정하면 됩니다. 두 방법 모두 동일하게 작동합니다.

attributeName 및 attributeType을 사용하여 애니메이션의 대상 속성 지정

모든 애니메이션 요소는 하나 이상의 속성인 attributeName과도 상호 작용합니다. attributeName은 애니메이션을 적용하는 속성의 이름을 지정하는 데 사용됩니다.

예를 들어 중앙 위치에 대한 애니메이션을 설정하려는 경우 x축에서는 attributeName 속성의 값으로 cx를 지정하여 이를 수행합니다.

attributeName은 한 번에 하나의 속성만 애니메이션화할 수 있으므로 하나의 값만 허용하고 값 목록은 허용하지 않습니다. 둘 이상의 속성에 대해 애니메이션을 정의하려면 해당 요소에 대해 둘 이상의 애니메이션 효과를 정의해야 합니다.

이것은 제가 그다지 좋아하지 않는 부분이며 CSS가 SMIL보다 장점이 있는 부분이라고 생각합니다. 하지만 다시 말하지만, 다른 애니메이션 속성에 가능한 값으로 인해( 그것에 대해서는 나중에 더 자세히), 한 번에 하나의 속성 이름만 정의하는 것이 좋습니다. 그렇지 않으면 속성 값을 여러 개 더 정의하면 너무 복잡해져서 작업할 수 없게 됩니다.

속성 이름을 지정할 때 XMLNS 접두사( XML 네임스페이스의 약자) 속성 네임스페이스를 나타냅니다.

네임스페이스는 attributeType 특성을 사용하여 지정할 수도 있습니다. 예를 들어 일부 속성은 CSS 네임스페이스에 속합니다. (즉, 속성은 CSS 속성으로도 찾을 수 있습니다.), 기타 - XML ​​네임스페이스만 해당됩니다.

다음은 이러한 속성을 나열한 표입니다. 이 표에는 모든 SVG 속성이 포함되지 않고 CSS를 사용하여 설정할 수 있는 속성만 포함됩니다. 일부는 현재 CSS 속성으로 이미 사용 가능합니다.

attributeType 값이 명시적으로 설정되지 않았거나 자동으로 설정된 경우 브라우저는 먼저 CSS 속성 목록을 검색해야 하며, 아무 것도 발견되지 않으면 요소의 기본 XML 네임스페이스를 검색해야 합니다.

예를 들어 다음 코드 조각은 SVG 직사각형의 불투명도에 대한 애니메이션을 설정합니다. opacity 속성은 CSS 속성으로도 사용할 수 있으므로 attributeType은 CSS 네임스페이스로 설정됩니다.

다음 예에서는 다른 애니메이션 속성을 살펴보겠습니다. 모든 애니메이션 속성은 달리 명시되지 않는 한 모든 애니메이션 요소에 공통됩니다.

시간이 지남에 따라 요소의 속성을 한 값에서 다른 값으로 변경하여 최종 상태(from, by, to, dur 및 fill)를 나타내는 애니메이션을 설정합니다.

원을 한 곳에서 다른 곳으로 옮기는 것부터 시작해 보겠습니다. 우리는 cx 속성의 값을 변경하여 이를 수행할 것입니다( x축을 따라 중심 위치를 결정합니다.).

이를 위해 우리는 요소를 사용합니다 . 이 요소는 하나의 속성에 한 번 애니메이션을 적용하는 데 사용됩니다. 숫자 및 색상 값을 취하는 속성은 일반적으로 다음을 사용하여 애니메이션됩니다. . 이 표에서 애니메이션으로 만들 수 있는 속성 목록을 찾을 수 있습니다.

일정 기간 동안 한 값에서 다른 값으로 값을 변경하려면 from, to 및 dur 속성이 사용됩니다. 이 외에도 시작 속성을 사용하여 애니메이션이 시작되어야 하는 시기를 지정할 수도 있습니다.

위의 예에서는 원을 정의한 다음 해당 원에서 애니메이션을 호출했습니다. 원의 중심은 x축을 따라 50단위 좌표의 원래 위치에서 450단위 좌표의 점으로 이동합니다.

시작 속성을 click 으로 설정했습니다. 이는 마우스 커서를 누른 후에 원이 움직이기 시작한다는 것을 의미합니다. 이 속성을 특정 시간으로 설정할 수 있습니다. 예를 들어, start="0s"는 페이지가 로드된 직후 애니메이션을 시작합니다.

양의 시간 값을 설정하여 애니메이션 시작을 지연시킬 수 있습니다. 예를 들어, start="2s"는 페이지가 로드된 후 2초 후에 애니메이션을 시작합니다.

더욱 흥미로운 점은 click + 1s 와 같은 값으로 시작 속성을 정의할 수 있다는 점입니다. 이 값은 마우스를 클릭한 후 1초 후에 애니메이션을 시작합니다!

또한 다른 애니메이션의 지속 시간과 지연을 정확하게 계산하지 않고도 애니메이션을 동기화할 수 있는 다른 값을 사용할 수 있습니다. 이에 대해서는 나중에 자세히 설명합니다.

dur 속성은 CSS animation-duration 속성과 유사합니다.

from 및 to 속성은 @keyframe CSS 애니메이션 블록의 from 및 to 키프레임과 유사합니다.

@keyframes moveCircle ( from ( /* 애니메이션 시작 값 */ ) ~ ( /* 애니메이션 끝 값 */ ) )

속성 채우기( 불행히도 요소의 채우기 색상을 지정하는 다른 채우기 속성과 이름이 동일합니다.)는 애니메이션이 완료된 후 요소가 원래 상태로 돌아가야 하는지 여부를 결정하는 animation-fill-mode 속성과 유사합니다.

SVG에서의 의미는 다른 이름을 사용한다는 점을 제외하면 CSS에서 사용되는 의미와 유사합니다.

  • 동결: 마지막 애니메이션 기간 값의 상태에서 효과 상태를 동결하도록 지정하는 값입니다. 문서가 닫힐 때까지 애니메이션 효과가 정지됩니다( 또는 애니메이션이 다시 시작될 때까지);
  • 제거: 애니메이션 효과가 제거됩니다( 더 이상 적용되지 않습니다), 지속 시간에 지정된 애니메이션 작업이 완료되면. 애니메이션이 완료되면 더 이상 대상 요소( 애니메이션이 다시 시작되지 않으면).

이 데모에서 값을 변경하여 애니메이션에 어떤 영향을 미치는지 확인해보세요.
HTML:

CSS:

결과

by 속성은 애니메이션의 상대 오프셋을 지정하는 데 사용됩니다. 이름에서 알 수 있듯이 애니메이션을 변경하는 값을 지정하는 데 사용할 수 있습니다.

이 효과는 CSS steps() 함수의 작동 방식과 유사하게 애니메이션 지속 시간을 한 주기에서 다음 주기로 변경할 때만 눈에 띄게 나타납니다.

CSS steps() 함수에 해당하는 SVG는 calcMode="discrete" 입니다. 잠시 후에 calcMode="discrete" 속성에 대해 살펴보겠습니다.

재시작을 사용하여 애니메이션 다시 시작

애니메이션이 활성화된 동안 애니메이션이 다시 시작되지 않도록 차단해야 할 수도 있습니다. 이를 위해 SVG는 재시작 속성을 제공합니다.

다음 세 가지 가능한 값 중 하나로 설정할 수 있습니다.

  • Always: 애니메이션은 언제든지 다시 시작할 수 있습니다. 이것이 기본값입니다.
  • whenNotActive: 애니메이션은 비활성화된 경우에만 다시 시작할 수 있습니다( 즉, 애니메이션 지속 기간이 완료되면). 애니메이션이 진행되는 동안 애니메이션을 다시 시작하려는 시도는 무시됩니다.
  • never: 상위 컨테이너가 다시 시작될 때까지 요소를 다시 시작할 수 없습니다. ( SVG의 경우 상위 컨테이너는 SVG 문서 조각이므로 문서를 다시 로드할 때까지 애니메이션을 다시 시작할 수 없습니다.).

애니메이션 이름과 타이밍

이동 애니메이션이 끝날 때 색상이 변경되도록 원의 위치와 색상에 애니메이션을 적용한다고 가정해 보겠습니다. 색상 변경 애니메이션의 시작 값을 이동 애니메이션의 지속 시간과 동일하게 설정하여 이를 수행할 수 있습니다. 이것이 우리가 CSS에서 일반적으로 수행하는 작업입니다.

그러나 SMIL에는 훌륭한 이벤트 처리 기능이 있습니다. 나는 이미 시작 속성이 click + 5s와 같은 값을 허용한다고 언급했습니다. 이 값을 " 행사의 의미", 이 경우에는 "시계의 값"이 뒤따르는 이벤트로 구성됩니다.

여기서 가장 흥미로운 부분은 두 번째 부분인 '시계의 의미'입니다. 왜 단순히 "라고 부르지 않습니까? 시간가치"? 대답은 이 값을 시계처럼 문자 그대로 사용할 수 있다는 것입니다. 이 값을 "10min" 또는 "01:33"으로 설정할 수 있습니다. 이는 " 1분 33초" 또는 "02:30:03"( 2시간 30분 3초). 이 글을 쓰는 시점에서 시계 값은 대부분의 브라우저에서 완전히 구현되지 않습니다.

따라서 이전 데모에서 click + 01:30을 사용했다면 브라우저 지원이 구현되면 마우스 클릭 후 1분 30초 후에 애니메이션이 시작됩니다.

이 속성이 취할 수 있는 또 다른 종류의 값은 이벤트 지정자가 뒤에 오는 다른 애니메이션의 ID입니다. 두 개 이상의 애니메이션 효과가 있는 경우( 동일한 요소에 적용되는지 여부에 관계없이!), 다른 애니메이션의 실행 단계에 따라 하나가 시작되도록 동기화하려는 경우 다른 애니메이션의 지속 시간을 몰라도 이 작업을 수행할 수 있습니다.

예를 들어 다음 예에서는 원 애니메이션이 시작된 후 1초 후에 파란색 직사각형이 움직이기 시작합니다. 다음 코드에 표시된 대로 각 애니메이션 요소에 ID를 지정한 다음 시작 이벤트와 함께 해당 ID를 사용하면 됩니다.

start="circ-anim.begin + 1s"원 애니메이션이 시작된 후 1초 후에 사각형 애니메이션을 시작하도록 브라우저에 지시합니다.

이 데모에서 모든 것을 볼 수 있습니다:

HTML:

원을 클릭하면 애니메이션이 시작되고 1초 후에 직사각형의 애니메이션이 시작됩니다.

CSS:

결과

end 이벤트를 사용하여 원 애니메이션이 완료되면 직사각형 애니메이션을 시작할 수도 있습니다.

원 애니메이션이 완료되기 전에 실행할 수도 있습니다.

RepeatCount를 사용하여 애니메이션 반복

애니메이션을 두 번 이상 실행하려면 RepeatCount 속성을 사용하면 됩니다. 반복할 횟수를 지정하거나 무한 키워드를 사용하여 애니메이션을 무한정 반복할 수 있습니다.

따라서 원 애니메이션을 두 번 반복하려면 코드는 다음과 같아야 합니다.

데모에서 이를 볼 수 있습니다. 원의 반복 횟수는 2로, 사각형의 반복 횟수는 무한으로 설정했습니다.
HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

애니메이션은 루프가 끝났을 때 도달한 값이 아니라 의 원래 값에서 다시 시작됩니다. 불행하게도 SMIL은 CSS 애니메이션처럼 시작 값과 끝 값 사이의 왕복 경로를 정의하는 것을 허용하지 않습니다.

CSS에서 animation-direction 속성은 애니메이션이 반대 방향으로 재생되어야 하는지 아니면 각 사이클을 0점에서 시작해야 하는지를 결정합니다.

의미 애니메이션 방향: 대체짝수 애니메이션 루프는 정방향으로 재생되고, 홀수 애니메이션 루프는 역방향으로 재생된다는 의미입니다. 즉, 첫 번째 루프는 처음부터 끝까지 재생되고, 두 번째 루프는 처음부터 다시 시작하고, 세 번째 루프는 다시 처음부터 끝까지 재생되는 식입니다.

SMIL에서 이를 수행하려면 JavaScript를 사용하여 from 및 to 속성의 값을 변경해야 합니다. 존 맥파틀랜드얼마 전 빅바이트 크리에이티브에서 기사를 게재했다, 그가 작업 중인 메뉴 아이콘 애니메이션에 대해 이 작업을 수행한 방법을 설명했습니다.

다음은 Miles Elam이 만든 지연을 사용하여 무한정 반복되는 훌륭하고 간단한 애니메이션입니다.

HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

RepeatDur를 사용하여 애니메이션 반복 시간 제한

애니메이션을 끝없이 실행하는 작업이 오랫동안 계속되면 짜증이 나거나 페이지 디자인이 망가질 수 있습니다.

따라서 애니메이션 반복을 특정 기간으로 제한하고 문서가 로드된 후 일정 시간 동안 애니메이션 반복을 중지할 수 있는 것이 매우 유용할 수 있습니다. 이를 프레젠테이션 시간이라고 합니다.

프리젠테이션 시간은 전체 문서의 시작과 관련된 특정 문서 조각의 시간 척도에서의 위치를 ​​나타냅니다. 이는repeatDur 속성을 사용하여 지정됩니다.

구문은 시계 값과 유사하지만 다른 애니메이션이나 상호 작용 이벤트에서 계산되는 대신 이 경우 문서의 시작(로딩)부터 시간이 계산됩니다.

예를 들어 다음 코드 조각은 문서가 시작(로드)된 후 1분 30초 동안 반복되는 애니메이션을 중지합니다.

다음은 이 속성을 보여주는 데모입니다.
HTML:

결과

반복 횟수에 따른 애니메이션 동기화

이제 두 애니메이션 간의 동기화로 돌아가 보겠습니다. 실제로 SMIL에서는 애니메이션을 동기화하여 다른 애니메이션이 반복되는 횟수에 따라 하나의 애니메이션이 실행되도록 할 수 있습니다.

예를 들어, 특정 시간을 더하거나 빼서 다른 애니메이션을 n번째 반복한 후에 애니메이션을 시작할 수 있으며, 이 설정도 설정할 수 있습니다.

다음 예에서 직사각형 애니메이션은 원 애니메이션의 두 번째 반복에서 시작됩니다.

반복 횟수에 따른 동기화는 현재 모든 브라우저에서 구현되지 않으므로 안타깝게도 이 섹션에는 데모 버전이 제공되지 않습니다.

애니메이션 키프레임 값 관리: keyTimes 및 값

CSS에서는 애니메이션이 재생될 때 특정 키프레임의 애니메이션 속성이 취해야 하는 값을 지정할 수 있습니다.

예를 들어 요소를 왼쪽으로 이동하도록 애니메이션을 지정하는 경우 오프셋을 0에서 300까지 직접 변경하도록 지정하는 대신 다음과 같이 특정 프레임에서 오프셋이 특정 값을 갖도록 애니메이션을 적용할 수 있습니다. :

@keyframes 예 ( 0% ( 왼쪽: 0; ) 50% ( 왼쪽: 320px; ) 80% ( 왼쪽: 270px; ) 100% ( 왼쪽: 300px; ) )

0%, 20%, 80%, 100%는 애니메이션 프레임이고, 각 프레임의 블록에 있는 값은 각각에 대한 값입니다. 위에서 설명한 효과는 공이 튀는 애니메이션의 요소 중 하나입니다.

SMIL에서는 비슷한 방식으로 키프레임 값을 관리할 수 있지만 구문 자체는 완전히 다릅니다.

키프레임을 지정하려면 keyTimes 속성이 사용됩니다. 그리고 각 프레임의 애니메이션 속성 값을 지정하기 위해 값 속성이 사용됩니다. SMIL의 명명 규칙은 매우 편리합니다.

움직이는 원으로 돌아가 위에서 설명한 CSS 키프레임과 유사한 값을 사용하면 코드는 다음과 같습니다.

우리는 무엇을 했나요?

가장 먼저 주목해야 할 점은 키프레임의 시간과 중간값이 목록 형식으로 지정된다는 점입니다. keyTimes 속성은 애니메이션 단계를 제어하는 ​​데 사용되는 세미콜론으로 구분된 시간 값 목록입니다. 목록의 각 시간은 값 속성 목록의 값에 해당하며 해당 값이 애니메이션 기능에서 사용되는 시기를 결정합니다.

keyTimes 목록의 각 시간 값은 0에서 1(포함)까지의 십진수로 지정되며 애니메이션 요소 재생 시 비례 시간 이동을 나타냅니다. 따라서 keyTimes는 백분율이 아닌 소수로 정의한다는 점을 제외하면 CSS와 동일하게 작동합니다.

아래는 이 코드에 대한 데모입니다.
HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

값 목록을 사용하면 해당 목록에 지정된 값에 따라 애니메이션이 적용된다는 점에 유의해야 합니다. 이 경우 모든 from, to 및 by 속성은 무시됩니다.

사용자 정의 조정으로 애니메이션 템포 제어: calcMode 및 keySplines

이제 CSS와 SMIL의 비교로 돌아가겠습니다. 이미 CSS 애니메이션에 익숙하다면 SMIL의 구문과 개념을 훨씬 더 쉽게 이해할 수 있기 때문입니다.

CSS에서는 기본 애니메이션 타이밍을 재정의하고 animation-timing-function 속성을 사용하여 애니메이션을 제어하는 ​​사용자 정의 조정 함수를 지정할 수 있습니다.

타이밍 함수는 미리 정의된 여러 키워드 또는 3차 bzier 함수 중 하나로 지정할 수 있습니다. 후자는 Leia Verou가 개발한 것과 같은 도구를 사용하여 만들 수 있습니다.

SMIL에서 애니메이션 템포는 calcMode 속성을 사용하여 설정됩니다. 기본적으로 animateMotion( 나중에 다시 다루겠습니다). 선형 값 외에도 불연속, 페이싱 또는 스플라인 값을 설정할 수도 있습니다.

  • 이산은 애니메이션 함수가 보간 없이 한 값에서 다른 값으로 이동하도록 지정합니다. 이는 CSS steps() 함수와 유사합니다.
  • paced는 중간 값을 무시하고 keyTimes에 정의된 애니메이션 타이밍을 변경한다는 점을 제외하면 선형과 유사합니다.
  • 스플라인은 3차 베지어 스플라인에 의해 정의된 시간 함수에 따라 값 목록의 한 값에서 다른 값으로 보간됩니다. 스플라인 지점은 keyTimes 속성에 정의되고, 각 간격의 전환 지점은 keySplines 속성에 정의됩니다.

제가 새로운 속성인 keySplines를 언급한 것을 눈치채셨을 것입니다. keySplines 속성은 무엇을 합니까?

이번에도 CSS와 유사합니다.

CSS에서는 전체 애니메이션에 대해 단일 애니메이션 템포를 지정하는 대신 각 키프레임 내에서 애니메이션 템포를 지정할 수 있습니다. 이를 통해 각 애니메이션 프레임의 흐름을 더 효과적으로 제어할 수 있습니다. 이 기능을 사용하는 예는 공이 튀는 효과를 만드는 것입니다. 이에 대한 키프레임은 다음과 같습니다.

@keyframes 바운스( 0%( 상단: 0; 애니메이션 타이밍 기능:이지 인; ) 15%( 상단: 200px; 애니메이션 타이밍 기능: 완화; ) 30%( 상단: 70px; 애니메이션 타이밍 -기능: 이즈인; ) 45%(상단: 200px; 애니메이션 타이밍 기능: 이즈 아웃; ) 60%(상단: 120px; 애니메이션 타이밍 기능: 이즈인; ) 75%(상단: 200px ; 애니메이션 타이밍 기능:이지 아웃; ) 90%(상단: 170px; 애니메이션 타이밍 기능: 완화; ) 100%(상단: 200px; 애니메이션 타이밍 기능: 완화; ) )

조정 함수 대신 해당 큐빅 베지어 함수를 사용할 수 있습니다.

  • easy-in = 큐빅 베지어(0.47, 0, 0.745, 0.715);
  • 완화 = 3차 베지어(0.39, 0.575, 0.565, 1)

동일한 튀는 공 효과를 만들기 위해 주황색 원에 대한 주요 시간 간격과 값 목록을 정의하는 것부터 시작하겠습니다.

요소를 마우스로 클릭하면 애니메이션이 시작되고 최종 값에 도달하자마자 정지됩니다. 다음으로, 각 키프레임의 템포를 설정하기 위해 keySplines 속성을 추가하겠습니다.

keySplines 속성은 다양한 템포에서 간격을 제어하는 ​​3차 베지어 함수를 정의하는 keyTimes 목록과 연관된 bzier 중단점 세트를 사용합니다. 속성 값은 세미콜론으로 구분된 제어점 설명 목록입니다.

각 제어점 설명은 x1 y1 x2 y2의 네 가지 값 세트로, 하나의 시간 세그먼트에 대한 bzier 제어점의 좌표를 설명합니다. 값은 0과 1 사이여야 하며 calcMode는 spline으로 설정되어야 합니다. 그렇지 않으면 속성이 무시됩니다.

3차 베지어 함수를 값으로 사용하는 대신 keySplines는 곡선을 그리는 데 사용되는 두 제어점의 좌표를 사용합니다. Leah의 도구에서 가져온 아래 스크린샷에서 이러한 제어점을 볼 수 있습니다.

스크린샷에는 각 지점의 좌표도 표시되며, 각 좌표 값은 설명하는 지점과 동일한 색상을 갖습니다. keySplines 속성의 경우 이는 각 애니메이션 키프레임의 템포를 결정하는 데 사용할 값입니다.

SMIL에서는 이러한 값을 쉼표와 추가 공백 또는 공백으로 구분할 수 있습니다. 해당 세그먼트를 정의하는 keyTimes 값은 " 기준점" b;zier 및 keySplines 값은 중단점입니다. 따라서 체크포인트는 keyTimes보다 1 작은 값으로 설정되어야 합니다.


튀는 공 예제로 돌아가면 Ease-In 및 Ease-Out 기능에 대한 제어점 좌표가 다음 이미지에 표시됩니다.
따라서 이 모든 것을 SVG 애니메이션 요소로 변환하면 다음 코드를 얻게 됩니다.

아래는 데모입니다. 최신 버전에는 데모가 제대로 작동하지 못하게 하는 버그가 있으므로 Chrome이 아닌 Firefox에서 실행해야 합니다.

HTML:

원을 클릭하면 애니메이션이 시작됩니다.

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

중간 값 없이 전체 애니메이션에 대한 일반 속도 조정 기능만 지정하려는 경우에도 keyTimes 속성을 사용하여 키프레임을 지정해야 하지만 0인 시작 및 끝 키프레임만 지정하면 됩니다. 1 - 중간 값이 없습니다.

추가 및 누적된 애니메이션: 추가 및 누적

때로는 이전 애니메이션이 끝난 곳에서 시작하는 애니메이션을 정의해야 할 때도 있습니다. 또는 이전 애니메이션의 누적 합계를 값으로 사용하여 재생을 시작하는 애니메이션입니다. 이를 위해 SVG에는 적절하게 이름이 지정된 두 가지 속성(additive 및 acquire )이 있습니다.

너비를 늘리려는 요소나 길이를 늘리려는 선이 있다고 가정해 보겠습니다. 또는 특정 간격으로 단계적으로 이동하려는 요소가 있다고 가정해 보겠습니다. 이 기능은 애니메이션을 반복할 때 특히 유용합니다.

다른 애니메이션과 마찬가지로 시작 및 끝 값을 지정해야 합니다. 동시에 추가 속성을 합계로 설정하면 이러한 각 값은 애니메이션되는 속성의 원래 값과 연결됩니다.

그럼 우리 서클로 돌아가 봅시다. 이를 위해 초기 위치 cx는 50입니다. 값을 "0"에서 "100"으로 설정하면 실제로 0은 초기 값 50을 의미하고 100은 초기 값 50+100을 의미합니다. 즉, 실제로는 “from="50″ to="150" 으로 설정한 것으로 나타났습니다.

이 작업을 수행하면 다음과 같은 결과를 얻게 됩니다.

HTML:

원을 클릭하면 애니메이션이 시작됩니다.

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

이것이 덧셈 속성이 하는 전부입니다. 단순히 from 및 to 값이 현재 속성 값과 연관되는지 여부를 결정합니다. 속성은 sum 및 replacement 두 값 중 하나를 사용합니다.

후자의 값이 기본값이며, 이는 일반적으로 지정된 from 및 to 값이 현재/원래 값을 재정의하여 결국 애니메이션 시작 시 애니메이션 요소의 위치가 갑자기 변경될 수 있음을 의미합니다.

(위의 예에서 sum을 바꾸기로 바꾸면 무슨 일이 일어나는지 볼 수 있습니다.).

하지만 첫 번째 애니메이션 루프가 끝난 곳에서 두 번째 애니메이션 루프가 시작되도록 값을 추가하려면 어떻게 해야 할까요? 이를 위해서는 축적 속성이 도움이 될 것입니다.

누적 속성은 속성의 이전 종료 값이 고려되는지 여부를 제어합니다. 기본적으로 해당 값은 none 입니다. 이는 애니메이션이 반복될 때 이전 반복의 끝을 계산하지 않고 맨 처음부터 반복한다는 의미입니다.

그러나 이를 sum 으로 설정할 수 있습니다. 이는 각각의 새로운 애니메이션 주기가 이전 주기가 끝난 위치에 연결된다는 의미입니다.

따라서 이전 애니메이션으로 돌아가서 acquire="sum" 을 지정하면 다음과 같은 결과를 얻게 됩니다.
HTML:

원을 클릭하면 애니메이션이 시작됩니다.

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

대상 속성의 값이 추가를 지원하지 않거나 애니메이션 요소가 반복되지 않는 경우 누적 속성은 무시됩니다. 애니메이션 기능에 to 속성이 하나만 지정된 경우에도 무시됩니다.

end를 사용하여 애니메이션의 끝 지정

애니메이션이 시작되어야 하는 시점을 지정하는 것 외에도 end 속성을 통해 애니메이션이 종료되어야 하는 시점을 지정할 수도 있습니다. 예를 들어 애니메이션이 무한정 반복되도록 설정한 다음 다른 요소가 애니메이션을 시작하면 중지할 수 있습니다.

end 속성은 start 속성과 동일한 값을 갖습니다. 절대 또는 상대 시간 값/간격, 반복 값, 이벤트 값 등을 지정할 수 있습니다.

예를 들어 다음 데모에서는 주황색 원이 캔버스 반대편으로 30초에 걸쳐 천천히 이동합니다. 녹색 원에도 애니메이션이 적용되지만 애니메이션은 클릭할 때만 시작됩니다.

녹색 원의 애니메이션이 시작되면 주황색 원의 애니메이션이 종료됩니다. 따라서 녹색 원을 클릭하면 주황색 원이 중지됩니다.

HTML:

CSS:

svg(테두리: 3px 단색 #eee; 디스플레이: 블록; 여백: 1em 자동; )

결과

물론, 동일한 요소에 적용된 두 개의 애니메이션에 대해 동일한 애니메이션 동기화가 수행될 수 있습니다. 예를 들어, 색상이 한 값에서 다른 값으로 무한정 변경되는 원 색상 애니메이션을 설정한다고 가정해 보겠습니다.

그런 다음 마우스 커서로 클릭하면 원이 움직이도록 설정하는 애니메이션입니다. 이제 요소를 클릭하고 요소가 움직이기 시작하면 색상 변경이 중지되도록 설정하겠습니다.
HTML:

CSS:

svg(테두리: 3px 단색 #eee; 디스플레이: 블록; 여백: 1em 자동; )

결과

여러 시작 및 끝 값을 사용하여 애니메이션 간격 정의

실제로 시작 속성과 끝 속성 모두 쉼표로 구분된 값 목록을 허용합니다. 시작 속성의 각 값은 종료 속성의 해당 값을 가지며 활성 및 비활성 애니메이션 간격을 만듭니다.

이는 자동차가 움직이고 있는지 정지해 있는지에 따라 바퀴가 일정 시간 동안 활성화되거나 비활성화되는 움직이는 자동차로 생각할 수 있습니다.

적절한 효과를 적용하여 움직이는 자동차의 애니메이션을 만들 수도 있습니다. 하나는 자동차를 이동하거나 추가 및 누적 애니메이션을 사용하는 경로를 따라 이동하는 것입니다. 두 번째는 움직임과 동기화되는 간격으로 바퀴를 회전시키는 것입니다.

여러 애니메이션 시작 및 종료 시간(예: 간격)을 설정하는 예는 다음 데모입니다. 여기서 직사각형은 특정 간격으로 회전하여 활성에서 비활성으로 전환됩니다.
(애니메이션을 놓친 경우 데모를 다시 시작하세요).
HTML:

CSS:

svg(테두리: 3px 단색 #eee; 디스플레이: 블록; 여백: 1em 자동; )

결과

위의 예에서는 요소를 사용했습니다. 직사각형의 회전을 설정합니다. 다음 섹션에서 이 요소에 대해 더 자세히 설명하겠습니다.

또한,peatCount를 inlimited로 설정하더라도 종료 값으로 재정의되어 애니메이션이 무한정 반복되지는 않습니다.

min 및 max를 사용하여 요소의 기간 제한

애니메이션이 반복되는 횟수나 시간을 제한할 수 있는 것처럼 애니메이션의 지속 시간도 제한할 수 있습니다.

min 및 max 속성은 각각 최소 및 최대 애니메이션 기간 값을 지정합니다. 이는 요소의 지속 시간에 대한 하한 및 상한을 조정하는 기능을 제공합니다. 두 속성 모두 시간을 허용합니다.

min은 요소의 지속 시간으로 측정되는 애니메이션의 최소 지속 시간 값을 지정합니다. 이 속성의 값은 0보다 크거나 같아야 합니다( 작업 기간이 전혀 제한되지 않는 기본값).

max에서 시간 값은 요소의 지속 시간으로 측정된 작업 지속 시간의 최대값 값을 지정합니다. 해당 값은 0보다 커야 합니다. max의 기본값은 무한정입니다. 행동 기간을 전혀 제한하지 않습니다.

두 속성이 모두 지정된 경우 최대값은 최소값보다 크거나 같아야 합니다. 이 요구 사항이 충족되지 않으면 두 속성이 모두 무시됩니다.

그러면 요소의 동작 지속 시간을 결정하는 것은 무엇입니까? 앞서 애니메이션 반복에 지속 시간이 있다고 언급했는데, 이는 " 단순 기간", 이는 반복되지 않는 애니메이션의 지속 시간입니다( dur로 표시).

그렇다면 이 모든 것이 어떻게 함께 작동합니까? 우선순위가 더 높은 것은 무엇입니까? 그리고 end 속성은 어떻습니까? 값을 다시 할당합니까, 아니면 그냥 애니메이션을 종료합니까?

모두 이렇게 작동합니다. 브라우저는 먼저 dur,peatCount,repeatDur,end 값을 기반으로 활동 기간을 계산합니다. 그런 다음 최소값과 최대값에 따라 기간 계산이 시작됩니다.

첫 번째 계산 단계의 결과가 두 번째 단계에서 계산된 간격 내에 있으면 처음 계산된 기간이 그대로 유지되며 변경되지 않습니다. 그렇지 않으면 두 가지 시나리오가 가능합니다.

  • 처음 계산된 기간이 최대값보다 큰 경우 요소의 기간은 최대값과 동일한 것으로 결정됩니다.
  • 처음 계산된 지속 시간이 최소값보다 작은 경우 요소의 지속 시간은 최소값과 동일하며 요소의 동작은 다음과 같습니다.
  • 반복 기간 ( 또는 요소가 반복되지 않는 경우 단순 기간) 요소가 min 보다 크면 해당 요소는 작업 기간의 표준 시간( min 포함)에 재생됩니다.
  • 그렇지 않으면 요소가 표준 반복 기간 동안 재생됩니다( 또는 요소가 반복되지 않는 경우 단순 기간), 채우기 속성의 값에 따라 정지되어 전혀 출력되지 않습니다.

이는 브라우저가 실제로 활동 기간을 어떻게 계산하는지에 대한 질문으로 이어집니다. 간결성을 위해 자세한 내용은 다루지 않겠습니다.

그러나 사양에는 dur,peatCount,repeatDur 및 end 속성의 다양한 조합과 각 조합에 따라 애니메이션 지속 시간이 어떻게 결정되는지 보여주는 매우 자세한 테이블이 포함되어 있습니다.

이 표를 보고 다음에서 자세한 정보를 얻을 수 있습니다. 사양의 이 섹션.

마지막으로, 요소가 상위 요소가 시작되기 전에 시작하도록 정의된 경우( 예를 들어 음수 오프셋 값을 사용하는 경우)의 경우 최소 기간은 첫 번째 단계에서 계산된 값에 따라 결정되며 상위 요소의 유효 기간에는 포함되지 않습니다.

즉, 최소값은 요소의 애니메이션에 눈에 띄는 영향을 미치지 않습니다.

: 경로 변환

SMIL을 통해 애니메이션화할 수 있는 속성 중 하나( 하지만 CSS를 통해 애니메이션을 설정할 수는 없습니다.)는 다음의 속성입니다. SVG - 디 ( "데이터"의 줄임말).

d 속성에는 생성 중인 모양 또는 모양의 윤곽선을 정의하는 데이터가 포함됩니다. 이 윤곽선 데이터는 최종 윤곽선을 구성하는 점, 호, 선을 그리는 위치와 방법을 브라우저에 알려주는 일련의 명령과 좌표로 구성됩니다.

이 속성에 애니메이션을 적용하면 SVG 윤곽선을 변환하고 효과를 만들 수 있습니다. 인물의 변신.

그러나 모양을 변환할 수 있으려면 시작, 끝 및 모든 중간 모양의 정점/점 수가 동일해야 하며 동일한 순서로 나타나야 합니다. 서로 다른 모양의 정점 개수가 일치하지 않으면 애니메이션이 작동하지 않습니다.

그 이유는 실제로는 꼭지점을 이동하고 그 위치를 보간함으로써 모양의 변형이 이루어지기 때문입니다. 따라서 정점 하나가 누락되거나 전체 출력 순서와 일치하지 않으면 윤곽선을 보간할 수 없습니다.

SVG 윤곽선에 애니메이션을 적용하려면 attributeName 속성을 d로 설정한 다음 시작 및 끝 모양을 정의하는 from 및 to 값을 설정해야 합니다. 또한 값 속성을 사용하여 변환 시 경로가 취해야 하는 중간 값을 정의할 수도 있습니다.

간결성을 위해 이 작업을 수행하는 방법에 대해서는 자세히 설명하지 않겠습니다. 대신, 당신은 읽을 수 있습니다 Noah Blon의 훌륭한 기사입니다., 그는 어떻게 변형 인물을 만들었는지 설명합니다. . Noah가 만든 애니메이션의 데모는 다음과 같습니다.
HTML:

CSS:

본문( 높이: 100vh; 텍스트 정렬: 중앙; 상자 크기: 테두리 상자; 패딩 상단: 계산(50vh - 56px); ) img, svg( 디스플레이: 인라인 블록; 수직 정렬: 중간; ) svg ( 높이: 38px; 너비: 38px; 디스플레이: 인라인 블록; )

// 이미지를 삽입하면 동기화를 유지하는 데 도움이 됩니다. $(document).ready(function())( $("img").attr("src", "http://dab1nmslvvntp.cloudfront.net/wp-content/ 업로드 /2014/08/1407310358spinner-cropped.gif"); ));

결과

다음은 Felix Ornoy의 모핑의 또 다른 예입니다.
HTML:

CSS:

결과

변환 경로를 사용하여 주변 배경을 잘라내고 특정 그림을 정의할 수도 있습니다. Heather Bushel의 예는 다음과 같습니다.
HTML:

SCSS:

$베이스: #C8C8A9; $기본: #FE4365; 본문( 배경: $base; 텍스트 정렬: 중앙; ) svg( 위치: 절대; 위쪽: 50%; 왼쪽: 50%; 여백-상단: -60px; 여백-왼쪽: -60px; ) .logo( 채우기: $primary; ) .clip ( 애니메이션: 슬라이드 8s 무한; ) @keyframes 슬라이드 ( from ( 변환:translateY(-135px); ) 50% ( 변환:translateY(-5px); ) to ( 변환:translateY(-135px) ; ) )

결과

자유 경로를 따른 애니메이션: 요소

- 제가 SMIL 애니메이션에서 가장 좋아하는 요소입니다. 이를 사용하여 경로를 따라 요소를 이동할 수 있습니다. 지금 설명할 두 가지 방법 중 하나를 사용하여 모션 경로를 지정한 다음 해당 경로를 따라 이동하도록 요소를 설정할 수 있습니다.

요소 앞서 언급한 요소와 동일한 속성과 함께 keyPoints, 회전 및 경로라는 세 가지 속성을 추가로 사용합니다. 또한 calcMode 속성과 관련된 한 가지 차이점이 있습니다. 요소의 경우 기본값은 선형이 아닌 속도 조절입니다.

path 속성을 사용하여 이동 경로 지정

path 속성은 이동 경로를 나타내는 데 사용됩니다. 이는 경로 요소의 d 속성과 동일한 형식으로 표시되고 동일한 방식으로 해석됩니다.

경로를 따라 모션을 애니메이션화하는 효과는 연관된 객체의 현재 행렬에 추가 변환 행렬을 추가하는 것입니다. 이를 통해 다음을 계산하여 현재 사용자 좌표계의 x 및 y축을 따라 객체의 이동을 지정할 수 있습니다. 각 순간의 X 및 Y 값.

즉, 지정된 경로는 요소의 현재 위치를 기준으로 계산되며 경로 데이터를 사용하여 요소를 다른 경로 위치에 해당하는 복사본으로 변환합니다.

우리는 다음과 같은 경로를 따라 이동하도록 원에 애니메이션을 적용하고 싶습니다.


이 경로를 따라 원을 이동시키는 데 필요한 코드는 다음과 같습니다.

제가 주목하고 싶은 한 가지가 있습니다: 경로 데이터의 좌표입니다. 경로는 (M) 좌표가 (0, 0)인 지점으로 이동하는 것으로 시작되며, 그 후 다른 지점으로 곡선(c)을 설명하기 시작합니다.

이동 애니메이션의 시작 위치에 관계없이 점 (0, 0)이 실제로 원의 초기 위치라는 점을 이해하는 것이 중요합니다. 이는 좌표계의 왼쪽 위 모서리가 아닙니다. 위에서 언급했듯이 경로 속성의 좌표는 요소의 현재 위치에 연결됩니다!

위 코드의 출력은 다음과 같습니다.
HTML:

CSS:

* ( 상자 크기: 테두리 상자; ) .cont ( 높이: 100vh; 패딩: 20vmin; -webkit-filter: 대비(10); 배경색: 흰색; ) svg ( 너비: 100%; 높이: 100% ; 불투명도: 0.9; -webkit-filter: 흐림(3px);)

결과

(0, 0) 이외의 좌표를 가진 지점에서 경로의 시작을 지정한 경우 원은 애니메이션이 시작되기 전에 지정된 좌표의 지점으로 급격하게 점프합니다.

예를 들어 Illustrator에서 경로를 그린 다음 모션 경로로 사용하기 위해 해당 경로의 데이터를 내보냈다고 가정해 보겠습니다. 이것이 제가 이 요소로 처음 작업했을 때 한 일입니다.); 내보낸 경로는 다음과 같습니다.

이 경우 경로의 시작점은 (100.4, 102.2)입니다. 이 데이터를 모션 경로로 사용한다면 원은 애니메이션이 시작되기 전에 갑자기 오른쪽으로 약 100단위, 아래로 102단위 점프한 다음 새 위치를 기준으로 경로를 따라 이동하기 시작합니다. 따라서 애니메이션을 위한 모션 경로를 준비할 때 데이터를 주의 깊게 확인하십시오.

from, by, to 및 값 속성( 만약 사용된다면)는 모션 경로를 나타내는 현재 캔버스의 모양을 나타냅니다.

요소를 사용하여 모션 경로 지정

이동 궤적을 지정하는 또 다른 방법도 있습니다. 연관된 경로 속성을 사용하는 대신 요소를 사용하여 외부 경로를 참조할 수 있습니다. . - 요소의 하위 요소 , xlink:href 속성을 사용하여 외부 경로에 연결할 수 있습니다.

운동의 궤적 문서의 어느 위치에서나 정의할 수 있습니다. 요소 내부에서 정의할 수도 있습니다. 캔버스에 전혀 렌더링되지 않습니다. 대부분의 경우 요소가 이동하는 경로를 표시하려고 하기 때문에 다음 예제에서는 경로를 표시합니다.

사양에 따라 다음 사항에 유의하십시오.

모양의 다양한 점(x, y)은 객체와 관련된 추가 CTM 변환 행렬을 제공하여 모양(x, y) 값 계산을 통해 사용자의 현재 좌표계의 x 및 y 축을 따라 이동합니다. 각 시간 세그먼트에 대해. 이러한 방식으로 연결된 개체는 일정 시간에 걸쳐 이동되며 개체의 모션 경로는 현재 사용자의 원래 좌표계로 이동됩니다. 추가 변환은 대상 요소의 변환 속성 덕분에 모든 변환 전환 시 적용되거나 대상 요소의 animateTransform 요소 덕분에 해당 속성의 애니메이션 전환 시 적용됩니다.

다시 말하지만, 원은 경로 데이터의 좌표에 따라 다른 지점에서 다른 원으로 "증식"하거나 "변형"합니다.

다음 예에서는 캔버스 중앙에 경로가 있습니다. 원은 경로의 시작 부분에 배치됩니다. 그러나 이 경로를 적용하면 원은 현재 위치에서 움직이지 않습니다. 더 나은 이해를 위해 데모 버전을 시청하세요. 원을 클릭하면 애니메이션이 적용됩니다.

HTML:

원을 클릭하면 애니메이션이 시작됩니다.

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

원이 어떻게 같은 모양을 따르지만 다른 위치에 있는지 확인하세요. 이는 경로 데이터 값에 따라 원 위치가 변환되기 때문입니다.

이 문제를 해결하는 한 가지 방법은 경로 데이터를 사용하여 변환할 때 원이 움직이기 시작하고 예상대로 움직이도록 원을 (0, 0)에 설정하는 것입니다.

또 다른 방법은 경로가 적용되기 전에 원의 좌표가 0으로 설정되도록 "재설정"하는 변환을 적용하는 것입니다.

아래는 닫힌 경로를 사용하고 모션 애니메이션을 무한히 반복하는 위 데모의 수정된 버전입니다.

HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

규칙 재정의

animateMotion에 대해 동일한 작업을 수행하는 방법은 여러 가지가 있으므로 규칙을 재정의하여 어떤 값이 다른 값으로 대체되는지 지정하는 것이 합리적입니다.

animateMotion 규칙 재정의:

  • 모션 경로를 정의할 때 mpath 요소는 경로 속성을 재정의하고, 이는 차례로 값을 재정의하고 값은 from, by 및 to를 재정의합니다.
  • keyTimes 속성에 해당하는 지점을 정의하는 경우 keyPoints 속성은 path 속성을 재정의하고, path는 값을 재정의하며, 값은 from , by , to 를 재정의합니다.

회전을 사용하여 모션 경로를 따라 요소 방향 설정

이전 예에서 애니메이션이 경로를 따라 이동하도록 설정한 요소는 원이었습니다. 하지만 자동차 아이콘과 같이 특정 방향을 가진 요소에 애니메이션을 적용한다면 어떻게 될까요?

다음 예의 자동차 아이콘은 Freepik에서 만든 것입니다.

이 예에서는 그룹을 구성하는 요소가 포함된 식별자 "car"가 있는 그룹으로 원을 대체했습니다.

그런 다음 위에서 언급한 경로 이동 문제를 피하기 위해 자동차를 일정 거리만큼 이동하는 변환을 적용하여 초기 위치가 (0, 0)으로 설정되도록 했습니다.

변환 내부의 값은 실제로 자동차의 첫 번째 궤적이 놓이기 시작하는 지점의 좌표입니다( 이동 명령 M 직후).

그런 다음 자동차가 궤적을 따라 움직이기 시작합니다. 하지만... 이 움직임은 다음과 같습니다.
HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

차량의 방향은 고정되어 있으며 궤적을 따라 어떤 지점에서도 변경되지 않습니다. 이를 변경하려면 회전 속성을 사용해야 합니다.

회전 속성은 다음 세 가지 값 중 하나를 사용합니다.

  • 자동: 객체가 방향( 저것들. 탄젠트 벡터) 운동 궤적;
  • 자동 역방향: 객체가 방향( 저것들. 탄젠트 벡터) 이동 궤적 + 180도;
  • 숫자: 일정한 회전 변환이 대상 요소에 적용되도록 지정합니다. 여기서 회전 각도는 지정된 숫자(도)와 같습니다.

위 예에서 자동차의 방향을 조정하기 위해 회전 값을 auto 로 설정하는 것부터 시작하겠습니다. 그리고 우리는 다음과 같은 결과를 얻습니다.

HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

자동차가 경로 영역 외부로 이동하도록 하려면 자동 후진 값을 사용하여 수행합니다.

원을 클릭하면 애니메이션이 적용됩니다.

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

훨씬 나아졌지만 여전히 한 가지 문제가 있습니다. 차가 거꾸로 운전하고 있다는 것입니다! 이를 변경하려면 자체 Y축을 따라 뒤집어야 합니다. 이는 이 축을 따라 "-1"만큼 크기를 조정하여 수행할 수 있습니다.

따라서 ID car 를 사용하여 g에 변환을 적용하면 자동차가 원하는 방식으로 움직일 것입니다. 크기 변환은 이전에 적용한 변환과만 번갈아 이루어져야 합니다.

최종 데모는 다음과 같습니다.
HTML:

CSS:

svg ( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) p ( 색상: #aaa; 텍스트 정렬: 중앙; 여백: 2em 0; )

결과

키포인트를 사용하여 모션 경로에서 애니메이션 거리 제어

keyPoints 속성을 사용하면 지정된 각 keyTimes 값에 대해 모션 경로로부터의 거리를 지정할 수 있습니다. keyPoints 속성이 지정되면 값 속성 배열이나 경로 속성 포인트에 지정된 포인트가 아닌 keyPoints 값에 keyTimes가 적용됩니다.

keyPoints는 0에서 1까지 세미콜론으로 구분된 십진수 값 목록을 사용하고 해당 keyTimes 값으로 지정된 시간에 객체가 모션 경로에서 얼마나 멀리 움직여야 하는지를 지정합니다.

거리 계산은 브라우저 알고리즘에 의해 결정됩니다. 목록의 각 후속 값은 thekeyTimes 속성 목록의 값에 해당합니다. keyPoints 목록이 지정되면 keyTimes 목록과 정확히 동일한 개수의 값이 포함되어야 합니다.

이 글을 쓰는 시점에는 Chrome 및 Firefox에서 keyPoints 속성이 지원되지 않습니다. 앞서 언급한 사양의 다른 부분과 마찬가지로 아직 구현되지 않았습니다.

임의의 경로를 따라 텍스트 이동

사용자 정의 경로를 따라 텍스트를 이동하는 것은 경로를 따라 다른 SVG 요소를 이동하는 것과 다릅니다. 텍스트에 애니메이션을 적용하려면 요소를 사용해야 합니다. , 하지만 .

먼저 경로를 따라 텍스트를 배치해 보겠습니다. 이는 요소를 중첩하여 수행할 수 있습니다. 요소 내부 .

경로를 따라 배치될 텍스트는 요소 내부에 정의됩니다. , 의 자녀가 아닌 .

그런 다음 textPath는 이전 예제에서와 마찬가지로 사용하려는 실제 경로를 참조합니다. 경로는 유사하게 캔버스에 표시되거나 내부적으로 정의될 수 있습니다. . 아래 코드를 확인하세요.
HTML:

경로를 따라 배치된 텍스트입니다.

CSS:

결과

이 경로를 따라 움직이는 텍스트에 애니메이션을 적용하려면 요소를 사용합니다. startOffset 속성에 애니메이션을 적용합니다.

startOffset은 경로를 따라 텍스트의 오프셋을 표시합니다. 0%는 여행의 시작입니다. 100%가 끝입니다. 예를 들어 오프셋이 50%로 설정된 경우 텍스트는 경로 중간에서 시작됩니다. 우리가 다음에 무엇을 할 것인지 이미 짐작하신 것 같습니다.

startOffset에 애니메이션을 적용하여 경로를 따라 이동하는 텍스트의 효과를 만듭니다. 다음 데모의 코드를 살펴보세요.

HTML:

경로를 따라 배치된 텍스트입니다.

CSS:

svg( 테두리: 3px 솔리드 #eee; 디스플레이: 블록; 여백: 1em 자동; ) 텍스트( 채우기: deepPink; 글꼴 크기: 2em; )

결과

애니메이션 변환: 요소

요소 대상 요소의 변환 속성에 애니메이션을 적용하여 애니메이션이 이동, 크기 조정, 회전 및/또는 기울이기를 제어할 수 있도록 합니다. 요소에 대해 나열된 것과 동일한 속성을 허용합니다. , 추가 속성: type .

type 속성은 애니메이션을 적용하는 변환 유형을 지정하는 데 사용됩니다. 다음 다섯 가지 값 중 하나를 사용합니다. 번역, 크기 조정, 회전, 기울이기X그리고 스큐Y .

from, by 및 to 속성은 이 변환 유형에 사용할 수 있는 동일한 구문을 사용하여 표현된 값을 취합니다.

  • + type="translate" 의 경우 각 개별 값은 다음과 같이 표현됩니다. [,];
  • + type="scale" 의 경우 각 개별 값은 다음과 같이 표현됩니다. [,];
  • + type="rotate"의 경우 각 개별 값은 [ ];
  • + type="skewX" 및 type="skewY" 의 경우 각 개별 값은 다음과 같이 표현됩니다. .

요소를 사용하여 분홍색 직사각형을 회전했던 이전 데모로 돌아가 보겠습니다. . 회전 코드는 다음과 같습니다.

from 및 to 속성은 회전 각도(시작 및 끝)와 회전 중심을 지정합니다. 물론 두 경우 모두 회전 중심은 동일하게 유지됩니다. 중심을 지정하지 않으면 SVG 캔버스의 왼쪽 상단이 됩니다. 위 코드의 데모는 다음과 같습니다.
HTML:

CSS:

svg(테두리: 3px 단색 #eee; 디스플레이: 블록; 여백: 1em 자동; )

결과

다음은 Gabriel이 만든 단일 animateTransform을 사용한 또 다른 재미있는 예입니다.

HTML:

CSS:

* ( 여백: 0; 패딩: 0; ) html, body ( 높이: 100%; ) body ( 배경: #FC0; ) svg ( 위치: 고정; 위쪽: 20%; 높이: 60%; 왼쪽: 20%; 너비: 60%; )

결과

단일 변환을 애니메이션화하는 것은 매우 간단하지만 여러 변환을 활성화하면 상황이 정말 복잡하고 혼란스러울 수 있습니다. 특히 하나의 animateTransform 요소가 다른 요소를 재정의할 수 있기 때문에 일관된 일련의 효과 대신 완전히 반대되는 결과가 나올 수 있습니다.

이는 SVG 좌표계와 변환이 얼마나 복잡한지에 추가됩니다. 다양한 특수 사례가 있을 수 있으며 이에 대한 고려 사항은 이 기사의 범위를 벗어납니다.

SVG를 변환하려면 CSS 변환을 사용하는 것이 좋습니다. 최신 솔루션은 SVG와 잘 작동하므로 SVG에서 변환을 애니메이션화하는 데 SMIL이 전혀 필요하지 않을 수도 있습니다.

요소

set 요소는 특정 시간에 대한 속성 값을 설정하는 간단한 방법을 제공합니다. 문자열 및 부울과 같이 보간할 수 없는 속성을 포함하여 모든 유형의 속성을 지원합니다.

set 요소는 추가할 수 없습니다. 추가 및 누적된 속성은 허용되지 않으며, 지정 시 무시됩니다.

왜냐하면 특정 시간에 대한 특정 값으로 요소를 설정하는 데 사용되지만 이 자습서의 앞부분에서 설명한 모든 속성을 허용하지는 않습니다. 예를 들어, from 또는 by 속성은 해당 값이 일정 기간 동안 점진적으로 변경되지 않기 때문에 포함되지 않습니다.

세트 요소의 경우 대상 요소, 속성 이름 및 유형, 대상 값, 타이밍 애니메이션을 지정할 수 있으며 다음을 사용하여 제어할 수 있습니다. 시작, 지속 기간, 종료, 최소, 최대, 다시 시작, 반복 카운트, 반복 지속그리고 채우십시오.

다음은 마우스 클릭 후 회전하는 직사각형의 색상을 파란색으로 설정하는 예입니다. 색상은 3초 동안 파란색으로 유지된 후 원래 값으로 돌아옵니다. 직사각형을 클릭할 때마다 애니메이션이 시작되고 3초 동안 색상이 변경됩니다.

HTML:

CSS:

svg(테두리: 3px 단색 #eee; 디스플레이: 블록; 여백: 1em 자동; )

결과

애니메이션을 적용할 수 있는 요소, 속성 및 속성

모든 SVG 속성에 애니메이션을 적용할 수 있는 것은 아니며 애니메이션 요소를 사용하여 애니메이션을 적용할 수 있는 모든 속성에 애니메이션을 적용할 수 있는 것은 아닙니다.

애니메이션화할 수 있는 모든 속성의 전체 목록과 해당 속성을 애니메이션화하는 데 사용할 수 있는 요소는 다음을 참조하세요. SVG 애니메이션 사양의 이 섹션.

결론

SMIL은 많은 잠재력을 가지고 있으며, 저는 단지 몇 가지 기본 원칙과 기술적인 측면의 표면만 살펴보았습니다. 사양을 사용하면 특히 모핑 및 모양 변형을 통해 인상적인 효과를 많이 만들 수 있습니다.

  • 지도 시간

제 생각에는 많은 사람들이 차세대 게임 콘솔에 대한 리뷰를 본 것 같습니다. 다각형(Vox Media). 블루프린트 스타일로 그려진 콘솔은 다음과 같습니다:

리뷰는 멋지고 매우 특이하며 새 것처럼 보였습니다. 리뷰의 주요 기능(SVG 애니메이션, 유사한 작업을 직접 수행하는 방법)이 어떻게 구현되는지 컷 아래에서 확인할 수 있으며 경로 요소의 애니메이션 측면에서 오래된 SVG가 숨기는 다른 "비밀" 기능이 무엇인지 확인할 수 있습니다.

스트로크-다샤레이 보간, 이론

일반적으로 이러한 라인 애니메이션 기술은 새로운 것이 아니며 최근까지 SVG 및 이와 관련된 모든 것이 부당하게 망각에 맡겨졌지만 다행스럽게도 상황이 바뀌고 있습니다. 따라서 경로 요소의 스트로크-다샤레이 속성 덕분에 경로 요소에 애니메이션을 적용하는 트릭이 가능합니다. 이 속성을 사용하면 점선의 매개변수, 즉 획의 길이와 획 사이의 간격을 설정할 수 있습니다. 획의 길이를 선의 전체 길이와 동일하게 설정하면 일반적인 실선이 생성됩니다. 획의 길이를 0으로 설정하고 간격의 길이를 다시 선의 전체 길이와 동일하게 설정하면 보이지 않는 선이 생깁니다. 그리고 전체 선의 길이와 동일한 간격 길이로 획의 길이를 점차적으로 늘려서 그 그림을 시뮬레이션할 수 있습니다. 이 접근 방식을 사용하면 선의 시작 부분부터 그리기가 발생합니다. 갑자기 끝부터 그려야 하는 경우, 스트로크 대시오프셋이라는 속성을 하나 더 사용해야 합니다. 이 속성은 첫 번째 획의 오프셋을 지정합니다. 따라서 오프셋을 줄이고 획의 길이를 늘려 선 끝에서 그림을 그립니다.

에서 온 사람들 복스미디어그들은 하이브리드 옵션(내 생각에는 중복됨)을 사용했습니다. 그런데 그들이 어떻게 이 작업을 수행했는지 블로그에서 읽을 수 있습니다(그리고 읽어야 합니다): Polygon feature design: SVG animations for fun andprofit.

SVG 애니메이션 구현

안에 복스미디어그들은 부드러운 애니메이션을 위해 requestAnimationFrame을 사용할 것을 제안하지만 우리는 약간 다른 목표를 가지고 있으므로 더 간단한 경로를 택하여 D3.js 라이브러리와 여기에 구현된 지속 시간 기반 애니메이션을 사용하겠습니다.

다음은 기사 시작 부분부터 콘솔에 애니메이션을 적용하는 데 사용된 실제 작업 코드입니다.

대기열() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(ready); function Ready(error, xml) ( //HTML 문서에 svg 파일 추가 var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("너비"), svgHeight = svg.attr("높이"); var paths = svg.selectAll("경로") .call(전환) ; 함수 전환(경로) ( path.transition() .duration(5000) .attrTween("Stroke-dasharray", tweenDash) .each("end", function() ( d3.select(this).call(transition) ; )); // 무한 루프 ) function tweenDash() ( var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // 획 보간 -dasharray 속성 return function(t) ( return i(t); ); ) )


지금은 회전하지 않고 선을 따라 이동하는 것부터 시작하겠습니다.

대기열() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(ready); function Ready(error, xml) ( //HTML 문서에 svg 파일 추가 var importNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(경로); var marker = svg.append("circle"); marker.attr(" r", 7).attr("transform", "translate(" + startPoint + ")"); Transition(); //마커 함수 배치를 위한 경로 시작점 가져오기 pathStartPoint(path) ( var d = path.attr( "d"), dsplitted = d.split(" "); return dsplitted.split(","); ) 함수 전환() ( marker.transition() .duration(7500) .attrTween("transform",translateAlong( path.node())) .each("end", 전환);// 무한 루프 ) function moveAlong(path) ( var l = path.getTotalLength(); return function(i) ( return function(t) ( var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")";//마커 이동 ) ) ) )
여기서 pathStartPoint(path)는 경로 요소의 속성에서 선의 시작 좌표를 가져옵니다. TranslateAlong(path)에서 마커의 좌표는 보간기를 사용하여 설정됩니다. 예는 여기에서 볼 수 있습니다: D3.js를 사용하는 SVG 경로 요소에 따른 마커 애니메이션. 선 그리기 애니메이션과 마커 이동을 결합할 수도 있습니다. 이는 다음과 같이 보일 수 있습니다: D3.js II를 사용하여 SVG 경로 요소를 따르는 마커 애니메이션.

작업을 복잡하게 만들고 회전을 추가해 보겠습니다. 마커를 원에서 더 흥미로운 것으로 변경해 보겠습니다. 마커로 너비가 48이고 길이가 24인 로켓이 있습니다. 마커의 기본 앵커 포인트는 왼쪽 상단이므로 마커 중앙에 맞춰지도록 오프셋을 적용해야 합니다. 회전할 때도 이 점을 고려해야 합니다. 기본적으로 왼쪽 상단 모서리 주변에서도 발생하기 때문입니다. 변위를 정리 한 것 같습니다. 이제 직접 회전으로 넘어가겠습니다. 여기서 접선의 정의가 도움이 될 것이며 아크탄젠트를 사용하여 각도를 결정할 것입니다.

보간기를 정의하는 TranslateAlong(path) 함수는 다음과 같습니다:

함수 moveAlong(path) ( var l = path.getTotalLength(); var t0 = 0; return function(i) ( return function(t) ( var p0 = path.getPointAtLength(t0 * l);//이전 지점 var p = path.getPointAtLength(t * l);///현재 점 var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//접선 각도 t0 = t ; //중심을 로켓 중심으로 이동 var centerX = p.x - 24, centerY = p.y - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12 "+")"; ) ) )
구현은 여기에서 볼 수 있습니다.