Skip to content

Commit aaad9c7

Browse files
committed
[css-easing-2] Rewrite the linear() output algo to handle a single point (and correctly handle a number of edge cases). w3c#10580
1 parent a8f5f8c commit aaad9c7

File tree

1 file changed

+55
-48
lines changed

1 file changed

+55
-48
lines changed

css-easing-2/Overview.bs

+55-48
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ Linear Easing Functions: ''linear'', ''linear()''</h3>
151151
A <dfn export>linear easing function</dfn>
152152
is an [=easing function=]
153153
that interpolates linearly
154-
between its [=control points=].
155-
Each <dfn for="linear easing function">control point</dfn>
154+
between its [=linear()/control points=].
155+
Each <dfn for="linear()">control point</dfn>
156156
is a pair of numbers,
157157
associating an [=input progress value=]
158158
to an [=output progress value=].
@@ -162,7 +162,7 @@ to an [=output progress value=].
162162
alt="A linear curve used as an easing function.">
163163
<figcaption>
164164
''linear(0, .1 25%, .75 50%, 1)''<br>
165-
The shape of the curve follows the [=control points=].<br>
165+
The shape of the curve follows the [=linear()/control points=].<br>
166166
Input progress values serve as <var>x</var> values of the curve,
167167
whilst the <var>y</var> values are the output progress values.
168168
</figcaption>
@@ -186,20 +186,20 @@ A [=linear easing function=] has the following syntax:
186186
::
187187
Specifies a [=linear easing function=].
188188

189-
Each comma-separated argument specifies one or two [=control points=],
189+
Each comma-separated argument specifies one or two [=linear()/control points=],
190190
with an [=input progress value=] equal to the specified <<percentage>>
191191
(converted to a <<number>> between 0 and 1),
192192
and an [=output progress value=] equal to the specified <<number>>.
193193
When the argument has two <<percentage>>s,
194-
it defines two [=control points=] in the specified order,
194+
it defines two [=linear()/control points=] in the specified order,
195195
one per <<percentage>>.
196196

197197
If an argument lacks a <<percentage>>,
198198
its [=input progress value=] is initially empty,
199199
but that is immediately corrected by [=linear() canonicalization=] after parsing.
200200

201201
<div algorithm>
202-
To <dfn export lt="linear() canonicalization|canonicalize a linear()">canonicalize a linear()</dfn> function's [=control points=],
202+
To <dfn export lt="linear() canonicalization|canonicalize a linear()">canonicalize a linear()</dfn> function's [=linear()/control points=],
203203
perform the following:
204204

205205
1. If the first [=control point=] lacks an [=input progress value=],
@@ -214,10 +214,10 @@ A [=linear easing function=] has the following syntax:
214214
of any preceding [=control point=].
215215

216216
4. If any [=control point=] still lacks an [=input progress value=],
217-
then for each contiguous run of such [=control points=],
217+
then for each contiguous run of such [=linear()/control points=],
218218
set their [=input progress values=]
219219
so that they are evenly spaced
220-
between the preceding and following [=control points=]
220+
between the preceding and following [=linear()/control points=]
221221
with [=input progress values=].
222222

223223
After canonicalization,
@@ -229,7 +229,7 @@ A [=linear easing function=] has the following syntax:
229229
was originally supplied,
230230
so that information should be retained
231231
in the [=CSS/internal representation=].
232-
It does not rely on whether a pair of [=control points=]
232+
It does not rely on whether a pair of [=linear()/control points=]
233233
were specified as two percentages on a single argument
234234
or as separate arguments.
235235
</div>
@@ -269,8 +269,8 @@ Serializing</h4>
269269

270270
<div class=example>
271271
When serialized,
272-
[=control points=] originally specified with two [=input progress values=]
273-
are turned into two separate [=control points=],
272+
[=linear()/control points=] originally specified with two [=input progress values=]
273+
are turned into two separate [=linear()/control points=],
274274
and the [=input progress values=] are in strictly ascending order.
275275
For example:
276276

@@ -283,48 +283,55 @@ Serializing</h4>
283283
<h4 id=linear-easing-function-output>
284284
Output</h4>
285285

286-
<section algorithm="to calculate linear easing output progress">
287-
288-
To <dfn export>calculate linear easing output progress</dfn>
289-
for a given [=linear easing function=] |linearEasingFunction|,
290-
and an [=input progress value=] |inputProgress|,
291-
perform the following.
292-
It returns an [=output progress value=].
293-
294-
1. Let |points| be |linearEasingFunction|'s [=linear easing function/points=].
295-
296-
1. Let |pointAIndex| be index of the last [=list/item=] in |points|
297-
with an [=linear easing point/input=] less than or equal to |inputProgress|,
298-
or 0 if there is no match.
299-
300-
1. If |pointAIndex| is equal to |points| [=list/size=] minus 1,
301-
decrement |pointAIndex| by 1.
302-
303-
Note: This ensures we have a "next" [=linear easing point|point=] to compare to.
304-
305-
1. Let |pointA| be |points|[pointAIndex].
306-
307-
1. Let |pointB| be |points|[pointAIndex + 1].
308-
309-
1. If |pointA|'s [=linear easing point/input=] is equal to |pointB|'s [=linear easing point/input=],
310-
return |pointB|'s [=linear easing point/output=].
311-
312-
1. Let |progressFromPointA| be |inputProgress| minus |pointA|'s [=linear easing point/input=].
313-
314-
1. Let |pointInputRange| be |pointB|'s [=linear easing point/input=] minus |pointA|'s [=linear easing point/input=].
315-
316-
1. Let |progressBetweenPoints| be |progressFromPointA| divided by |pointInputRange|.
317-
318-
1. Let |pointOutputRange| be |pointB|'s [=linear easing point/output=] minus |pointA|'s [=linear easing point/output=].
319-
320-
1. Let |outputFromLastPoint| be |progressBetweenPoints| multiplied by |pointOutputRange|.
286+
<div algorithm>
321287

322-
1. Return |pointA|'s [=linear easing point/output=] plus |outputFromLastPoint|.
288+
To <dfn export>calculate linear easing output progress</dfn>
289+
for a given [=linear easing function=] |func|,
290+
and an [=input progress value=] |inputProgress|,
291+
perform the following.
292+
It returns an [=output progress value=].
293+
294+
1. Let |points| be |func|'s [=linear()/control points=].
295+
296+
2. If |points| holds only a single item,
297+
return the [=output progress value=]
298+
of that item.
299+
300+
3. If at least one of |points| has an [=input progress value=]
301+
matching |inputProgress|,
302+
return the largest [=output progress value=] from among them.
303+
304+
4. Otherwise, find two [=linear()/control points=],
305+
|A| and |B|,
306+
which will be used for interpolation:
307+
308+
1. If |inputProgress| is smaller
309+
than any [=input progress value=] in |points|,
310+
let |A| and |B| be the first two items in |points|.
311+
If |A| and |B| have the same [=input progress value=],
312+
return |A|'s [=output progress value=].
313+
314+
2. Otherwise, if |inputProgress| is larger
315+
than any [=input progress value=] in |points|,
316+
let |A| and |B| be the last two items in |points|.
317+
If |A| and |B| have the same [=input progress value=],
318+
return |B|'s [=output progress value=].
319+
320+
3. Otherwise, let |A| be the [=linear()/control point=]
321+
with the largest [=output progress value=]
322+
whose [=input progress value=] is smaller than |inputProgress|,
323+
and let |B| be the [=linear()/control point=]
324+
with the smallest [=output progress value=]
325+
whose [=input progress value=] is larger than |inputProgress|.
326+
327+
5. Linearly interpolate (or extrapolate) |inputProgress|
328+
along the line defined by |A| and |B|,
329+
and return the result.
330+
</div>
323331

324332
<wpt>
325333
linear-timing-functions-output.html
326334
</wpt>
327-
</section>
328335

329336
<h4 id=linear-easing-function-examples>
330337
Examples</h4>

0 commit comments

Comments
 (0)