-
Notifications
You must be signed in to change notification settings - Fork 688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-easing-1] Some ideas for linear() easing #6533
Changes from all commits
6979847
654008f
0bde5c9
f53a1b7
4ce3db6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,16 +125,126 @@ The syntax for specifying an [=easing function=] is as follows: | |
<<step-easing-function>></div> | ||
|
||
|
||
<h3 id=the-linear-easing-function oldids=linear-timing-function-section>The linear easing function: ''linear''</h3> | ||
<h3 id=the-linear-easing-function oldids=linear-timing-function-section>The linear easing function: ''linear()''</h3> | ||
|
||
The <dfn export lt="linear easing function|linear timing function">linear easing | ||
function</dfn> is an identity function | ||
meaning that its [=output progress value=] is equal to the | ||
[=input progress value=] for all inputs. | ||
A <dfn export lt="linear easing function|linear timing function">linear easing function</dfn> | ||
is an easing function | ||
that interpolates linearly | ||
between its [=linear easing function/points=]. | ||
|
||
The syntax for the [=linear easing function=] is simply the | ||
<dfn dfn-type=value for=easing-function>linear</dfn> keyword. | ||
A [=linear easing function=] has <dfn for="linear easing function">points</dfn>, | ||
a [=/list=] of [=linear easing points=]. | ||
Initially a new empty [=/list=]. | ||
|
||
A <dfn>linear easing point</dfn> | ||
is a [=/struct=] | ||
that has: | ||
|
||
<dl dfn-for="linear easing point"> | ||
|
||
: <dfn>input</dfn> | ||
:: A number or null | ||
|
||
Note: The [=linear easing point/input=] is only null during the [=create a linear easing function=] algorithm. | ||
|
||
: <dfn>output</dfn> | ||
:: A number | ||
|
||
|
||
</dl> | ||
|
||
<section algorithm="to calculate linear output progress"> | ||
|
||
To <dfn export>calculate linear output progress</dfn> | ||
for a given [=linear easing function=] |linearEasingFunction|, | ||
and an [=input progress value=] |inputProgress|, | ||
perform the following. | ||
It returns an [=output progress value=]. | ||
|
||
1. If |linearEasingFunction|'s [=linear easing function/points=] [=list/is empty=], | ||
then return |inputProgress|. | ||
|
||
1. If |linearEasingFunction|'s [=linear easing function/points=] [=list/size=] is 1, | ||
then return |linearEasingFunction|'s [=linear easing function/points=][0]'s [=linear easing point/output=]. | ||
|
||
1. Plot |linearEasingFunction|'s [=linear easing function/points=] points on a graph | ||
using [=linear easing point/input=] as the x-axis | ||
and [=linear easing point/output=] as the y-axis. | ||
|
||
1. Interpolate the points linearly. | ||
|
||
1. Extend the ends of the graph to infinity using the final angle of the line at either end. | ||
If the line starts/ends with two points of the same position, the line should extend along the x-axis. | ||
|
||
1. Return the y-axis value corresponding to the x-axis value of |inputProgress|. | ||
|
||
</section> | ||
|
||
<dfn function lt="linear()">linear(<<linear-stop-list>>)</dfn> | ||
|
||
<pre class="prod"> | ||
<dfn><linear-stop-list></dfn> = [ <<linear-stop>> ]# | ||
<dfn><linear-stop></dfn> = <<number>> && <<linear-stop-length>>? | ||
<dfn><linear-stop-length></dfn> = <<percentage>>{1,2} | ||
</pre> | ||
|
||
<section algorithm="to create a linear easing function"> | ||
|
||
To <dfn>create a linear easing function</dfn> | ||
from a <<linear-stop-list>> |stopList|, | ||
perform the following. | ||
It returns a [=linear easing function=]. | ||
|
||
1. Let |function| be a new [=linear easing function=]. | ||
|
||
1. Let |largestInput| be negative infinity. | ||
|
||
1. For each |stop| in |stopList|: | ||
|
||
1. Let |point| be a new [=linear easing point=]. | ||
|
||
1. [=list/Append=] |point| to |function|'s [=linear easing function/points=]. | ||
|
||
1. Set |point|'s [=linear easing point/output=] to |stop|'s <<number>>. | ||
|
||
1. If |stop| has a <<linear-stop-length>>, then: | ||
|
||
1. Set |point|'s [=linear easing point/input=] to whichever is greater: | ||
|stop|'s <<linear-stop-length>>'s first <<percentage>> as a number, | ||
or |largestInput|. | ||
|
||
1. Set |largestInput| to |point|'s [=linear easing point/input=]. | ||
|
||
1. If |stop|'s <<linear-stop-length>> has a second <<percentage>>, then: | ||
|
||
1. Let |extraPoint| be a new [=linear easing point=]. | ||
|
||
1. [=list/Append=] |extraPoint| to |function|'s [=linear easing function/points=]. | ||
|
||
1. Set |extraPoint|'s [=linear easing point/output=] to |stop|'s <<number>>. | ||
|
||
1. Set |extraPoint|'s [=linear easing point/input=] to whichever is greater: | ||
|stop|'s <<linear-stop-length>>'s second <<percentage>> as a number, | ||
or |largestInput|. | ||
|
||
1. Set |largestInput| to |extraPoint|'s [=linear easing point/input=]. | ||
|
||
1. Otherwise, if |stop| is the first [=list/item=] in |stopList|, | ||
then set |point|'s [=linear easing point/input=] to 0. | ||
|
||
1. Otherwise, if |stop| is the last [=list/item=] in |stopList|, | ||
then set |point|'s [=linear easing point/input=] to 1. | ||
|
||
1. For runs of [=list/items=] in |function|'s [=linear easing function/points=] that have a null [=linear easing point/input=], | ||
assign a number to the [=linear easing point/input=] by linearly interpolating between the previous and next [=linear easing function/points=] that have a non-null [=linear easing point/input=]. | ||
|
||
1. Return |function|. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Serializing back from this returned function may result in a different round trip result: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens with linear-gradient? If there's precedent there, same should happen here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
So the two options of keeping both presentable & function forms, or calculating the function form every time seem... unattractive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree it's a little weird that syntax unfolds like that, but I think it still makes sense to do the same as gradient. |
||
|
||
</section> | ||
|
||
<h3 id="the-linear-easing-keyword">The linear easing keyword: ''linear''</h3> | ||
|
||
The <dfn dfn-type=value for=easing-function>linear</dfn> keyword is equivalent to ''linear()''. | ||
|
||
<h3 id=cubic-bezier-easing-functions oldids=cubic-bezier-timing-functions>Cubic | ||
Bézier easing functions: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, admittedly this is an edge case, but if any of the entries not at either edge contain negative or higher-than-100% percentage values (
linear(0, 0.2 -10%, 0.8 110%, 1.0)
), this would no longer be a proper function?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the ordering enforced? So -10% would be clamped to 0, since there's a 0 beforehand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true on the start side - how about the end,
linear([...], 0.8 110%, 1.0)
? Could use|largestInput|
, though each side behaving differently seems a bit less intuitive (Debatable, since we're already in an edge case).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the last value doesn't have a position, it should be assumed to be 100%. Does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, let me test gradients…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://jsbin.com/mopojul/4/edit?html,css,output
It seems like the first value is assigned 0% if it has no position. However, it seems like the last position will be
Math.max(previousPosition, 100%)
.My intent will be to spec the same position behaviour as gradients unless there's a good reason to do something different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable. Thanks!