From: Manuel Carrasco MoƱino Date: Sat, 9 Nov 2013 14:21:27 +0000 (+0100) Subject: Adding a TransitionsAnimation class whish is like PropertiesAnimation but using CSS3 X-Git-Tag: release-1.4.0~33^2~6 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=00a9035774e41fcc38ae42af363e64c9777f6ba6;p=gwtquery.git Adding a TransitionsAnimation class whish is like PropertiesAnimation but using CSS3 --- diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java index 03ed86b0..426c408d 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Fx.java @@ -18,6 +18,29 @@ public class Fx { */ public static boolean off = false; + /** + * A pojo to store color transition values. + */ + public static class TransitFx extends Fx { + public String transitEnd; + public String transitStart; + + TransitFx() { + } + + TransitFx(String attr, String value, String start, String end, String unit) { + this.cssprop = attr; + this.value = value; + this.transitStart = start; + this.transitEnd = end; + this.unit = unit; + } + + public String toString() { + return super.toString() + " transitStart=" + transitStart + " transitEnd=" + transitEnd; + } + } + /** * A pojo to store color effect values. */ 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 f91f0557..d9404e22 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 @@ -15,6 +15,8 @@ */ package com.google.gwt.query.client.plugins.effects; +import static com.google.gwt.query.client.GQuery.$; + import com.google.gwt.dom.client.Element; import com.google.gwt.query.client.Function; import com.google.gwt.query.client.GQuery; @@ -131,13 +133,13 @@ public class PropertiesAnimation extends GQAnimation { } } - private static final String[] ATTRS_TO_SAVE = new String[]{"overflow"}; + protected static final String[] ATTRS_TO_SAVE = new String[]{"overflow"}; private static final RegExp REGEX_NUMBER_UNIT = RegExp.compile("^([0-9+-.]+)(.*)?$"); - private static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp.compile("^([+-]=)?([0-9+-.]+)(.*)?$"); + protected static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp.compile("^([+-]=)?([0-9+-.]+)(.*)?$"); - private static final RegExp REGEX_NON_PIXEL_ATTRS = + protected static final RegExp REGEX_NON_PIXEL_ATTRS = RegExp.compile("z-?index|font-?weight|opacity|zoom|line-?height|^\\$", "i"); private static final RegExp REGEX_COLOR_ATTR = RegExp.compile(".*color$", "i"); @@ -266,21 +268,19 @@ public class PropertiesAnimation extends GQAnimation { return new Fx(key, val, start, end, unit, rkey); } - private Easing easing = EasingCurve.linear; - private JsObjectArray effects = JsObjectArray.create(); - private Function[] funcs; + protected Easing easing; + protected JsObjectArray effects = JsObjectArray.create(); + protected Function[] funcs; + protected Properties prps; private Effects g; - private Properties prps; - - public PropertiesAnimation(Easing easing, Element elem, Properties p, - Function... funcs) { - this.easing = easing; + public PropertiesAnimation(Easing easing, Element elem, Properties p, Function... funcs) { + this.easing = easing != null ? easing : EasingCurve.linear; this.e = elem; this.funcs = funcs; this.prps = p; - g = Effects.$(e).as(Effects.Effects); + g = $(e).as(Effects.Effects); } @Override @@ -346,11 +346,7 @@ public class PropertiesAnimation extends GQAnimation { @Override protected double interpolate(double progress) { - if (easing != null) { - return easing.interpolate(progress); - } - // maybe return super.interpolate() instead ? - return progress; + return easing.interpolate(progress); } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java index b4cb8f2c..9a290753 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java @@ -45,10 +45,10 @@ import com.google.gwt.user.client.DOM; .promise().done(new Function(){public void f() { g1.transition("{x: +100}", 2000, "linear", 0); }}); - + $("#bar") .transition("{ opacity: 0.1, scale: 2, x: 50, y: 50 }", 5000, EasingCurve.easeInBack) - .transition("{x: +100, width: +40px}", 2000, EasingCurve.easeOut); + .transition("{x: +100, width: +40px}", 2000, EasingCurve.easeOut); * */ @@ -156,7 +156,7 @@ public class Transitions extends GQuery { private static final String TRANSFORM = "_t_"; private static final String transformOrigin = getVendorPropertyName("transformOrigin"); - private static final RegExp transformRegex = RegExp.compile("^(scale|translate|rotate([XY]|3d)?|perspective|skew[XY]|x|y)$"); + protected static final RegExp transformRegex = RegExp.compile("^(scale|translate|rotate([XY]|3d)?|perspective|skew[XY]|x|y)$"); private static final String transition = getVendorPropertyName("transition"); private static final String transitionDelay = getVendorPropertyName("transitionDelay"); @@ -270,16 +270,26 @@ public class Transitions extends GQuery { } /** - * Works like GQuery.animate(), but uses CSS transitions. + * The transition() method allows you to create animation effects on any numeric HTML Attribute, + * CSS property, or color using CSS3 transformations and transitions. * - * It allows chaining like: + * It works similar to animate(), supports chainning and queueing and an extra parameter for + * delaying the animation. + * + * Example: *
-    $("#foo")
-      .transition("{ opacity: 0.1, scale: 2, x: 50, y: 50 }", 5000, EasingCurve.easeInBack)
-      .transition("{x: +100, width: +40px}", 2000, EasingCurve.easeOut);
+     $("#foo").transition("{ opacity: 0.1, scale: 2, x: 50, y: 50 }", 5000, EasingCurve.easeInBack);
+
+     $("#bar")
+       .transition("{ opacity: 0.1, scale: 2, x: 50, y: 50 }", 5000, EasingCurve.easeInBack)
+       .transition("{x: +100, width: +40px}", 2000, EasingCurve.easeOut);
    * 
*/ public Transitions transition(Object stringOrProperties, int duration, Easing easing, int delay, final Function... funcs) { + if (isEmpty()) { + return this; + } + final Properties p = (stringOrProperties instanceof String) ? $$((String) stringOrProperties) : (Properties) stringOrProperties; final String oldTransitions = css(transition); @@ -295,28 +305,45 @@ public class Transitions extends GQuery { value += (value.isEmpty() ? "" : ", ") + s + " " + attribs; } - // Use gQuery queue, so as we can chain transitions final String transitionValue = value; + + // Use gQuery queue, so as we can chain transitions, animations etc. delay(0, new Function(){public void f() { - // Configure animation using transition property - css(transition, transitionValue); - // Set all css properties for this transition - css(p); - // prevent memory leak - removeData(TRANSFORM); + // This is called once per element + $(this) + // Configure animation using transition property + .css(transition, transitionValue) + // Set all css properties for this transition using the css method in this class + .as(Transitions).css(p) + // prevent memory leak + .removeData(TRANSFORM); }}); // restore oldTransitions in the element, and use the queue to prevent more effects being run. // TODO: Use transitionEnd events once GQuery supports non-bit events delay(duration + delay, new Function(){public void f() { - css(transition, oldTransitions); - each(funcs); + // This is called once per element + $(this).as(Transitions) + .css(transition, oldTransitions) + .each(funcs); }}); return this; } + /** + * The transition() method allows you to create animation effects on any numeric HTML Attribute, + * CSS property, or color using CSS3 transformations and transitions. + * + * It works similar to animate() but has an extra parameter for delaying the animation. + * + * Example animate an element within 2 seconds: + * $("#foo") + * .transition("{ opacity: 0.1, scale: 2, x: 50, y: 50 }", 5000, EasingCurve.easeInBack, 2000); + * + */ public Transitions transition(Object stringOrProperties, int duration, String easing, int delay) { return transition(stringOrProperties, duration, EasingCurve.valueOf(easing), delay); } + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/TransitionsAnimation.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/TransitionsAnimation.java new file mode 100755 index 00000000..3d0479ea --- /dev/null +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/TransitionsAnimation.java @@ -0,0 +1,147 @@ +/* + * 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; + +import static com.google.gwt.query.client.GQuery.*; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.query.client.Function; +import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.js.JsObjectArray; +import com.google.gwt.query.client.plugins.effects.Fx.TransitFx; +import com.google.gwt.regexp.shared.MatchResult; + +/** + * Animation effects on any numeric CSS3 property or transformation + * using CSS3 transitions + */ +public class TransitionsAnimation extends PropertiesAnimation { + + public static Fx computeFxProp(Element e, String key, String val, boolean hidden) { + Transitions g = $(e).as(Transitions.Transitions); + String unit = ""; + if ("toggle".equals(val)) { + val = hidden ? "show" : "hide"; + } + + if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden) { + return null; + } + + if (hidden) { + g.show(); + } + + String cur = g.css(key, true); + String trsStart = cur, trsEnd = trsStart; + + if ("show".equals(val)) { + g.saveCssAttrs(key); + trsStart = "0"; + } else if ("hide".equals(val)) { + if (hidden) { + return null; + } + g.saveCssAttrs(key); + trsEnd = "0"; + } else { + MatchResult parts = REGEX_SYMBOL_NUMBER_UNIT.exec(val); + if (parts != null) { + unit = REGEX_NON_PIXEL_ATTRS.test(key) || Transitions.transformRegex.test(key) ? "" : "px"; + + String $1 = parts.getGroup(1); + String $2 = parts.getGroup(2); + String $3 = parts.getGroup(3); + trsEnd = "" + Double.parseDouble($2); + + if (unit.isEmpty() && $3 != null) { + unit = $3; + } + if (trsStart.isEmpty()) { + trsStart = "0"; + } + + if (!trsStart.endsWith(unit)) { + trsStart += unit; + } + + if ($1 != null && !$1.isEmpty()) { + double n = "-=".equals($1) ? -1 : 1; + double st = Double.parseDouble(trsStart); + double en = Double.parseDouble(trsEnd); + trsEnd = "" + (st + (n*en)); + } + } else { + trsStart = trsEnd = val; + } + } + return new TransitFx(key, val, trsStart, trsEnd, unit); + } + + private Transitions g; + + public TransitionsAnimation(Easing easing, Element elem, Properties p, Function... funcs) { + super(easing, elem, p, funcs); + g = $(e).as(Transitions.Transitions); + } + + private Properties getFxProperties(boolean isStart) { + Properties p = $$(); + for (int i = 0; i < effects.length(); i++) { + TransitFx fx = (TransitFx)effects.get(i); + p.set(fx.cssprop, (isStart ? fx.transitStart : fx.transitEnd) + fx.unit); + } + return p; + } + + @Override + public void onStart() { + effects = JsObjectArray.create(); + boolean resize = false; + boolean move = false; + boolean hidden = !g.isVisible(); + Fx fx; + for (String key : prps.keys()) { + String val = prps.getStr(key); + if ((fx = computeFxProp(e, key, val, hidden)) != null) { + effects.add(fx); + resize = resize || "height".equals(key) || "width".equals(key); + move = move || "top".equals(key) || "left".equals(key); + } + System.out.println(fx); + } + g.saveCssAttrs(ATTRS_TO_SAVE); + if (resize) { + g.css("overflow", "hidden"); + } + if (move && !g.css("position", true).matches("absolute|relative|fixed")) { + g.css("position", "relative"); + } + } + + @Override + public void run(int duration) { + onStart(); + Properties p = getFxProperties(true); + System.out.println(p.toJsonString()); + g.css(p); + p = getFxProperties(false); + System.out.println(p.toJsonString()); + g.transition(p, duration - 150, easing, 0, new Function(){public void f() { + onComplete(); + }}); + } +}