Piecewise linear easing function

XMLWordPrintable

    • Type: CSR
    • Resolution: Approved
    • Priority: P4
    • jfx26
    • Component/s: javafx
    • None
    • source
    • minimal
    • No compatibility risk is expected since no existing API is changed.
    • Java API
    • JDK

      Summary

      Add the linear() easing function.

      Problem

      CSS Easing Functions Level 2 specifies the linear easing function, which is supported by most browsers but still missing in JavaFX.

      Solution

      1. Add an ofLinear() interpolator to javafx.animation.Interpolator.
      2. Support the CSS syntax in javafx.css.CssParser.

      Specification

      cssref.html:

          --- a/modules/javafx.graphics/src/main/docs/javafx/scene/doc-files/cssref.html
          +++ b/modules/javafx.graphics/src/main/docs/javafx/scene/doc-files/cssref.html
          @@ -1789,12 +1789,35 @@
                   ) ]+ </span></p>
           
               <h3><a id="typeeasingfunction">&lt;easing-function&gt;</a></h3>
          -    <p class="grammar">linear | &lt;cubic-bezier-easing-function&gt; | &lt;step-easing-function&gt; | &lt;fx-easing-function&gt;</p>
          +    <p class="grammar">linear | &lt;linear-easing-function&gt; | &lt;cubic-bezier-easing-function&gt; | &lt;step-easing-function&gt; | &lt;fx-easing-function&gt;</p>
               <p><strong>Linear</strong> <span class="grammar" style="font-size: smaller;">linear</span><br>
          -       The linear easing function is a simple linear mapping from the input progress value to the output progress value.</p>
          +       The linear easing keyword is a simple linear mapping from the input progress value to the output progress value.<br>
          +       It it equivalent to <span class="grammar">linear(0, 1)</span></p>
               <figure style="display: inline-block">
                   <img src="easing-linear.svg" width="200" alt="Linear easing function">
               </figure>
          +    <p><strong>Linear Easing Function</strong> <span class="grammar" style="font-size: smaller;">&lt;linear-easing-function&gt;</span><br></p>
          +    <p class="grammar">linear([ <a href="#typenumber" class="typelink">&lt;number&gt;</a> && <a href="#typepercentage" class="typelink">&lt;percentage&gt;{0,2}</a> ]#)</p>
          +    <p>The linear easing function interpolates linearly between its control points. The control points are specified
          +        as a comma-separated list of two or more items, where each item consists of a <a href="#typenumber" class="typelink">&lt;number&gt;</a>,
          +        optionally followed by one or two <a href="#typepercentage" class="typelink">&lt;percentage&gt;</a> values.</p>
          +    <p>The <a href="#typenumber" class="typelink">&lt;number&gt;</a> specifies the progress of the animation in time.
          +        The optional <a href="#typepercentage" class="typelink">&lt;percentage&gt;</a> specifies when that progress
          +        is reached; if two percentages are specified, they indicate a segment of time when the animation is paused.
          +        If no percentage is specified, the control point is spaced evenly between neighboring control points.</p>
          +    <p>Examples of linear easing functions:</p>
          +    <figure style="display: inline-block">
          +        <img src="easing-linear-func1.svg" width="200" alt="linear easing function">
          +        <figcaption style="margin-left: 40px" class="grammar">linear(0, 0.25, 1)</figcaption>
          +    </figure>
          +    <figure style="display: inline-block">
          +        <img src="easing-linear-func2.svg" width="200" alt="linear easing function">
          +        <figcaption style="margin-left: 20px" class="grammar">linear(0, 0.25 75%, 1)</figcaption>
          +    </figure>
          +    <figure style="display: inline-block">
          +        <img src="easing-linear-func3.svg" width="200" alt="linear easing function">
          +        <figcaption style="margin-left: 10px" class="grammar">linear(0, 0.25 25% 75%, 1)</figcaption>
          +    </figure>
      

      javafx.animation.Interpolator:

          --- a/modules/javafx.graphics/src/main/java/javafx/animation/Interpolator.java
          +++ b/modules/javafx.graphics/src/main/java/javafx/animation/Interpolator.java
          @@ -78,9 +80,7 @@
               };
           
               /**
          -     * Built-in interpolator that provides linear time interpolation. The return
          -     * value of {@code interpolate()} is {@code startValue} + ({@code endValue}
          -     * - {@code startValue}) * {@code fraction}.
          +     * Built-in interpolator instance that is equivalent to {@code ofLinear([0, 0], [1, 1])}.
                */
               public static final Interpolator LINEAR = new Interpolator() {
                   @Override
          @@ -94,6 +94,33 @@
                   }
               };
           
          +    /**
          +     * Returns an interpolator that interpolates linearly between its specified control points.
          +     * <p>
          +     * Each control point associates an input progress value (X) with an output progress value (Y).
          +     * The input progress value is the normalized progress of the animation, while the output progress
          +     * value is the normalized progress of the value change. This means that when the time has reached
          +     * X of the animation, the animation should be at Y of its value change. Both values are specified
          +     * in normalized coordinates, but are not required to fall within the {@code [0..1]} interval.
          +     * <p>
          +     * If the input progress value (X) of a control point is unspecified ({@link Double#NaN}), it is
          +     * distributed evenly between its neighboring control points. If the input progress value of
          +     * the first or last control point is unspecified, it is set to 0 or 1, respectively.
          +     * <p>
          +     * The control point list is canonicalized so that input progress values (X) are non-decreasing in
          +     * the order provided. In particular, if a control point specifies an X value that is lower than
          +     * any preceding control point's X value, it is adjusted to match the greatest preceding X value.
          +     *
          +     * @param controlPoints the control points
          +     * @throws NullPointerException if {@code controlPoints} is {@code null}
          +     * @throws IllegalArgumentException if {@code controlPoints} contains less than two items
          +     * @return a linear interpolator
          +     * @since 26
          +     */
          +    public static Interpolator ofLinear(Point2D... controlPoints) {
          +        return new LinearInterpolator(controlPoints);
          +    }
      

            Assignee:
            Michael Strauß
            Reporter:
            Michael Strauß
            Kevin Rushforth
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: