1. 소개
이 섹션은 규범적인 내용이 아닙니다.
어떤 값이 변화하는 속도를 제어하는 것이 바람직한 경우가 많습니다. 예를 들어, 요소가 움직이는 속도를 점차 증가시키면 해당 요소가 모멘텀을 얻는 것처럼 무게감을 줄 수 있습니다. 이는 직관적인 사용자 인터페이스 요소를 만들거나 물리적 실체처럼 동작하는 만화 소품을 설득력 있게 구현할 때 사용할 수 있습니다. 반대로, 애니메이션이 분할된 휠처럼 항상 특정 위치에 세그먼트가 나타나도록 명확한 단계로 앞으로 이동하는 것이 바람직할 때도 있습니다.
이와 같이 그라데이션 보간의 변화율을 제어하면 오목하거나 볼록한 표면을 암시하거나, 줄무늬 효과를 내는 등 다양한 시각적 효과를 만들 수 있습니다.
이징 함수는 입력 진행 값을 받아서 이에 대응하는 변환된 출력 진행 값을 만들어내는 방식으로 이러한 값을 변환할 수 있는 방법을 제공합니다.
입력 진행 값이 0.7일 때, 이징 함수는 값을 스케일링하여 출력 진행 값 0.52를 만듭니다.
이 이징 함수를 애니메이션에 적용하면 처음에는 느리게 진행되다가 점차 빠르게 진행됩니다.
1.1. 값 정의
이 명세서는 값 정의 구문을 [CSS-VALUES-3]에서 사용합니다. 이 명세서에서 정의되지 않은 값 타입은 CSS 값 및 단위 [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈과의 조합으로 이러한 값 타입의 정의가 확장될 수 있습니다.
2. 이징 함수
이징 함수는 입력 진행 값을 받아서 출력 진행 값을 생성합니다.
이징 함수는 반드시 순수 함수여야 하며, 동일한 입력값 세트에 대해 항상 동일한 출력 진행 값을 반환해야 합니다.
입력 진행 값은 [-∞, ∞] 범위의 실수입니다. 일반적으로 입력 진행 값은 [0, 1] 범위이지만, 이징 함수를 연쇄적으로 사용할 때는 그렇지 않을 수 있습니다.
이징 함수를 연쇄적으로 사용하는 예로는 Web Animations [WEB-ANIMATIONS]이 있습니다. 여기서는 애니메이션 효과에 지정된 이징 함수의 출력이 키프레임 효과의 키프레임에 지정된 이징 함수의 입력이 될 수 있습니다. 이 경우, 키프레임 효과의 이징 함수 입력 값이 [0, 1] 범위를 벗어날 수 있습니다.
출력 진행 값은 [-∞, ∞] 범위의 실수입니다.
일부 이징 함수 유형은 추가적으로 불리언 before flag 입력을 받기도 하며, 이는 이후에 정의됩니다.
이 명세는 네 가지 유형의 이징 함수를 정의하며, 그 정의는 아래에 이어집니다.
이징 함수를 지정하는 구문은 다음과 같습니다:
테스트
2.1. 선형 이징 함수: linear()
선형 이징 함수는 이징 함수로서, points 사이를 선형적으로 보간합니다.
선형 이징 함수는 points, list 형태의 선형 이징 포인트를 가집니다. 처음에는 새로운 빈 list입니다.
선형 이징 포인트는 struct로 다음을 가집니다:
- input
-
숫자 또는 null
참고: 이 값은 선형 이징 함수를 생성하는 동안에만 null입니다.
- output
-
숫자
2.1.1. 구문
선형 이징 함수의 구문은 다음과 같습니다:
<linear-easing-function> = linear(<linear-stop-list>) <linear-stop-list> = [ <linear-stop> ]# <linear-stop> = <number> && <linear-stop-length>? <linear-stop-length> = <percentage>{1,2}
linear()는 선형 이징 함수로 파싱되며, 선형 이징 함수를 생성하는 과정에서 <linear-stop-list>가 list 형태의 <linear-stop>들로 전달됩니다.
2.1.2. 파싱
선형 이징 함수를 생성하려면 list 형태의 <linear-stop> stopList가 주어졌을 때, 다음을 수행합니다. 이 알고리즘은 선형 이징 함수 또는 실패를 반환합니다.
-
function을 새로운 선형 이징 함수로 설정합니다.
-
largestInput을 음의 무한대로 설정합니다.
-
stopList에 item이 두 개 미만이면 실패를 반환합니다.
-
각 stop에 대해 stopList에서 반복합니다:
-
point를 새로운 선형 이징 포인트로 생성하고, output을 stop의 <number> 값으로 설정합니다.
-
stop에 <linear-stop-length>가 있으면:
-
point의 input을 다음 중 더 큰 값으로 설정합니다: stop의 <linear-stop-length>의 첫 번째 <percentage> 값, 또는 largestInput.
-
largestInput을 point의 input으로 설정합니다.
-
stop의 <linear-stop-length>에 두 번째 <percentage>가 있으면:
-
extraPoint를 새로운 선형 이징 포인트로 생성하고, output을 stop의 <number> 값으로 설정합니다.
-
extraPoint의 input을 다음 중 더 큰 값으로 설정합니다: stop의 <linear-stop-length>의 두 번째 <percentage> 값, 또는 largestInput.
-
largestInput을 extraPoint의 input으로 설정합니다.
-
-
-
그렇지 않고 stop이 item 중 첫 번째이면:
-
point의 input을 0으로 설정합니다.
-
largestInput을 0으로 설정합니다.
-
-
그렇지 않고 stop이 item 중 마지막이면, point의 input을 1 또는 largestInput 중 더 큰 값으로 설정합니다.
-
-
function의 item들 중 input이 null인 연속 구간에 대해, input 값을 가장 가까운 앞뒤 points 중 null이 아닌 input 값 사이를 선형 보간하여 할당합니다.
-
function을 반환합니다.
2.1.3. 직렬화
예시:
-
linear(0, 0.25, 1)은 linear(0 0%, 0.25 50%, 1 100%)로 직렬화됩니다.
-
linear(0 20%, 0.5 10%, 1)은 linear(0 20%, 0.5 20%, 1 100%)로 직렬화됩니다.
-
linear(0, 0.25 25% 75%, 1)은 linear(0 0%, 0.25 25%, 0.25 75%, 1 100%)로 직렬화됩니다.
linear easing function (linearEasingFunction)의 직렬화된 계산 값을 얻으려면 아래를 수행합니다. 반환값은 문자열입니다.
2.1.4. 선형 이징 함수의 출력
선형 이징 출력 진행값 계산을 위해 linear easing function linearEasingFunction과 input progress value inputProgress가 주어졌을 때, 다음을 수행합니다. 반환값은 output progress value입니다.
-
points에 linearEasingFunction의 points를 할당합니다.
-
pointAIndex를 points에서 item 중 input이 inputProgress 이하인 마지막 인덱스로 설정합니다. 일치하는 값이 없으면 0으로 설정합니다.
-
pointAIndex가 points size - 1과 같다면, pointAIndex를 1 감소시킵니다.
참고: 이렇게 하면 비교할 "다음" 포인트가 항상 존재합니다.
-
pointA에 points[pointAIndex]를 할당합니다.
-
pointB에 points[pointAIndex + 1]을 할당합니다.
-
progressFromPointA에 inputProgress에서 pointA의 input을 뺀 값을 할당합니다.
-
pointInputRange에 pointB의 input에서 pointA의 input을 뺀 값을 할당합니다.
-
progressBetweenPoints에 progressFromPointA를 pointInputRange로 나눈 값을 할당합니다.
-
pointOutputRange에 pointB의 output에서 pointA의 output을 뺀 값을 할당합니다.
-
outputFromLastPoint에 progressBetweenPoints를 pointOutputRange와 곱한 값을 할당합니다.
-
pointA의 output에 outputFromLastPoint를 더한 값을 반환합니다.
2.1.5. 예시
예를 들어, linear(0, 0.25, 1)은 0에서 0.25, 그리고 1까지 선형적으로 이동하는 이징 함수를 만듭니다:
예를 들어, linear(0, 0.25 75%, 1)은 다음과 같은 이징 함수를 생성합니다. 전체 시간의 75%를 0에서 .25로, 마지막 25%를 .25에서 1로 변화합니다:
예를 들어, linear(0, 0.25 25% 75%, 1)은 linear(0, 0.25 25%, 0.25 75%, 1)과 동등하며, 다음과 같은 이징 함수를 만듭니다:
예를 들어, linear()를 사용해서 재사용 가능한 "bounce" 이징 함수를 만들 수 있습니다:
:root{ --bounce : linear ( /* 시작부터 1차 바운스까지 */ 0 , 0.063 , 0.25 , 0.563 , 1 36.4 % , /* 1차 바운스부터 2차 바운스까지 */ 0.812 , 0.75 , 0.813 , 1 72.7 % , /* 2차 바운스부터 3차 바운스까지 */ 0.953 , 0.938 , 0.953 , 1 90.9 % , /* 3차 바운스부터 끝까지 */ 0.984 , 1 100 % 100 % ); } .example{ animation-timing-function : var ( --bounce); }
정의 끝에 1 100% 100%
로 두 개의 최종 포인트를 만들어,
입력이 1보다 크더라도 항상 출력값이 1이 됩니다.
더 느린 애니메이션에서는 더 부드러운 결과를 위해 포인트를 더 많이 추가할 수 있습니다.
2.2. 선형 이징 키워드: linear
linear 키워드는 정체 선형 이징 함수를 생성하며, 출력 진행 값이 모든 입력에 대해 입력 진행 값과 동일합니다.
이는 linear(0, 1)과 동일한 결과를 냅니다.
참고: 이것은 선형 이징 함수를 생성하지만, linear 키워드 사용 시에는 항상 linear로 직렬화됩니다. 반면 함수형 linear(0, 1)은 linear(0 0%, 1 100%)로 직렬화됩니다. 이 규칙은 직렬화에 정의되어 있습니다.
2.3. 큐빅 베지어 이징 함수: ease, ease-in, ease-out, ease-in-out, cubic-bezier()
큐빅 베지어 이징 함수는 네 개의 실수로 정의되는 이징 함수의 한 종류이며, 이 네 개의 값은 큐빅 베지어 곡선의 두 제어점 P1과 P2를 지정합니다. 곡선의 시작점 P0와 끝점 P3는 각각 (0, 0)과 (1, 1)으로 고정되어 있습니다. P1과 P2의 x 좌표는 [0, 1] 범위로 제한됩니다.
곡선의 형태는 제어점 P1과 P2의 위치에 의해 결정됩니다.
입력 진행 값은 곡선의 x 값 역할을 하며, y 값은 출력 진행 값이 됩니다.
큐빅 베지어 이징 함수의 구문은 다음과 같습니다 ([CSS-VALUES-3]의 표기법 사용):
각 값의 의미는 아래와 같습니다:
- ease
-
cubic-bezier(0.25, 0.1, 0.25, 1)과 동일합니다.
- ease-in
-
cubic-bezier(0.42, 0, 1, 1)과 동일합니다.
- ease-out
-
cubic-bezier(0, 0, 0.58, 1)과 동일합니다.
- ease-in-out
-
cubic-bezier(0.42, 0, 0.58, 1)과 동일합니다.
-
- cubic-bezier(<number [0,1]>, <number>, <number [0,1]>, <number>)
-
큐빅 베지어 이징 함수를 지정합니다. 네 개의 수는 곡선의 P1, P2를 (x1, y1, x2, y2)로 지정합니다. 두 x 값이 [0, 1] 범위에 있지 않으면 정의는 무효입니다.
위에 나열된 키워드 값의 이징 함수는 아래 그림에서 확인할 수 있습니다.
2.3.1. 큐빅 베지어 이징 함수의 출력
입력 진행 값에서 출력 진행 값으로의 매핑은 주어진 x 값(input progress value)에 대한 대응 y 값(output progress value)을 결정하는 방식으로 수행됩니다. 이 곡선의 계산은 [FUND-COMP-GRAPHICS] 등 다양한 문헌에서 다룹니다.
input progress value가 [0, 1] 범위를 벗어나면, 가장 가까운 끝점의 접선 방향으로 곡선이 무한히 연장됩니다. 방법은 다음과 같습니다:
-
input progress value가 0보다 작을 때,
-
P1의 x 값이 0보다 크면, P1과 P0을 지나는 직선을 접선으로 사용합니다.
-
그렇지 않고 P2의 x 값이 0보다 크면, P2와 P0을 지나는 직선을 접선으로 사용합니다.
-
둘 다 아니라면, [-∞, 0) 구간의 모든 input progress value에 대해 output progress value는 0입니다.
-
-
input progress value가 1보다 클 때,
-
P2의 x 값이 1보다 작으면, P2와 P3을 지나는 직선을 접선으로 사용합니다.
-
그렇지 않고 P1의 x 값이 1보다 작으면, P1과 P3을 지나는 직선을 접선으로 사용합니다.
-
둘 다 아니라면, (1, ∞] 구간의 모든 input progress value에 대해 output progress value는 1입니다.
-
2.4. 스텝 이징 함수: step-start, step-end, steps()
스텝 이징 함수는 입력 시간을 지정한 개수의 동일 길이 구간으로 나누는 이징 함수의 한 종류입니다. steps 개수와 step position으로 정의됩니다. 구문은 다음과 같습니다:
<step-position> = jump-start | jump-end | jump-none | jump-both | start | end
각 값의 의미는 아래와 같습니다:
- step-start
-
steps(1, start)로 계산됩니다.
- step-end
-
steps(1, end)로 계산됩니다.
스텝 이징 함수 키워드 값 예시. - steps(<integer>, <step-position>?)
-
첫 번째 매개변수는 함수의 구간 수를 지정합니다. 0보다 큰 양의 정수여야 하며, 두 번째 매개변수가 jump-none인 경우에는 1보다 큰 양의 정수여야 합니다.
두 번째 매개변수(선택사항)는 step position을 다음 값 중 하나로 지정합니다:
- jump-start
-
첫 번째 상승이 input progress value 0에서 발생합니다.
- jump-end
-
마지막 상승이 input progress value 1에서 발생합니다.
- jump-none
-
모든 상승은 (0, 1) 범위 내에서 발생합니다.
- jump-both
-
첫 번째 상승은 input progress value 0에서, 마지막 상승은 input progress value 1에서 발생합니다.
- start
-
jump-start와 동일하게 동작합니다.
- end
-
jump-end와 동일하게 동작합니다.
두 번째 매개변수를 생략하면 end 값이 기본 적용됩니다.
아래 그림은 각 값의 동작을 보여줍니다:
스텝 이징 함수 예시.
2.4.1. 스텝 이징 함수의 출력
스텝이 발생하는 정확한 지점에서 함수 결과는 개념적으로 스텝의 상단입니다. 그러나 before flag가 step easing function의 입력값으로 true로 전달되면, 결과는 해당 지점에서 스텝의 하단이 됩니다.
before flag가 이 함수의 동작에 어떻게 영향을 주는지에 대한 예시로, step easing function의 step position이 start이고, 양의 delay와 backwards fill이 있는 애니메이션을 생각해봅시다.
예를 들어, CSS 애니메이션에서:
animation : moveRight5 s 1 s steps ( 5 , start);
delay 단계에서는 input progress value가 0이지만, before flag가 애니메이션이 아직 interval에 도달하지 않았음을 나타내면, 이징 함수는 output progress value로 0, 즉 첫 번째 스텝의 하단을 반환합니다.
애니메이션 interval이 시작되는 정확한 순간에 input progress value는 여전히 0이지만, before flag가 설정되지 않으므로 함수의 결과는 첫 번째 스텝의 상단이 됩니다.
output progress value를 계산할 때, step position start는 jump-start와 동일하게 간주됩니다. 마찬가지로 end는 jump-end와 동일하게 간주됩니다. 따라서 아래 알고리즘에서는 start나 end를 명시적으로 참조하지 않습니다.
참고: 사용자 에이전트는 직렬화 목적(see § 2.5 직렬화)에서 jump-start와 start를 구분해야 합니다.
output progress value는 input progress value와 before flag를 아래와 같이 계산합니다:
-
current step을
floor(input progress value × steps)
로 계산합니다. -
step position 속성이 다음 중 하나라면:
current step을 1 증가시킵니다.
-
다음 두 조건이 모두 true라면:
-
before flag가 설정되어 있고, 그리고
-
input progress value × steps mod 1이 0이면 (즉, input progress value × steps가 정수이면),
current step을 1 감소시킵니다.
-
-
input progress value ≥ 0 이고 current step < 0이면, current step을 0으로 합니다.
-
step position에 따라 jumps를 다음과 같이 계산합니다:
-
input progress value ≤ 1 이고 current step > jumps이면, current step을 jumps로 합니다.
이 절차의 4, 6단계는 input progress value가 [0, 1] 범위일 때, 스텝 이징 함수가 그 범위를 벗어난 output progress value를 생성하지 않도록 보장합니다.
예를 들어, 수학적으로는 step position이 jump-start인 스텝 이징 함수가 input progress value가 1일 때 1을 넘어서는 결과를 만들어낼 수 있지만, 직관적으로 그러한 이징 함수를 앞으로 채우는 애니메이션에 적용하면, 애니메이션이 앞으로 채워질 때 output progress value가 1이 되기를 기대합니다.
비슷하게, step position이 jump-end인 스텝 이징 함수도 애니메이션 delay 단계에서 같은 상황이 발생합니다.
-
output progress value는
current step / jumps
입니다.
2.5. 직렬화
이징 함수는 [CSSOM]에 정의된 공통 직렬화 패턴을 사용하며, 다음의 추가 요구 사항이 있습니다:
-
ease, linear, ease-in, ease-out, ease-in-out 키워드 값은 변환하지 않고 그대로 직렬화됩니다. 즉, 이 값들은 cubic-bezier() 또는 linear() 함수로 변환하지 않고 직렬화합니다.
-
스텝 이징 함수는 steps() 함수 또는 step-start, step-end 키워드로 지정하더라도 아래와 같이 직렬화합니다:
-
step position이 jump-end 또는 end인 경우, steps(<integer>)로 직렬화합니다.
-
그 외의 경우, steps(<integer>, <step-position>)로 직렬화합니다.
-
-
linear easing function은 linear()로 생성된 경우 직렬화된 계산 값을 얻어 직렬화합니다.
프라이버시 고려사항
이 명세에 대해 새롭게 보고된 프라이버시 고려사항은 없습니다.
이 명세는 웹 플랫폼에 새로운 기능을 직접 도입하는 것이 아니라, 다른 명세에서 참조할 수 있는 공통 정의를 제공합니다.
보안 고려사항
이 명세에서 정의된 기능을 참조하는 명세는, 이징 함수가 일반적으로 input progress value [0,1] 범위의 값을 받아 output progress value [0, 1] 범위의 값을 생성하지만, 항상 그런 것은 아니라는 점을 고려해야 합니다. 이징 함수의 응용에서는 입력과 출력이 이 범위 바깥일 때의 동작을 정의하여 새로운 보안 고려사항이 발생하지 않도록 해야 합니다.
3. 변경 사항
3.1. 1단계 이후 추가사항
-
linear() 함수가 추가되었습니다.
4. 감사의 글
이 명세는 L. David Baron, Dean Jackson, David Hyatt, Chris Marrin이 편집한 CSS Transitions 명세를 기반으로 하였습니다. 편집자들은 Douglas Stockwell, Steve Block, Tab Atkins, Rachel Nabors, Martin Pitt, 그리고 Animation at Work 슬랙 커뮤니티의 피드백과 기여에도 감사를 표합니다.