From: Manuel Carrasco MoƱino Date: Fri, 1 Nov 2013 12:49:53 +0000 (+0100) Subject: Implement animation Easing based on Bezier curves instead of using different algorith... X-Git-Tag: release-1.4.0~36^2~4 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=658a538299022a645603178a74312438d7d379e7;p=gwtquery.git Implement animation Easing based on Bezier curves instead of using different algorithm for each one. Includes a set of most popular transitions used in web. --- diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java index 7112f4c6..44deecb5 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Effects.java @@ -26,6 +26,7 @@ import com.google.gwt.query.client.plugins.effects.ClipAnimation.Direction; import com.google.gwt.query.client.plugins.effects.Fx; import com.google.gwt.query.client.plugins.effects.PropertiesAnimation; import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; +import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve; /** * Effects plugin for Gwt Query. @@ -119,9 +120,9 @@ public class Effects extends QueuePlugin { *
    *  //move the element from its original position to the position top:500px and left:500px for 400ms.
    *  //use a swing easing function for the transition
-   *  $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, Easing.SWING);
+   *  $("#foo").animate(Properties.create("{top:'500px',left:'500px'}"), 400, EasingCurve.swing);
    *  // Change the width and border attributes of a table
-   *  $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, Easing.LINEAR);
+   *  $("table").animate(Properties.create("{$width: '500', $border: '10'}"), 400, EasingCurve.linear);
    * 
* * In addition to numeric values, each property can take the strings 'show', @@ -145,8 +146,8 @@ public class Effects extends QueuePlugin { * Example: * *
-   *  $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'", 400, Easing.SWING);
-   *  $("#foo").animate($$("{backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'}"), 400, Easing.SWING);
+   *  $("#foo").animate("backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'", 400, EasingCurve.swing);
+   *  $("#foo").animate($$("{backgroundColor:'red', color:'#ffffff', borderColor:'rgb(129, 0, 70)'}"), 400, EasingCurve.swing);
    * 
* * @param p a {@link Properties} object containing css properties to animate. @@ -185,7 +186,7 @@ public class Effects extends QueuePlugin { * //move the element from its original position to left:500px for 500ms * $("#foo").animate("left:'500'"); * // Change the width attribute of a table - * $("table").animate("$width:'500'"), 400, Easing.LINEAR); + * $("table").animate("$width:'500'"), 400, EasingCurve.swing); * * * In addition to numeric values, each property can take the strings 'show', @@ -284,7 +285,7 @@ public class Effects extends QueuePlugin { * @param duration the duration in milliseconds of the animation */ public Effects animate(Object stringOrProperties, int duration, Function... funcs) { - return animate(stringOrProperties, duration, Easing.LINEAR, funcs); + return animate(stringOrProperties, duration, EasingCurve.linear, funcs); } /** diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Bezier.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Bezier.java new file mode 100644 index 00000000..7b098a6d --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Bezier.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, The gwtquery team. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.gwt.query.client.plugins.effects; + + +/** + * Bezier curve for transition easing functions. + * + * Inspired in KeySpline.js from Gaetan Renaudeau [1] which + * is based in nsSMILKeySpline.cpp from mozilla. + * + * [1] https://gist.github.com/gre/1926947 + * [2] http://dxr.mozilla.org/mozilla-central/source/content/smil/nsSMILKeySpline.cpp + */ +public class Bezier { + + private double x1, y1 , x2, y2; + + public Bezier(double x1, double y1, double x2, double y2) { + this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; + } + + private double A(double a1, double a2) { + return 1.0 - 3.0 * a2 + 3.0 * a1; + } + private double B(double a1, double a2) { + return 3.0 * a2 - 6.0 * a1; + } + private double C(double a1){ + return 3.0 * a1; + } + + private double calcBezier(double t, double a1, double a2) { + return ((A(a1, a2)*t + B(a1, a2))*t + C(a1))*t; + } + + private double calcSlope(double t, double a1, double a2) { + return 3.0 * A(a1, a2)*t*t + 2.0 * B(a1, a2) * t + C(a1); + } + + private double getTForX(double x) { + double t = x; + for (double i = 0; i < 4; ++i) { + double currentSlope = calcSlope(t, x1, x2); + if (currentSlope == 0.0) return t; + double currentX = calcBezier(t, x1, x2) - x; + t -= currentX / currentSlope; + } + return t; + } + + public double f (double x) { + return calcBezier(getTForX(x), y1, y2); + } + + public String toString() { + return x1 + "," + y1 + "," + x2 + "," + y2; + } + +} diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java index 92386f5e..acd2c127 100755 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/PropertiesAnimation.java @@ -36,19 +36,90 @@ public class PropertiesAnimation extends GQAnimation { */ public static interface Easing { public double interpolate(double progress); - - public Easing LINEAR = new Easing() { - public double interpolate(double progress) { - return progress; - } - }; - - public Easing SWING = new Easing() { - public double interpolate(double progress) { - return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2; - } - }; + /** + * @deprecated use EasingCurve.linear instead + */ + public Easing LINEAR = EasingCurve.linear; + + /** + * @deprecated use EasingCurve.swing instead + */ + public Easing SWING = EasingCurve.swing; } + + /** + * This is a collection of most popular curves used in web animations + * implemented using Bezier Curve instead of a different formula per + * animation. + * + * The toString() method returns the string parameter which can be used + * for CSS3 transition-timing-function properties, example: + *
+
+   transition-timing-function: ease;
+   transition-timing-function: cubic-bezier(0, 0, 1, 1);
+     
+   * 
+ */ + public static enum EasingCurve implements Easing { + linear (0, 0, 1, 1) { + public double interpolate(double p){return p;} + public String toString() {return "linear";} + }, + ease (0.25, 0.1, 0.25, 1) { + public String toString() {return "ease";} + }, + easeIn (0.42, 0, 1, 1) { + public String toString() {return "ease-in";} + }, + easeOut (0, 0, 0.58, 1) { + public String toString() {return "ease-out";} + }, + easeInOut (0.42, 0, 0.58, 1) { + public String toString() {return "ease-in-out";} + }, + snap (0,1,.5,1), + swing (.02,.01,.47,1), + easeInCubic (.550,.055,.675,.190), + easeOutCubic (.215,.61,.355,1), + easeInOutCubic (.645,.045,.355,1), + easeInCirc (.6,.04,.98,.335), + easeOutCirc (.075,.82,.165,1), + easeInOutCirc (.785,.135,.15,.86), + easeInExpo (.95,.05,.795,.035), + easeOutExpo (.19,1,.22,1), + easeInOutExpo (1,0,0,1), + easeInQuad (.55,.085,.68,.53), + easeOutQuad (.25,.46,.45,.94), + easeInOutQuad (.455,.03,.515,.955), + easeInQuart (.895,.03,.685,.22), + easeOutQuart (.165,.84,.44,1), + easeInOutQuart (.77,0,.175,1), + easeInQuint (.755,.05,.855,.06), + easeOutQuint (.23,1,.32,1), + easeInOutQuint (.86,0,.07,1), + easeInSine (.47,0,.745,.715), + easeOutSine (.39,.575,.565,1), + easeInOutSine (.445,.05,.55,.95), + easeInBack (.6,-.28,.735,.045), + easeOutBack (.175, .885,.32,1.275), + easeInOutBack (.68,-.55,.265,1.55), + custom(0, 0, 1, 1); + + private Bezier c = new Bezier(0, 0, 1, 1); + EasingCurve(double x1, double y1, double x2, double y2) { + with(x1, y1, x2, y2); + } + public void with(double x1, double y1, double x2, double y2) { + c = new Bezier(x1, y1, x2, y2); + } + public double interpolate(double progress) { + return c.f(progress); + } + public String toString() { + return "cubic-bezier(" + c + ")"; + } + } private static final String[] ATTRS_TO_SAVE = new String[]{ "overflow"}; @@ -190,7 +261,7 @@ public class PropertiesAnimation extends GQAnimation { return new Fx(key, val, start, end, unit, rkey); } - private Easing easing = Easing.SWING; + private Easing easing = EasingCurve.linear; private JsObjectArray effects = JsObjectArray.create(); private Function[] funcs; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java index a3190a95..9a7f22eb 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/widgets/TextBoxBaseWidgetFactory.java @@ -17,7 +17,6 @@ package com.google.gwt.query.client.plugins.widgets; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.InputElement; -import com.google.gwt.query.client.GQuery; import com.google.gwt.user.client.ui.TextBoxBase; /** diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java index 2dcefa3a..8cf497db 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryEffectsTestGwt.java @@ -16,15 +16,15 @@ package com.google.gwt.query.client; import static com.google.gwt.query.client.GQuery.*; + import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; import com.google.gwt.dom.client.Element; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.query.client.GQuery.Offset; -import com.google.gwt.query.client.plugins.effects.Bezier.EasingCurve; import com.google.gwt.query.client.plugins.effects.Fx.ColorFx; import com.google.gwt.query.client.plugins.effects.PropertiesAnimation; -import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; +import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.EasingCurve; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Label; @@ -118,10 +118,10 @@ public class GQueryEffectsTestGwt extends GWTTestCase { final int duration = 1000; g.as(Effects). - animate($$("left: '+=100'"), duration, Easing.LINEAR). - animate($$("top: '+=100'"), duration, Easing.LINEAR). - animate($$("left: '-=100'"), duration, Easing.LINEAR). - animate($$("top: '-=100'"), duration, Easing.LINEAR); + animate($$("left: '+=100'"), duration, EasingCurve.linear). + animate($$("top: '+=100'"), duration, EasingCurve.linear). + animate($$("left: '-=100'"), duration, EasingCurve.linear). + animate($$("top: '-=100'"), duration, EasingCurve.linear); // Configure the max duration for this test delayTestFinish(duration * 4); @@ -246,7 +246,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { .toString()); prop1 = GQuery.$$("marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px'"); - PropertiesAnimation an = new PropertiesAnimation(EasingCurve.SWING, g.get(0), prop1); + PropertiesAnimation an = new PropertiesAnimation(EasingCurve.swing, g.get(0), prop1); an.onStart(); an.onComplete(); @@ -272,7 +272,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { .toString()); prop1 = GQuery.$$("marginTop: '0', marginLeft: '0', top: '0%', left: '0%', width: '100px', height: '100px', padding: '5px'"); - an = new PropertiesAnimation(Easing.SWING, g.get(0), prop1); + an = new PropertiesAnimation(EasingCurve.swing, g.get(0), prop1); an.onStart(); an.onComplete(); @@ -358,7 +358,7 @@ public class GQueryEffectsTestGwt extends GWTTestCase { delayTestFinish(duration * 3); g.as(Effects). - animate($$("$width: +=100; $border: +=4"), duration, Easing.LINEAR); + animate($$("$width: +=100; $border: +=4"), duration, EasingCurve.linear); final Timer timer = new Timer() { public void run() {